Autor Beitrag
jackie05
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 357



BeitragVerfasst: Fr 14.06.13 22:07 
Hallo,
ich habe ein Problem beim verkleinern von sehr große JPEG Dateien z.B. von (3872x2592) auf (272x272) Pixel, alles klappt zwar, nur ist es dann stark verpixelt, wenn ich es verkleiner.

Hier ist mal der Code:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
function ResizeJPEG(jpeg: TJpegImage; width, height: integer): TJpegImage;
var
  bmp:TBitmap;
begin
  try
    bmp:=TBitmap.Create;
    try
      bmp.width:=width;
      bmp.height:=height;

      bmp.canvas.StretchDraw(Rect(0,0,bmp.width,bmp.height),jpeg);
      jpeg.assign(bmp);
    finally
      bmp.free;
    end;
    jpeg.CompressionQuality := 100;
    jpeg.Compress;
    result := jpeg;
  finally

  end;
end;

procedure SavePNG(name: string; width: integer; height: integer);
var
  JPG:TJPEGImage;
  BMP:TBitmap;
  PNG:TPNGImage;
begin
  JPG:= TJPEGImage.Create;
  BMP:= TBitmap.Create;
  PNG:= TPngImage.Create;
  JPG.LoadFromFile('img/'+name);
  JPG := ResizeJPEG(JPG, width, height);
  //JPG.SaveToFile('img/'+name);
  BMP.Assign(JPG);
  PNG.Assign(BMP);
  PNG.SaveToFile(ChangeFileExt('img/'+name,'.png'));
end;


Wie kann ich TJpegImage so einstellen, das es noch weich gezeichnet wird?
Weil das Bild stark verpixelt ist, nachdem ich es verkleinert habe.

Ich bedanke mich schonmal im Voraus.

MfG
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 14.06.13 22:17 
Dafür kannst du nach smooth resize suchen:
www.swissdelphicente...showcode.php?id=1896
jackie05 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 357



BeitragVerfasst: Fr 14.06.13 23:21 
Ich danke Dir.

Das klappt irgendwie nicht.

Kann ich nicht irgendwie mein Code ausbessern um eine gute Qualität zu erzielen?

MfG
MeierZwoo
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 94
Erhaltene Danke: 11

Win 7, DOS5
Delphi 2007 Architect, BP7/TP5, LISP, PS
BeitragVerfasst: Sa 15.06.13 02:39 
Grundsätzlich sollte es beim VERKLEINERN keine Artefakte geben - das passiert normal nur beim vergrößern.

Was ich nicht ganz verstehe, ist, weshalb Du erst auf eine BitMap zeichnest, dann aber der JPG die BitMap zuweist und dann die BitMap "wegwirfst" statt mit der BitMap weiter zu arbeiten. Dein Verpixeln entsteht wohl gerade an dieser Stelle, der Zuweisung einer BitMap an eine JPG. Dem Programm und auch dem Speicher und auch der Ausgabe ist es völlig egal, da beim Zeichnen eh eine BitMap gezeichnet wird, also die JPG wieder in RAW-Daten umgerechnet wird - denn eine JPG, GIF ... kann der Bildschirm (oder ein anderes pixelorientiertes Ausgabegerät) eh nicht darstellen.
jackie05 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 357



BeitragVerfasst: Sa 15.06.13 20:07 
Ich danke Dir.

Ich möchte ja eine JPEG Datei laden und diese verkleinern, anschließend möchte ich es dann als PNG speichern.

Wenn ich Bitmap entferne und nur mit JPEG und PNG arbeite:
ausblenden Delphi-Quelltext
1:
2:
PNG.Assign(JPG);
PNG.SaveToFile(ChangeFileExt('img/'+name,'.png'));

dann bekomme ich folgende fehlermeldung:
ausblenden Delphi-Quelltext
1:
TJPEGImage kann nicht zu TPNGImage zugewiesen werden.					


Wie könnte ich das anders lösen?

MfG
MeierZwoo
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 94
Erhaltene Danke: 11

Win 7, DOS5
Delphi 2007 Architect, BP7/TP5, LISP, PS
BeitragVerfasst: Sa 15.06.13 20:19 
Nochmal: Wieso entfernst Du denn die BitMap? Und wieso speicherst Du nicht die BitMap als PNG?

Es ist doch vollkommen egal, was für einen Grafiktyp Du lädst und als was Du speichern willst, das interne "Arbeits-Rohformat" (RAW) ist immer BitMap - von diesem Rohformat kann alles andere hergestellt werden. (Alternativ auch TIFF, weil TIFF nur ein encodetes Rohformat ist, welches durch decoden direkt wieder ins ursprüngliche Rohformat zurückgeführt werden kann und deshalb z.B. für Datenübertragung (z.B. zum Drucker) intern benutzt wird.)

