[gelöst] JPG Größe anpassen

Für Probleme bezüglich Grafik, Audio, GL, ACS, ...
Antworten
VB_Lazarus
Beiträge: 90
Registriert: Do 23. Dez 2010, 19:10
OS, Lazarus, FPC: Windows 10/11 32/64bit, L 2.2.0 32bit, FPC 3.2.2 32bit
CPU-Target: 32Bit

[gelöst] JPG Größe anpassen

Beitrag von VB_Lazarus »

Hallo,

ich habe folgendes Problem:

Ich habe eine Datenbank. In dieser Datenbank sind Informationen gespeichert.
Jede Information soll so eine Art kleines Bild besitzen.
Der Benutzer wählt erin Bild aus.
Das Bild (egal welche Größe) soll kopiert und auf eine bestimmte Größe reduziert werden.
Ich habe nichts (vielleicht die falsche Frage bei g**gle eingegeben) gefunden, wie ich ein Bild (jpg) on the fly in der Größe reduzieren kann.
Gibt es eine einfache Methode die Bildgröße (ohne Controls) entsprechend zu reduzieren?

Danke.
Zuletzt geändert von VB_Lazarus am So 31. Aug 2014, 12:04, insgesamt 1-mal geändert.

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: JPG Größe anpassen

Beitrag von theo »

Auf ein neues TBitmap oder TJPEGImage Stretchdrawen.
http://lazarus-ccr.sourceforge.net/docs ... hdraw.html

Z.B.

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var i:TJPEGImage;
begin
  i:=TJPEGImage.Create;
  i.SetSize(100,100);
  i.Canvas.StretchDraw(Rect(0,0,100,100),Image1.Picture.Jpeg);
  i.SaveToFile('/home/theo/test38.jpg');
  i.free;
end;


Könnte man noch proportional machen.

gocher
Beiträge: 298
Registriert: Di 23. Nov 2010, 23:41
OS, Lazarus, FPC: Ubuntu/Win, Lazarus trunk, FPC trunk
CPU-Target: 32Bit/64Bit
Wohnort: Geldern
Kontaktdaten:

Re: JPG Größe anpassen

Beitrag von gocher »

also bei mir klappt das mit g**gle
g**gle:) free pascal dynamisch skalierte bilder
bei dieser Abrage führt der 1.Treffer http://www.gocher.me/dynamic-scaled-images zu meiner Methode (ohne visuelle Komponenten), einfach ist dieser Weg allerdings nicht, aber sehr schnell!
Ich nutze diese Variante um auf meiner Homepage die Thumbnails zu generieren, bei JPGs nutze ich dafür auch das Vorschaubild falls vorhanden,
ich speichere die Bilder allerdings nicht, denn das ist nur Platzverschwendung und die Zeit zum auslesen der internen Vorschau ist zu vernachlässigen, dabei fällt mir auf, dass ich die Unit FPWriteGIF (enthält allerdings keine Lösung für animierte GIFs) noch veröffentlichen sollte die existiert in Free Pascal noch nicht. (ist nun bereits passiert!!)

sMimeType = 'image/jpeg', 'image/png', 'image/gif', 'image/bmp' ( 'image/bmp' wird automatisch nach 'image/jpeg' konvertiert)
bCrop (nie verzerren, bei bCrop beschneiden auf LWidth, LHeight, sonst einpassen)
das skalierte Bild liegt dann im MemoryStream, kann man dann speichern, muss man aber nicht

Code: Alles auswählen

  
uses ..., ImgUtils;
 
var MemoryStream: TMemoryStream;
...
  MemoryStream := TMemoryStream.Create;
  scaleImageToStream(AFilename, sMimeType, MemoryStream, LWidth, LHeight, bCrop);
...
 



g**gle:) free pascal bilder skalieren --> ... etliche Treffer zu deiner Frage
MfG Gocher
akt. Projekt: Webserver(HTTPS HTTP/2) mit integrierten CMS in Free Pascal - www.gocher.me

VB_Lazarus
Beiträge: 90
Registriert: Do 23. Dez 2010, 19:10
OS, Lazarus, FPC: Windows 10/11 32/64bit, L 2.2.0 32bit, FPC 3.2.2 32bit
CPU-Target: 32Bit

