AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Bitmap shrinken

Ein Thema von bernhard_LA · begonnen am 8. Jan 2013 · letzter Beitrag vom 9. Jan 2013
 
bernhard_LA

Registriert seit: 8. Jun 2009
Ort: Bayern
1.124 Beiträge
 
Delphi 11 Alexandria
 
#1

Bitmap shrinken

  Alt 8. Jan 2013, 11:14
ich möchte mit folgendem Code eine Bitmap in der Größe möglichst verlustfrei reduzieren

Delphi-Quellcode:

Function SmartShrinkBitmap0(PBitmap: TBitMap; Scale: Double): Boolean;
var
  Out_X, Out_Y: Integer;
  Source_X, Source_Y: Integer;
  ScanImageBox: TRect;
  ShrinkImageLine: PByteArray;
  SourceImageLine: PByteArray;
  ScaleF: Double;
  PixCount: Integer;
  Local_Red, Local_Green, Local_Blue: Integer;
  Local_Scr_X, local_dest_X: Integer;
  SourceBitmap: TBitMap;
begin
  Result := False;

  // no work to to ....
  if not assigned(PBitmap) or (Scale > 1) or (Scale < 0) or (PBitmap.Width < 2)
    or (PBitmap.Height < 2) then
    exit;

  if Scale = 1 then
  begin
    exit;
  end;

  if Scale = 0 then
  begin
    PBitmap.Width := 0;
    PBitmap.Height := 0;
    exit;
  end;

  ScaleF := 1 / Scale;

  // Daten von PBitMap in new SourceBitmap Kopieren
  SourceBitmap := TBitMap.Create;
  SourceBitmap.PixelFormat := pf24bit;
  SourceBitmap.Assign(PBitmap);

  // set values for new out bitmap
  PBitmap.Width := round(SourceBitmap.Width * Scale);
  PBitmap.Height := round(SourceBitmap.Height * Scale);
  PBitmap.PixelFormat := pf24bit;

  try // try...finally
    try // try...except
      // for each pixel in new OutBitmap do...
      for Out_Y := 0 to PBitmap.Height - 1 do
      begin
        ShrinkImageLine := PBitmap.Scanline[Out_Y];
        for Out_X := 0 to PBitmap.Width - 1 do
        begin
          ScanImageBox.Left := trunc(Out_X * ScaleF);
          ScanImageBox.Top := trunc(Out_Y * ScaleF);
          ScanImageBox.Right := trunc((Out_X + 1) * ScaleF);
          ScanImageBox.Bottom := trunc((Out_Y + 1) * ScaleF);
          Local_Red := 0;
          Local_Green := 0;
          Local_Blue := 0;
          PixCount := 0;
          for Source_Y := ScanImageBox.Top to ScanImageBox.Bottom - 1 do
          begin
            SourceImageLine := SourceBitmap.Scanline[Source_Y];
            for Source_X := ScanImageBox.Left to ScanImageBox.Right - 1 do
            begin
            /// hier entsteht die AV ???

              [B]
              Local_Scr_X := Source_X * 3;
              inc(Local_Red, SourceImageLine[Local_Scr_X]);
              [/B]
              inc(Local_Green, SourceImageLine[Local_Scr_X + 1]);
              inc(Local_Blue, SourceImageLine[Local_Scr_X + 2]);
              inc(PixCount);
            end;
          end;
          local_dest_X := Out_X * 3;
          If local_dest_X > 32000 then
            Raise Exception.CreateFmt('Variable LDX to high ...(%d)', [local_dest_X]);
          // Raise Exception.Create ('Variable LDX to high ...('+ inttostr (LDX)+')');
          ShrinkImageLine[local_dest_X] := Local_Red div PixCount;
          ShrinkImageLine[local_dest_X + 1] := Local_Green div PixCount;
          ShrinkImageLine[local_dest_X + 2] := Local_Blue div PixCount;
        end;
      end;

      Result := True;

    except
      // If the code produces an Exception ....
      on E: Exception do
        // {--Only for debuging reasons }

        ShowMessageFmt(E.ClassName + ' error raised, with message : ' +
          E.Message + #13#10 + 'Variables values:' + #13#10 +
          ' out_X=' + Inttostr(Out_X) + ', ' + ' out_Y=' + Inttostr(Out_Y) + #13#10 +
          ' src_x=' + Inttostr(Source_X) + ', ' + ' src_Y=' + Inttostr(Source_Y) + #13#10 +
          ' ScanBOX.TOP=' + Inttostr(ScanImageBox.TOP) + #13#10 +
          ' ScanBOX.LEFT=' + Inttostr(ScanImageBox.LEFT) + #13#10 +
          ' ScanBOX.RIGHT=' + Inttostr(ScanImageBox.Right) + #13#10 +
          ' ScanBOX.BOTTOM=' + Inttostr(ScanImageBox.Bottom) + #13#10 +
          ' LDX=' + Inttostr(local_dest_X) + #13#10 +
          ' LSX=' + Inttostr(Local_Scr_X) + #13#10 +
          ' PBitmap=%p, OutBitmap=%p' + ' DLine=%p, Dimensions='  + #13#10 +
          ' Inbmp Size ' + Inttostr(SourceBitmap.Height) + 'x' + Inttostr(SourceBitmap.Width)+ ' pixel' + #13#10 +
          ' Outbmp Size ' + Inttostr(PBitmap.Height) + 'x' + Inttostr(PBitmap.Width)+ ' pixel' + #13#10 +
          ' Scale :'  + Floattostr(Scale) +
          ' ScaleF:'  + Floattostr(ScaleF),
          [SourceBitmap.Scanline[0], PBitmap.Scanline[0], ShrinkImageLine]);

    end; // Try...except...end;
  finally
    SourceBitmap.free;
  end; // Try...finally...end;
end;

mein Problem : bei machen Bildern erzeugt die Fubktion scanline eine AV beim Zugriff auf bestimmte Pixel, ich kann mir aber keinen Reim darauf machen, auch wenn ich alle Werte ausgeben lasse , siehe screnn Dump.

Sieht jemand einen Fehler in diesem Code ?
Angehängte Grafiken
Dateityp: jpg shrink_bmp_error.jpg (19,4 KB, 6x aufgerufen)
  Mit Zitat antworten Zitat
 


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:04 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz