Ignore:
Timestamp:
Dec 22, 2016, 8:49:19 PM (8 years ago)
Author:
chronos
Message:
  • Modified: Updated BGRABitmap package.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • GraphicTest/Packages/bgrabitmap/bgrareadpng.pas

    r472 r494  
    5656      //CFmt : TColorFormat; // format of the colors to convert from
    5757      StartX,StartY, DeltaX,DeltaY, StartPass,EndPass : integer;  // number and format of passes
    58       FSwitchLine, FCurrentLine, FPreviousLine : pByteArray;
    5958      FPalette : TFPPalette;
    6059      FSetPixel : TSetPixelProc;
     
    10099      DataIndex : longword;
    101100      DataBytes : TColorData;
    102       function CurrentLine(x:longword) : byte;
    103       function PrevSample (x:longword): byte;
    104       function PreviousLine (x:longword) : byte;
    105       function PrevLinePrevSample (x:longword): byte;
    106101      procedure HandleChunk; virtual;
    107102      procedure HandlePalette; virtual;
     
    109104      function CalcX (relX:integer) : integer;
    110105      function CalcY (relY:integer) : integer;
    111       function CalcColor: TColorData;
     106      function CalcColor(const ScanLine : PByteArray): TColorData;
    112107      procedure HandleScanLine (const y : integer; const ScanLine : PByteArray); virtual;
    113108      procedure BGRAHandleScanLine(const y: integer; const ScanLine: PByteArray);
    114109      procedure BGRAHandleScanLineTr(const y: integer; const ScanLine: PByteArray);
    115110      procedure DoDecompress; virtual;
    116       function  DoFilter(LineFilter:byte;index:longword; b:byte) : byte; virtual;
    117111      procedure SetPalettePixel (x,y:integer; const CD : TColordata);
    118112      procedure SetPalColPixel (x,y:integer; const CD : TColordata);
     
    381375end;
    382376
    383 function TBGRAReaderPNG.CurrentLine(x:longword):byte;
    384 begin
    385   result := FCurrentLine^[x];
    386 end;
    387 
    388 function TBGRAReaderPNG.PrevSample (x:longword): byte;
    389 begin
    390   if x < byteWidth then
    391     result := 0
    392   else
    393     result := FCurrentLine^[x - bytewidth];
    394 end;
    395 
    396 function TBGRAReaderPNG.PreviousLine (x:longword) : byte;
    397 begin
    398   result := FPreviousline^[x];
    399 end;
    400 
    401 function TBGRAReaderPNG.PrevLinePrevSample (x:longword): byte;
    402 begin
    403   if x < byteWidth then
    404     result := 0
    405   else
    406     result := FPreviousLine^[x - bytewidth];
    407 end;
    408 
    409 function TBGRAReaderPNG.DoFilter(LineFilter:byte;index:longword; b:byte) : byte;
    410 var diff : byte;
    411   procedure FilterSub;
    412   begin
    413     diff := PrevSample(index);
    414   end;
    415   procedure FilterUp;
    416   begin
    417     diff := PreviousLine(index);
    418   end;
    419   procedure FilterAverage;
    420   var l, p : word;
    421   begin
    422     l := PrevSample(index);
    423     p := PreviousLine(index);
    424     diff := (l + p) div 2;
    425   end;
    426   procedure FilterPaeth;
    427   var dl, dp, dlp : word; // index for previous and distances for:
    428       l, p, lp : byte;  // r:predictor, Left, Previous, LeftPrevious
    429       r : integer;
    430   begin
    431     l := PrevSample(index);
    432     lp := PrevLinePrevSample(index);
    433     p := PreviousLine(index);
    434     r := integer(l) + integer(p) - integer(lp);
    435     dl := abs (r - l);
    436     dlp := abs (r - lp);
    437     dp := abs (r - p);
    438     if (dl <= dp) and (dl <= dlp) then
    439       diff := l
    440     else if dp <= dlp then
    441       diff := p
    442     else
    443       diff := lp;
    444   end;
    445 begin
    446   case LineFilter of
    447     0 : diff := 0;
    448     1 : FilterSub;
    449     2 : FilterUp;
    450     3 : FilterAverage;
    451     4 : FilterPaeth;
    452   end;
    453   result := (b + diff) mod $100;
    454 end;
    455 
    456377function TBGRAReaderPNG.DecideSetPixel : TSetPixelProc;
    457378begin
     
    488409end;
    489410
    490 function TBGRAReaderPNG.CalcColor: TColorData;
     411function TBGRAReaderPNG.CalcColor(const ScanLine : PByteArray): TColorData;
    491412var cd : longword;
    492413    r : word;
     
    499420      begin
    500421       p := @Databytes;
    501        p^ := 0;
    502        for r:=0 to bytewidth-2 do
     422       for r:=0 to bytewidth shr 1 - 1 do
    503423       begin
    504         inc(p);
    505         p^:=FCurrentLine^[Dataindex+r];
     424        p^ := ScanLine^[Dataindex+(r shl 1)+1];
     425        (p+1)^ := ScanLine^[Dataindex+(r shl 1)];
     426        inc(p,2);
    506427       end;
    507428      end
    508     else move (FCurrentLine^[DataIndex], Databytes, bytewidth);
     429    else move (ScanLine^[DataIndex], Databytes, bytewidth);
    509430    {$IFDEF ENDIAN_BIG}
    510431    Databytes:=swap(Databytes);
     
    586507  for rx := 0 to ScanlineLength[CurrentPass]-1 do
    587508    begin
    588     c := CalcColor;
     509    c := CalcColor(ScanLine);
    589510    FSetPixel (x,y,c);
    590511    Inc(X, deltaX);
     
    666587  for rx := 0 to ScanlineLength[CurrentPass]-1 do
    667588    begin
    668     c := CalcColor;
     589    c := CalcColor(ScanLine);
    669590    FSetPixel (x,y,c);
    670591    Inc(X, deltaX);
     
    767688  for rx := 0 to ScanlineLength[CurrentPass]-1 do
    768689    begin
    769     c := CalcColor;
     690    c := CalcColor(ScanLine);
    770691    FSetPixel (x,y,c);
    771692    Inc(X, deltaX);
     
    934855  c := c + (c shl 2);
    935856  c := c + (c shl 4);
    936   with result do
    937     begin
    938     red := c;
    939     green := c;
    940     blue := c;
    941     alpha := 255;
    942     end;
     857  result := BGRA(c,c,c);
    943858end;
    944859
     
    948863  c := CD and $F;
    949864  c := c + (c shl 4);
    950   with result do
    951     begin
    952     red := c;
    953     green := c;
    954     blue := c;
    955     alpha := 255;
    956     end;
     865  result := BGRA(c,c,c);
    957866end;
    958867
     
    961870begin
    962871  c := CD and $FF;
    963   with result do
    964     begin
    965     red := c;
    966     green := c;
    967     blue := c;
    968     alpha := 255;
    969     end;
     872  result := BGRA(c,c,c);
    970873end;
    971874
     
    974877begin
    975878  c := (CD shr 8) and $FF;
    976   with result do
    977     begin
    978     red := c;
    979     green := c;
    980     blue := c;
    981     alpha := 255;
    982     end;
     879  result := BGRA(c,c,c);
    983880end;
    984881
     
    987884begin
    988885  c := CD and $00FF;
    989   with result do
    990     begin
    991     red := c;
    992     green := c;
    993     blue := c;
    994     alpha := (CD shr 8) and $FF;
    995     end;
     886  result := BGRA(c,c,c,(CD shr 8) and $FF);
    996887end;
    997888
     
    1000891begin
    1001892  c := (CD shr 8) and $FF;
    1002   with result do
    1003     begin
    1004     red := c;
    1005     green := c;
    1006     blue := c;
    1007     alpha := (CD shr 24) and $FF;
    1008     end;
     893  result := BGRA(c,c,c,(CD shr 24) and $FF);
    1009894end;
    1010895
     
    1013898begin
    1014899  temp := CD;
    1015   temp := ((temp and $ff) shl 16) or
    1016     (temp and $ff00) or ((temp shr 16) and $ff) or
    1017     $ff000000;
    1018   {$IFDEF ENDIAN_BIG}
    1019   DWord(result) := swap(temp);
    1020   {$ELSE}
    1021   DWord(result) := temp;
    1022   {$ENDIF}
     900  result := BGRA(temp and $ff, (temp shr 8) and $ff, (temp shr 16) and $ff);
    1023901end;
    1024902
    1025903function TBGRAReaderPNG.BGRAColorColor16(const CD: TColorData): TBGRAPixel;
    1026904begin
    1027   with result do
    1028     begin
    1029     red := CD shr 8 and $FF;
    1030     green := (CD shr 24) and $FF;
    1031     blue := (CD shr 40) and $FF;
    1032     alpha := 255;
    1033     end;
     905  result := BGRA(CD shr 8 and $FF,(CD shr 24) and $FF,(CD shr 40) and $FF);
    1034906end;
    1035907
     
    1038910begin
    1039911  temp := CD;
    1040   temp := ((temp and $ff) shl 16) or
    1041     (temp and $ff00) or ((temp shr 16) and $ff) or
    1042     (temp and $ff000000);
    1043   {$IFDEF ENDIAN_BIG}
    1044   DWord(result) := swap(temp);
    1045   {$ELSE}
    1046   DWord(result) := temp;
    1047   {$ENDIF}
     912  result := BGRA(temp and $ff, (temp shr 8) and $ff, (temp shr 16) and $ff, temp shr 24);
    1048913end;
    1049914
    1050915function TBGRAReaderPNG.BGRAColorColorAlpha16(const CD: TColorData): TBGRAPixel;
    1051916begin
    1052   with result do
    1053     begin
    1054     red := (CD shr 8) and $FF;
    1055     green := (CD shr 24) and $FF;
    1056     blue := (CD shr 40) and $FF;
    1057     alpha := (CD shr 56) and $FF;
    1058     end;
     917  result := BGRA(CD shr 8 and $FF,(CD shr 24) and $FF,(CD shr 40) and $FF, CD shr 56);
    1059918end;
    1060919
     
    11851044  end;
    11861045
     1046  procedure FilterSub(p: PByte; Count: NativeInt; bw: NativeInt);
     1047  begin
     1048    inc(p,bw);
     1049    dec(Count,bw);
     1050    while Count > 0 do
     1051    begin
     1052      {$push}{$r-}
     1053      p^ += (p-bw)^;
     1054      {$pop}
     1055      inc(p);
     1056      dec(Count);
     1057    end;
     1058  end;
     1059
     1060  procedure FilterUp(p,pPrev: PByte; Count: NativeUInt);
     1061  var Count4: NativeInt;
     1062  begin
     1063    Count4 := Count shr 2;
     1064    dec(Count, Count4 shl 2);
     1065    while Count4 > 0 do
     1066    begin
     1067      {$push}{$r-}
     1068      PDWord(p)^ := (((PDWord(pPrev)^ and $00FF00FF) + (PDWord(p)^ and $00FF00FF)) and $00FF00FF)
     1069        or (((PDWord(pPrev)^ and $FF00FF00) + (PDWord(p)^ and $FF00FF00)) and $FF00FF00);
     1070      {$pop}
     1071      inc(p,4);
     1072      inc(pPrev,4);
     1073      dec(Count4);
     1074    end;
     1075    while Count > 0 do
     1076    begin
     1077      {$push}{$r-}
     1078      p^ += pPrev^;
     1079      {$pop}
     1080
     1081      inc(p);
     1082      inc(pPrev);
     1083      dec(Count);
     1084    end;
     1085  end;
     1086
     1087  procedure FilterAverage(p,pPrev: PByte; Count: NativeUInt; bw: NativeInt);
     1088  var CountBW: NativeInt;
     1089  begin
     1090    CountBW := bw;
     1091    dec(Count,CountBW);
     1092    while CountBW > 0 do
     1093    begin
     1094      {$push}{$r-}
     1095      p^ += pPrev^ shr 1;
     1096      {$pop}
     1097      inc(p);
     1098      inc(pPrev);
     1099      dec(CountBW);
     1100    end;
     1101
     1102    while Count > 0 do
     1103    begin
     1104      {$push}{$r-}
     1105      p^ += (pPrev^+(p-bw)^) shr 1;
     1106      {$pop}
     1107      inc(p);
     1108      inc(pPrev);
     1109      dec(Count);
     1110    end;
     1111  end;
     1112
     1113  procedure FilterPaeth(p,pPrev: PByte; Count: NativeUInt; bw: NativeInt);
     1114  var
     1115    rx, dl, dp, dlp : NativeInt;
     1116    diag,left: NativeUInt;
     1117  begin
     1118    for rx := 0 to bw-1 do
     1119    begin
     1120      {$push}{$r-}
     1121      p^ += pPrev^;
     1122      {$pop}
     1123      inc(p);
     1124      inc(pPrev);
     1125    end;
     1126    dec(Count,bw);
     1127    while Count > 0 do
     1128    begin
     1129      diag := (pPrev-bw)^;
     1130      left := (p - bw)^;
     1131      dl := pPrev^ - NativeInt(diag);
     1132      dp := NativeInt(left) - NativeInt(diag);
     1133      dlp := abs(dl+dp);
     1134      if dl < 0 then dl := -dl;
     1135      if dp < 0 then dp := -dp;
     1136      {$push}{$r-}
     1137      if dp <= dlp then
     1138      begin
     1139        if dl <= dp then
     1140          p^ += left
     1141        else
     1142          p^ += pPrev^
     1143      end
     1144      else
     1145      if dl <= dlp then
     1146        p^ += left
     1147      else
     1148        p^ += diag;
     1149      {$pop}
     1150      inc(p);
     1151      inc(pPrev);
     1152      dec(Count);
     1153     end;
     1154  end;
     1155
    11871156  procedure Decode;
    1188   var y, rp, ry, rx, l : integer;
     1157  var y, rp, ry, l : NativeInt;
    11891158      lf : byte;
     1159      switchLine, currentLine, previousLine : pByteArray;
    11901160  begin
    11911161    FSetPixel := DecideSetPixel;
     
    12151185      if (l>0) then
    12161186        begin
    1217         GetMem (FPreviousLine, l);
    1218         GetMem (FCurrentLine, l);
    1219         fillchar (FCurrentLine^,l,0);
     1187        GetMem (previousLine, l);
     1188        GetMem (currentLine, l);
     1189        fillchar (currentLine^,l,0);
    12201190        try
    12211191          for ry := 0 to CountScanlines[rp]-1 do
    12221192            begin
    1223             FSwitchLine := FCurrentLine;
    1224             FCurrentLine := FPreviousLine;
    1225             FPreviousLine := FSwitchLine;
    1226             Y := CalcY(ry);
     1193            switchLine := currentLine;
     1194            currentLine := previousLine;
     1195            previousLine := switchLine;
     1196            Y := StartY + (ry * deltaY);
    12271197            lf := 0;
    12281198            Decompress.Read (lf, sizeof(lf));
    1229             Decompress.Read (FCurrentLine^, l);
    1230             if lf <> 0 then  // Do nothing when there is no filter used
    1231               for rx := 0 to l-1 do
    1232                 FCurrentLine^[rx] := DoFilter (lf, rx, FCurrentLine^[rx]);
     1199            Decompress.Read (currentLine^, l);
     1200
     1201            case lf of
     1202              1: FilterSub(PByte(currentLine), l, ByteWidth);
     1203              2: FilterUp(PByte(currentLine), PByte(previousLine), l);
     1204              3: FilterAverage(PByte(currentLine), PByte(previousLine), l, ByteWidth);
     1205              4: FilterPaeth(PByte(currentLine), PByte(previousLine), l, ByteWidth);
     1206            end;
     1207
    12331208            if FVerticalShrinkShr <> 0 then
    12341209              begin
    12351210                if (y and FVerticalShrinkMask) = 0 then
    1236                   FHandleScanLine (y shr FVerticalShrinkShr, FCurrentLine);
     1211                  FHandleScanLine (y shr FVerticalShrinkShr, currentLine);
    12371212              end else
    1238                 FHandleScanLine (y, FCurrentLine);
     1213                FHandleScanLine (y, currentLine);
    12391214            end;
    12401215        finally
    1241           freemem (FPreviousLine);
    1242           freemem (FCurrentLine);
     1216          freemem (previousLine);
     1217          freemem (currentLine);
    12431218        end;
    12441219        end;
Note: See TracChangeset for help on using the changeset viewer.