Question

Dans Delphi 7, j'ai une bibliothèque qui utilise le composant TCanvas pour générer des informations. L’image résultante fait environ 4800 * 6000 pixels et je souhaite l’imprimer et la sauvegarder au format .jpeg .

Pour ce faire, j'ai créé un TBitmap et lui ai donné son canevas en tant que paramètre, puis j'ai affecté le bitmap au jpeg. Apparemment, cela prend trop de mémoire, car je reçois une exception lorsque j'essaie de définir la largeur et la hauteur du bitmap, en disant "Il n'y a pas assez de mémoire disponible pour traiter cette commande".

// output to printer
Printer.BeginDoc();
doPrint(Printer.Canvas);
Printer.EndDoc();

// output in bmp.Canvas
bmp := TBitmap.Create;
bmp.Width := Printer.PageWidth;
bmp.Height := Printer.PageHeight; // <- BAM! Exception!
doPrint(bmp.Canvas);

// save as jpeg
jpg := TJPEGImage.Create;
jpg.Assign(bmp);
jpg.SaveToFile('...');

// free
bmp.Free();
jpg.Free();

Qu'est-ce que je fais mal? Puis-je enregistrer Printer.Canvas directement sous un fichier .jpeg ?

Édition: approximation mise à jour de la taille de l'image de 2000 * 2000 à 4800 * 6000

Était-ce utile?

La solution

vous devriez pouvoir traiter des images bitmap volumineuses à l'aide de TBitmap32 à partir de Graphic32 ( http://www.graphics32.org / wiki / )

Autres conseils

Vous devez définir le format de pixel du bmp sur quelque chose avant de le redimensionner, comme le suggère Ben Ziegler. Cela fait toute la différence.

Cette erreur se produit si vous définissez la taille du bitmap sur une taille supérieure à celle de votre bureau. Pour éviter cette erreur, vous pouvez créer une image bitmap indépendante du périphérique de la manière suivante:

bmp := TBitmap.Create;
bmp.HandleType := bmDIB;
bmp.Width := Printer.PageWidth;
bmp.Height := Printer.PageHeight; 

Que vous ayez besoin de cette solution dépend des capacités de votre carte vidéo. Nous avons souvent eu cette erreur dans des situations de serveur terminal où peu de RAM vidéo était allouée à une session. En utilisant cette solution, vous obligez Delphi à utiliser la RAM normale pour votre bitmap au lieu de la mémoire sur votre carte vidéo.

La classe TBitmap de Delphi rencontre des problèmes pour gérer des bitmaps aussi volumineux. Et non, vous ne pouvez pas enregistrer un TCanvas directement dans un fichier .jpg.

J'ai essayé le code suivant sur ma machine (Windows XP, Delphi 2006) et je n'ai reçu aucune exception. Quel système d'exploitation utilisez-vous?

  procedure TForm3.Button3Click(Sender: TObject);
  var
     bmp : TBitmap;
  begin
     bmp := TBitmap.Create;
     bmp.PixelFormat := pf32bit;
     bmp.Width := 6000;
     bmp.Height := 4800;
     bmp.Free;
  end;
Comme le disait mghie: Cela dépend beaucoup de votre système voir laboratoire informatique EFG sur de grandes images bitmap

Essayez de régler PixelFormat sur pf32bit ou pf24bit (comme dans l'exemple de Ben Ziegler), dans la plupart des cas, ce PixelFormat fait l'affaire (comme je me souviens, c'était principalement sous XP). Vous pouvez trouver plus d'informations ici .

Ce n'est pas le format JPEG: la spécification autorise les bitmaps de 32767x32767 pixels.

Le problème est l’énorme consommation en mémoire des gros bitmaps, et des limites de TCanvas qui peuvent finalement être retracées jusqu’à la plate-forme Windows.

Ma bibliothèque NativeJpg décode le traitement JPEG séparément de la visualisation. Vous pouvez par exemple enregistrez un tel fichier JPEG en utilisant "bande par bande", avec pour résultat des carreaux bitmap plus faciles à gérer.

NativeJpg est open-source et vous pouvez télécharger cette lib ici: http://www.simdesign.nl/forum/viewforum.php?f=16

Regardez le mosaïque pour savoir comment créer et enregistrer d’énormes images JPEG artificielles.

Cordialement, Nils

Pour utiliser moins de mémoire, vous pouvez toujours essayer de créer des bitmaps plus petites. Supposons que vous divisiez la hauteur de l’imprimante par 10 ou définissiez une hauteur maximale de 1 000. Juste une suggestion, vous ne savez pas si elle est applicable dans votre cas. Il en résulte plus d'une image par page.

Je ne sais pas si cela fonctionnera ou aidera. Mais nous avons créé une fonction qui enregistrera un composant sur un fichier jpeg:

    function SaveComponentToJPeg(mControl: TWinControl): TJpegImage;
    var
      bmp: TPicture;
      jpg : TJpegImage;
      dc: HDC;
      wnd: HWND;
      Params: array[0..255] of Char;

    begin
      bmp:=TPicture.Create;
      jpg := TJpegImage.create;
      try
        bmp.Bitmap.Width  := mControl.Width  - 05;  // Deduct for border.
        bmp.Bitmap.Height := mControl.Height -05;  // Deduct for border.
        wnd               := mControl.Handle;  //ctiveWindow;
        dc                := GetDc(wnd);
        BitBlt(bmp.Bitmap.Canvas.Handle,0,0,bmp.Width,bmp.Height,dc,0,0,SrcCopy);
        ReleaseDc(wnd, dc);
        jpg.assign(bmp.bitmap);
        result := jpg
      finally
        bmp.Free;
      end;
    end;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top