Re: JPG Größe anpassen

Beitrag von VB_Lazarus »

Hallo,

sorry, das ich mich so spät melde.

Danke an theo und gocher, für die beiden Lösungen.

Ich glaube ich suche meistens verkehrt (Lazarus + Frage).

Ich habe vorerst die Lösung von theo verwendet.

Gruß

ErnstVolker
Beiträge: 336
Registriert: Di 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: [gelöst] JPG Größe anpassen

Beitrag von ErnstVolker »

Guten Abend,
ich würde gerne "scaleImageToStream" von gocher benutzen um jpg's vor dem Einfügen in ein pdf (mit fpPDF) zu verkleinern.

Ich habe mal was zum Versuchen gebastelt:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var D: TPDFDocument; S: TPDFSection; P: TPDFPage; I: Integer;
  BildPfad, Bild: String; F: TFileStream; MemStream: TMemoryStream; ImgJPG: String;
begin
  D:= TPDFDocument.Create(Nil);

  if OpenPictureDialog1.Execute then begin
    BildPfad:= OpenPictureDialog1.FileName;
    Bild:= ExtractFileNameOnly(BildPfad);
    Memo1.Lines.Add(BildPfad);
    Memo1.Lines.Add(Bild);
    D.StartDocument;
    S:= D.Sections.AddSection;
    P:= D.Pages.AddPage;
    S.AddPage(P);
    P.PaperType:= ptA4;
    P.UnitOfMeasure:= uomMillimeters;
    
    MemStream:= TMemoryStream.Create;
    scaleImageToStream(BildPfad, ImgJPG, MemStream, 40, 20, false);
    
    I:= D.Images.AddFromStream(MemStream, ImgJPG, false);
    P.DrawImage(20,250,40,20,I);
    
    F:= TFileStream.Create('ErstesTestPDF.pdf',fmCreate);
    D.SaveToStream(F);
    F.Free;
    D.Free;
  end;
end; 
Es kommt die Meldung:

unit1.pas(53,49) Error: Incompatible type for arg no. 2: Got "AnsiString", expected "TFPCustomImageReaderClass"

Darf man bei scaleImageToStream als zweiten Parameter eine String-Variable (ImgJPG) übergeben?

Was muß ich als zweiten Parameter bei AddFromStream übergeben?

Vielen Dank für Eure Hilfe

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: [gelöst] JPG Größe anpassen

Beitrag von theo »

ErnstVolker hat geschrieben:
Di 17. Okt 2023, 22:34
Was muß ich als zweiten Parameter bei AddFromStream übergeben?
Wahrscheinlich einen Reader wie hier beschrieben:
https://wiki.freepascal.org/fcl-image#R ... image_file
Vermutlich eine TFPReaderJPEG Instanz.

Benutzeravatar
Ally
Beiträge: 263
Registriert: Do 11. Jun 2009, 09:25
OS, Lazarus, FPC: Win und Lazarus Stable release
CPU-Target: x64

Re: [gelöst] JPG Größe anpassen

Beitrag von Ally »

Anbei ein Beispielprogramm das die Unit rhsBitmapScale.pas verwendet und Bilder in guter Qualität skaliert.
Dateianhänge
BitmapScale.zip
(43.86 KiB) 38-mal heruntergeladen

ErnstVolker
Beiträge: 336
Registriert: Di 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: [gelöst] JPG Größe anpassen

Beitrag von ErnstVolker »

Hallo Theo,

vielen Dank für den Tipp mit dem TFPReaderJPEG. Damit kann man AddFromStream ausführen. Das funktioniert sehr gut wenn man die Funktion "scaleImageToStream" weglässt und den Memorystream mit LoadFromFile "befüllt".

Wenn ich "scaleImageToStream" aufrufe kommt eine Debuggerausnahmen-Nachricht, dass mein Projekt die Exception-Klasse FPImageException ausgelöst hat. Die Meldung lautet: "Wrong image format".

Die zu ladende Datei ist ein JPEG mit der Endung jpg. Ich übergebe der Funktion eine Stringvariable MimeType:= 'image/jpeg';

Was mache ich hier falsch bzw. wie ist diese Funktion aufzurufen?

