Zmniejszanie obrazu w formacie *.PNG

0

Witam,

bezskutecznie próbuje zmniejszyć obraz w formacie *.PNG za pomocą StretchDraw...

próbowałem tak:

var
  png,png2: tpngobject;
begin
png := tpngobject.Create;
png.loadfromfile('C:\1.png');

png2 := tpngobject.Create;

png2.Canvas.StretchDraw(rect(0,0,50,50),png);

form1.Canvas.Draw(0,0,png);
end;

to wyskakuje błąd "canvas does not allow drawing"

próbowałem również tak:

begin
png := tpngobject.Create;
png.loadfromfile('C:\1.png');

png2 := tpngobject.Create;
png2.loadfromfile('C:\1.png');

png2.Canvas.StretchDraw(rect(0,0,50,50),png);

form1.Canvas.Draw(0,0,png2);
end;

ale wyświetla się tylko jeden obraz (na png2 powinny wyświetlić się 2 obrazy - jeden na drugim)

pierwszy błąd jest jeszcze do zrozumienia, ale czemu 2 procedura nie działa prawidłowo ?

oczywiście pierwszy obraz jest większy niż drugi.

0

A nie możesz użyć po prostu pomocniczych bitmap? Np:

var
  Png1,Png2: Tpngobject;
  Bitmap1, Bitmap2: TBitmap;

begin
 Bitmap1:=TBitmap.Create;
 Bitmap2:=TBitmap.Create;
 Png1:=TPngobject.Create;
 Png2:=TPngobject.Create;
 try
   Png1.LoadFromFile('C:\1.png');
   Bitmap1.Assign(Png1);
   Png2.LoadFromFile('C:\2.png');
   Bitmap2.Assign(Png2);
   Bitmap1.Canvas.StretchDraw(rect(0,0,50,50), Bitmap2);
   Form1.Canvas.Draw(0, 0, Bitmap1);
 finally
   Bitmap1.Free;
   Bitmap2.Free;
   Png1.Free;
   Png2.Free;
 end;
end;

Pzdr.
Marogo

0

Wszystko byłoby dobrze, gdyby nie to, że w przezroczystych miejscach obrazka PNG pojawia się biało tło z bitmapy.

chyba nawet próbowałem już w ten sposób :)
w każdym razie dzięki za dobre chęci

0

bo ten komponent ma takie ustaienia jak set size inny scanline bo jeszcze z alpha
ale najlatwiej jeszcze wrzucic na nowa bitmape kanal 4

0

A to?:

procedure SmoothResize(apng:tpngobject; NuWidth,NuHeight:integer);
var
  xscale, yscale         : Single;
  sfrom_y, sfrom_x       : Single;
  ifrom_y, ifrom_x       : Integer;
  to_y, to_x             : Integer;
  weight_x, weight_y     : array[0..1] of Single;
  weight                 : Single;
  new_red, new_green     : Integer;
  new_blue, new_alpha    : Integer;
  new_colortype          : Integer;
  total_red, total_green : Single;
  total_blue, total_alpha: Single;
  IsAlpha                : Boolean;
  ix, iy                 : Integer;
  bTmp : TPNGObject;
  sli, slo : pRGBLine;
  ali, alo: pbytearray;
begin
  if not (apng.Header.ColorType in [COLOR_RGBALPHA, COLOR_RGB]) then
    raise Exception.Create('Only COLOR_RGBALPHA and COLOR_RGB formats' +
    ' are supported');
  IsAlpha := apng.Header.ColorType in [COLOR_RGBALPHA];
  if IsAlpha then new_colortype := COLOR_RGBALPHA else
    new_colortype := COLOR_RGB;
  bTmp := Tpngobject.CreateBlank(new_colortype, 8, NuWidth, NuHeight);
  xscale := bTmp.Width / (apng.Width-1);
  yscale := bTmp.Height / (apng.Height-1);
  for to_y := 0 to bTmp.Height-1 do begin
    sfrom_y := to_y / yscale;
    ifrom_y := Trunc(sfrom_y);
    weight_y[1] := sfrom_y - ifrom_y;
    weight_y[0] := 1 - weight_y[1];
    for to_x := 0 to bTmp.Width-1 do begin
      sfrom_x := to_x / xscale;
      ifrom_x := Trunc(sfrom_x);
      weight_x[1] := sfrom_x - ifrom_x;
      weight_x[0] := 1 - weight_x[1];

      total_red   := 0.0;
      total_green := 0.0;
      total_blue  := 0.0;
      total_alpha  := 0.0;
      for ix := 0 to 1 do begin
        for iy := 0 to 1 do begin
          sli := apng.Scanline[ifrom_y + iy];
          if IsAlpha then ali := apng.AlphaScanline[ifrom_y + iy];
          new_red := sli[ifrom_x + ix].rgbtRed;
          new_green := sli[ifrom_x + ix].rgbtGreen;
          new_blue := sli[ifrom_x + ix].rgbtBlue;
          if IsAlpha then new_alpha := ali[ifrom_x + ix];
          weight := weight_x[ix] * weight_y[iy];
          total_red   := total_red   + new_red   * weight;
          total_green := total_green + new_green * weight;
          total_blue  := total_blue  + new_blue  * weight;
          if IsAlpha then total_alpha  := total_alpha  + new_alpha  * weight;
        end;
      end;
      slo := bTmp.ScanLine[to_y];
      if IsAlpha then alo := bTmp.AlphaScanLine[to_y];
      slo[to_x].rgbtRed := Round(total_red);
      slo[to_x].rgbtGreen := Round(total_green);
      slo[to_x].rgbtBlue := Round(total_blue);
      if isAlpha then alo[to_x] := Round(total_alpha);
    end;
  end;
  apng.Assign(bTmp);
  bTmp.Free;
end;
0

Ta procedura wywala access violation.

Coś jest nie tak z nowym plikiem png.

bo taki kod:

btmp.savetofile('aa.png');
apng.loadfromfile('aa.png');

wywala to samo.

0

Jeżeli tworzysz ten obiekt przed użyciem, nie ma prawa wywalać AV.

Najlepiej będzie gdy wrzucisz tu swój kod, zacznając od tworzenia i ładowania po wywołanie tej funkcji.

0

Rzeczywiście błąd tkwił w innym miejscu: w innej procedurze dalej miałem stare wymiary obrazu i dlatego sie sypało :)

Wielkie dzięki za pomoc.

1 użytkowników online, w tym zalogowanych: 0, gości: 1