Changeset 494 for GraphicTest/Packages/bgrabitmap/bgrareadpng.pas
- Timestamp:
- Dec 22, 2016, 8:49:19 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
GraphicTest/Packages/bgrabitmap/bgrareadpng.pas
r472 r494 56 56 //CFmt : TColorFormat; // format of the colors to convert from 57 57 StartX,StartY, DeltaX,DeltaY, StartPass,EndPass : integer; // number and format of passes 58 FSwitchLine, FCurrentLine, FPreviousLine : pByteArray;59 58 FPalette : TFPPalette; 60 59 FSetPixel : TSetPixelProc; … … 100 99 DataIndex : longword; 101 100 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;106 101 procedure HandleChunk; virtual; 107 102 procedure HandlePalette; virtual; … … 109 104 function CalcX (relX:integer) : integer; 110 105 function CalcY (relY:integer) : integer; 111 function CalcColor : TColorData;106 function CalcColor(const ScanLine : PByteArray): TColorData; 112 107 procedure HandleScanLine (const y : integer; const ScanLine : PByteArray); virtual; 113 108 procedure BGRAHandleScanLine(const y: integer; const ScanLine: PByteArray); 114 109 procedure BGRAHandleScanLineTr(const y: integer; const ScanLine: PByteArray); 115 110 procedure DoDecompress; virtual; 116 function DoFilter(LineFilter:byte;index:longword; b:byte) : byte; virtual;117 111 procedure SetPalettePixel (x,y:integer; const CD : TColordata); 118 112 procedure SetPalColPixel (x,y:integer; const CD : TColordata); … … 381 375 end; 382 376 383 function TBGRAReaderPNG.CurrentLine(x:longword):byte;384 begin385 result := FCurrentLine^[x];386 end;387 388 function TBGRAReaderPNG.PrevSample (x:longword): byte;389 begin390 if x < byteWidth then391 result := 0392 else393 result := FCurrentLine^[x - bytewidth];394 end;395 396 function TBGRAReaderPNG.PreviousLine (x:longword) : byte;397 begin398 result := FPreviousline^[x];399 end;400 401 function TBGRAReaderPNG.PrevLinePrevSample (x:longword): byte;402 begin403 if x < byteWidth then404 result := 0405 else406 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 begin413 diff := PrevSample(index);414 end;415 procedure FilterUp;416 begin417 diff := PreviousLine(index);418 end;419 procedure FilterAverage;420 var l, p : word;421 begin422 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, LeftPrevious429 r : integer;430 begin431 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) then439 diff := l440 else if dp <= dlp then441 diff := p442 else443 diff := lp;444 end;445 begin446 case LineFilter of447 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 456 377 function TBGRAReaderPNG.DecideSetPixel : TSetPixelProc; 457 378 begin … … 488 409 end; 489 410 490 function TBGRAReaderPNG.CalcColor : TColorData;411 function TBGRAReaderPNG.CalcColor(const ScanLine : PByteArray): TColorData; 491 412 var cd : longword; 492 413 r : word; … … 499 420 begin 500 421 p := @Databytes; 501 p^ := 0; 502 for r:=0 to bytewidth-2 do 422 for r:=0 to bytewidth shr 1 - 1 do 503 423 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); 506 427 end; 507 428 end 508 else move ( FCurrentLine^[DataIndex], Databytes, bytewidth);429 else move (ScanLine^[DataIndex], Databytes, bytewidth); 509 430 {$IFDEF ENDIAN_BIG} 510 431 Databytes:=swap(Databytes); … … 586 507 for rx := 0 to ScanlineLength[CurrentPass]-1 do 587 508 begin 588 c := CalcColor ;509 c := CalcColor(ScanLine); 589 510 FSetPixel (x,y,c); 590 511 Inc(X, deltaX); … … 666 587 for rx := 0 to ScanlineLength[CurrentPass]-1 do 667 588 begin 668 c := CalcColor ;589 c := CalcColor(ScanLine); 669 590 FSetPixel (x,y,c); 670 591 Inc(X, deltaX); … … 767 688 for rx := 0 to ScanlineLength[CurrentPass]-1 do 768 689 begin 769 c := CalcColor ;690 c := CalcColor(ScanLine); 770 691 FSetPixel (x,y,c); 771 692 Inc(X, deltaX); … … 934 855 c := c + (c shl 2); 935 856 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); 943 858 end; 944 859 … … 948 863 c := CD and $F; 949 864 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); 957 866 end; 958 867 … … 961 870 begin 962 871 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); 970 873 end; 971 874 … … 974 877 begin 975 878 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); 983 880 end; 984 881 … … 987 884 begin 988 885 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); 996 887 end; 997 888 … … 1000 891 begin 1001 892 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); 1009 894 end; 1010 895 … … 1013 898 begin 1014 899 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); 1023 901 end; 1024 902 1025 903 function TBGRAReaderPNG.BGRAColorColor16(const CD: TColorData): TBGRAPixel; 1026 904 begin 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); 1034 906 end; 1035 907 … … 1038 910 begin 1039 911 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); 1048 913 end; 1049 914 1050 915 function TBGRAReaderPNG.BGRAColorColorAlpha16(const CD: TColorData): TBGRAPixel; 1051 916 begin 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); 1059 918 end; 1060 919 … … 1185 1044 end; 1186 1045 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 1187 1156 procedure Decode; 1188 var y, rp, ry, rx, l : integer;1157 var y, rp, ry, l : NativeInt; 1189 1158 lf : byte; 1159 switchLine, currentLine, previousLine : pByteArray; 1190 1160 begin 1191 1161 FSetPixel := DecideSetPixel; … … 1215 1185 if (l>0) then 1216 1186 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); 1220 1190 try 1221 1191 for ry := 0 to CountScanlines[rp]-1 do 1222 1192 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); 1227 1197 lf := 0; 1228 1198 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 1233 1208 if FVerticalShrinkShr <> 0 then 1234 1209 begin 1235 1210 if (y and FVerticalShrinkMask) = 0 then 1236 FHandleScanLine (y shr FVerticalShrinkShr, FCurrentLine);1211 FHandleScanLine (y shr FVerticalShrinkShr, currentLine); 1237 1212 end else 1238 FHandleScanLine (y, FCurrentLine);1213 FHandleScanLine (y, currentLine); 1239 1214 end; 1240 1215 finally 1241 freemem ( FPreviousLine);1242 freemem ( FCurrentLine);1216 freemem (previousLine); 1217 freemem (currentLine); 1243 1218 end; 1244 1219 end;
Note:
See TracChangeset
for help on using the changeset viewer.