Nachtrag:
Was ich auch nicht ganz verstehe, wieso man JPG läd um sie als PNG zu speichern.
a) Wenn man skalierbare Grafiken haben möchte. speichert man GLEICH als PNG (oder TIFF) und nicht als JPG - JPG ist als ENDformat gedacht und nicht zum weiteren skalieren, im Gegensatz zu PNG, welches zum skalieren gedacht ist.
b) macht man das nicht mit einem eigenen Tool, sondern benutzt fertige Tools, z.B. Irfan, die auch Batchbetrieb anbieten.
jackie05 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 357



BeitragVerfasst: Sa 15.06.13 20:30 
Danke Dir.

Das habe ich auch versucht, aber trotzdem ist das Bild dann verpixelt, wie es im anhang zusehen ist.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
bmp.width:=width;
bmp.height:=height;

bmp.canvas.StretchDraw(Rect(0,0,bmp.width,bmp.height),jpeg);
png.Assign(bmp);
png.SaveToFile('test.png');


Woran könnte es liegen?

MfG
Einloggen, um Attachments anzusehen!
MeierZwoo
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 94
Erhaltene Danke: 11

Win 7, DOS5
Delphi 2007 Architect, BP7/TP5, LISP, PS
BeitragVerfasst: Sa 15.06.13 21:06 
LOL, also im Anhang kann man garnichts erkennen, selbst mit Lupe nicht - und da der Ursprung nicht bekannt ist, kann man auch nichts über verpixelt oder so aussagen.

Im allgemeinen wird überall berichtet, daß StretchDraw wohl allgemein eine Sauqualität abliefert. Ich selbst kann dazu nichts sagen, da ich es vermeide und Images VORHER auf Ausgabegröße anpasse bzw. wenn, nur Strich-Images damit skaliere (keine Graustufen, keine Farbe ..).

Aber eine Suche nach stretchdraw in den einschlägigen Delphi-Foren (auch hier) liefert genug Ergebnisse im Bezug auf die miese Qualität von stretchdraw. In den meisten Fällen wird auf Routinen von
graphics32.org/wiki//Main/HomePage
verwiesen.
WasWeißDennIch
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: Sa 15.06.13 21:53 
Wenn man statt TCanvas.StretchDraw StretchBlt verwendet und vorher ggf. noch mit SetStretchBltMode den Modus umschaltet, bekommt man auch oft schon recht brauchbare Ergebnisse. Beispielcode findet sich z.B. hier: www.delphipraxis.net/1095307-post20.html
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Sa 15.06.13 22:14 
Folgender Code funktioniert sehr gut:

www.delphidabbler.com/tips/99
Note: to test this code you need to drop a TButton and a TOpenPictureDialog on a form and add the JPEG unit to the uses statement.

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, JPEG, StdCtrls, ExtDlgs;

type
  TForm1 = class(TForm)
    OpenPictureDialog1: TOpenPictureDialog;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  bmp: TBitmap;
  jpg: TJpegImage;
  scale: Double;
begin
  if OpenPictureDialog1.execute then
  begin
    jpg := TJpegImage.Create;
    try
      jpg.Loadfromfile(OpenPictureDialog1.filename);
      if jpg.Height > jpg.Width then
        scale := 500 / jpg.Height  //org 50
      else
        scale := 500 / jpg.Width;  //org 50
      bmp := TBitmap.Create;
      try
        {Create thumbnail bitmap, keep pictures aspect ratio}
        bmp.Width := Round(jpg.Width * scale);
        bmp.Height:= Round(jpg.Height * scale);
        bmp.Canvas.StretchDraw(bmp.Canvas.Cliprect, jpg);
        {Draw thumbnail as control}
        Self.Canvas.Draw(10010, bmp);
        {Convert back to JPEG and save to file}
        jpg.Assign(bmp);
        jpg.SaveToFile(
          ChangeFileext(OpenPictureDialog1.filename, '_thumb.JPG'));
      finally
        bmp.free;
      end;
    finally
      jpg.free;
    end;
  end;
end;

end.


Zuletzt bearbeitet von hathor am Do 24.07.14 07:45, insgesamt 1-mal bearbeitet
bummi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1248
Erhaltene Danke: 187

XP - Server 2008R2
D2 - Delphi XE
BeitragVerfasst: Sa 15.06.13 22:26 
Wenn GDI+ eine Option für Dich ist, hier gibt es diverse Filter für das Scalieren.

_________________
Das Problem liegt üblicherweise zwischen den Ohren H₂♂
DRY DRY KISS
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: So 16.06.13 08:16