Verarbeitung große Bilder mit Delphi für das Speichern als JPEG-
-
08-07-2019 - |
Frage
In Delphi 7 habe ich eine Bibliothek, die das TCanvas Komponente zur Ausgabe einiger Informationen verwendet. Das resultierende Bild ist etwa 4800 * 6000 Pixel und ich würde es drucken mag und es als .jpeg
speichern.
Um dies zu erreichen, habe ich eine TBitmap und gab seine Leinwand als Parameter in die Bibliothek und dann zugewiesen ich die Bitmap in den JPEG. Offenbar ist dies zu viel Speicher zu nehmen, weil ich eine Ausnahme bin immer beim Versuch, die Bitmap-Breite und Höhe zu setzen, sagen „nicht genügend Speicher diesen Befehl zu verarbeiten verfügbar ist.“
// 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();
Was mache ich falsch? Könnte ich Printer.Canvas direkt als .jpeg
Datei speichern?
Edit: Aktualisierte Bildgröße Annäherung von 2000 * 2000-4800 * 6000
Lösung
Sie sollten große Bitmaps TBitmap32 von Graphic32 ( verarbeiten können http://www.graphics32.org / wiki / )
Andere Tipps
Sie sollten das Pixelformat für die bmp auf etwas setzen, bevor die bmp taxieren, wie Ben Ziegler schlägt. Das macht den Unterschied aus.
Dieser Fehler tritt auf, wenn Sie die Größe der Bitmap, um etwas größer als te Größe von Ihnen Desktop eingestellt. Um diesen Fehler zu vermeiden, können Sie einen Device Independent Bitmap in der folgenden Art und Weise erstellen:
bmp := TBitmap.Create;
bmp.HandleType := bmDIB;
bmp.Width := Printer.PageWidth;
bmp.Height := Printer.PageHeight;
Ob Sie diese Lösung auf die Fähigkeiten Ihrer Grafikkarte abhängt. Wir hatten diesen Fehler viel in Terminal-Server-Situationen, in denen nicht viel Video-RAM auf eine Sitzung zugewiesen wurde. diese Lösung verwenden Sie Delphi zwingen normalen RAM für Ihre Bitmap auf der Grafikkarte statt Speicher zu verwenden.
Delphi TBitmap Klasse hat Probleme, große Bitmaps Handhabung. Und nein, man kann nicht eine TCanvas direkt auf eine JPG-Datei speichern.
Ich habe versucht, den folgenden Code auf meinem Rechner (Windows XP, Delphi 2006) und erhielt keine Ausnahmen. Welches Betriebssystem verwenden Sie?
procedure TForm3.Button3Click(Sender: TObject);
var
bmp : TBitmap;
begin
bmp := TBitmap.Create;
bmp.PixelFormat := pf32bit;
bmp.Width := 6000;
bmp.Height := 4800;
bmp.Free;
end;
Wie mghie sagte: Es hängt viel von Ihrem System finden Sie unter EFGS Computerlabor auf große Bitmaps
Versuchen Pixelformat pf32bit oder pf24bit (wie im Beispiel von Ben Ziegler) zu setzen, in den meisten Fällen dieses Pixelformat den Trick funktioniert (wie ich mich erinnere, war es vor allem auf XP). Sie können weitere Informationen finden hier .
Es ist nicht das JPEG-Format: die Spezifikation erlaubt Bitmaps so groß wie 32767x32767 Pixel
.Das Problem ist der große mem Verbrauch von großen Bitmaps, und die TCanvas Grenzen, die letztlich auf die Windows-Plattform aufgespürt werden können.
Meine NativeJpg Bibliothek decodiert die JPEG-Verarbeitung von der Visualisierung getrennt, und Sie können zum Beispiel Speichern eines solchen JPEG mit „Streifen für Streifen“, mit überschaubarer Bitmap-Fliesen als Ergebnis.
NativeJpg ist Open-Source und Sie können diese lib hier herunterladen: http://www.simdesign.nl/forum/viewforum.php?f=16
Sehen Sie sich die tiledemo zu sehen, wie riesige künstliche JPEG-Bilder erstellen und speichern.
Mit freundlichen Grüßen Nils
weniger Speicher verbrauchen, können Sie immer versuchen, kleinere Bitmaps erstellen. können sagen Sie den Drucker Höhe von 10 unterteilen, oder eine maximale Höhe bis 1000. Nur ein Vorschlag festgelegt, nicht sicher, ob es in Ihrem Fall anwendbar ist. Es führt mehr als ein Bild pro Seite.
Nicht sicher, ob dies funktionieren wird oder Hilfe. Aber haben wir eine Funktion, die eine Komponente zu einem JPEG speichern wird:
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;