Vielen Dank

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: [gelöst] JPG Größe anpassen

Beitrag von theo »

Keine Ahnung, der Code ist von Gocher.
Vielleicht ist dein Bild wirklich nicht in Ordnung. Hast du mal ein anderes JPEG probiert?
Sonst könntest du noch prüfen, was ein TFPCustomImage denn vorschlägt:

Code: Alles auswählen

var
  image: TFPCustomImage;
  aRd: TFPCustomImageReaderClass;
.... etc. etc.
    aRd := image.FindReaderFromStream(AFileStream);
    ShowMessage(ARd.ClassName);    

ErnstVolker
Beiträge: 336
Registriert: Di 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: [gelöst] JPG Größe anpassen

Beitrag von ErnstVolker »

Hallo Theo,

das Bild/die Bilder sind in Ordnung. Kann sie ja auch mit IrfanView öffnen. Wenn ich das Spiel mit PNG's mache kommt auch die Meldung.

Dein Vorschlag aus dem Stream den Reader zu erkennen funktioniert. Da wird der "TFPReaderJPEG" ausgegeben.

Ohne die Skalierungsfunktion von gocher funktioniert es. Die hätte halt den Vorteil mal eben 120 Bilder zu verkleinern und im pdf zu platzieren.

Vielen Dank auch Dir, Ally! Mit Deinem Prgramm habe ich das "Testbild" in unterschiedliche Größen gebracht um zu sehen was bei hinreichender Auflösung eine geringer PDF-Größe akzeptabel erscheinen lässt.

Meine "Vorgabedatei" (mit Excel erzeugt) hat 18 Seiten mit 81 Bildern und dabei nur 3,2 MB. Da will ich hin.

Vielleicht liest ja gocher hier mit.

Viele Grüße und schönen Abend!
Volker

wp_xyz
Beiträge: 4889
Registriert: Fr 8. Apr 2011, 09:01

Re: [gelöst] JPG Größe anpassen

Beitrag von wp_xyz »

Das ist das generelle Problem, wenn man mehrere Operationen am selben Stream ausführt:

In ScaleImageToStream gibt es keine Anweisung wie "MemoryStream.Position := 0", das heißt, der Stream steht beim Verlassen dieser Routine am Ende, hinter den Bilddaten. Wenn der nachfolgende Code nun den Stream nicht selbst wieder an den Anfang setzt, wird versucht, Daten hinter dem Stream-Ende zu verarbeiten, was nicht gut geht.

Daher nach ScaleImageToStream einfach "MemStream := 0" aufrufen.

Der folgende Code, basierend auf deinem, aber alles mit pdf entfernt, funktioniert einwandfrei:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var
  BildPfad, Bild: String;
  MemStream: TMemoryStream;
  ImgJPG: String;
begin
  BildPfad := 'irgendein_jpeg_foto.jpg';
  Bild:= ExtractFileNameOnly(BildPfad);
  MemStream:= TMemoryStream.Create;
  scaleImageToStream(BildPfad, ImgJPG, MemStream, 40, 20, false);
  MemStream.Position := 0;              // <---- Stream wieder an den Anfang setzen
  Image1.Picture.LoadFromStream(MemStream);
  MemStream.Position := 0;             // <----- Stream wieder an den Anfang setzen
  MemStream.SaveToFile(ChangeFileExt(Bild, '') + '-klein.jpg');
  MemStream.Free;
end; 
Eine Beschleunigung für jpeg-Bilder ohne Thumbnail im EXIF wüsste ich noch: Nachdem die Größe des original-Bildes ermittelt worden ist, könnte man das Scale des FPReaderJPEG je nachdem auf jsHalf, jsQuarter oder jsEighth setzen und damit nur den entsprechenden Bruchteil der Bilddaten einlesen, was entsprechend schneller abläuft als das Einlesen des vollen Bildes (jsFullSize).

ErnstVolker
Beiträge: 336
Registriert: Di 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: [gelöst] JPG Größe anpassen

Beitrag von ErnstVolker »

Hallo wp_xyz,

vielen lieben Dank! Die Position wieder auf "0" setzen war es wieso es bei mir nicht ging. Jetzt funzt es.

Noch einen schönen Abend!

Antworten