Changeset 494 for GraphicTest/Packages/bgrabitmap/blurnormal.inc
- Timestamp:
- Dec 22, 2016, 8:49:19 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
GraphicTest/Packages/bgrabitmap/blurnormal.inc
r472 r494 1 type 2 PWeightedPixel = ^TWeightedPixel; 3 TWeightedPixel = packed record 4 Coord: TPoint; 5 Weight: NativeInt; 6 PtrOfs: NativeInt; 7 end; 8 1 9 var 2 10 maskWidth,maskHeight: integer; 3 blurOfs: 4 PixelWeight: array of integer;5 Pixel Ofs: array of TPoint;11 blurOfs: TPoint; 12 ppixel: PWeightedPixel; 13 Pixel: array of TWeightedPixel; 6 14 PixelArrayLineStart: array of integer; 7 DiffPixelWeight: array of integer; 8 DiffPixelOfs: array of TPoint; 15 DiffPixel: array of TWeightedPixel; 9 16 DiffPixelArrayLineStart: array of integer; 10 17 11 procedure LoadMask; 12 var x,y,n: integer; 13 tempWeight: integer; 14 diffMask: array of array of integer; 18 bmpWidth,bmpHeight,lineDelta: NativeInt; 19 20 procedure LoadMask(out ABlurOfs: TPoint); 21 var x,y,n,i: NativeInt; 22 tempWeight: NativeInt; 23 diffMask: array of packed array of NativeInt; 24 p: PBGRAPixel; 15 25 begin 16 blurOfs := point(blurMask.Width shr 1, blurMask.Height shr 1);26 ABlurOfs := point(blurMask.Width shr 1, blurMask.Height shr 1); 17 27 18 28 //count number of non empty pixels … … 20 30 maskHeight := blurMask.Height; 21 31 n := 0; 22 for y := 0 to maskHeight - 1 do 23 for x := 0 to maskWidth - 1 do 24 if blurMask.GetPixel(x, y).red <> 0 then Inc(n); 32 p := blurMask.Data; 33 for i := blurMask.NbPixels-1 downto 0 do 34 begin 35 if p^.red <> 0 then inc(n); 36 inc(p); 37 end; 25 38 26 39 //initialize arrays 27 40 setlength(diffMask, maskHeight, maskWidth+1); 28 41 for y := 0 to maskHeight - 1 do 29 for x := 0 to maskWidth do 30 diffMask[y,x] := 0; 31 32 setlength(PixelWeight, n); 33 setlength(PixelOfs, n); 42 fillchar(diffMask[y,0], (maskWidth+1)*sizeof(NativeInt), 0); 43 44 setlength(Pixel, n); 34 45 setlength(PixelArrayLineStart, maskHeight+1); //stores the first pixel of each line 35 46 n := 0; … … 38 49 begin 39 50 PixelArrayLineStart[y] := n; 51 p := blurMask.ScanLine[y]; 40 52 for x := 0 to maskWidth - 1 do 41 53 begin 42 tempWeight := blurMask.GetPixel(x, y).red; 54 tempWeight := p^.red; 55 inc(p); 43 56 diffMask[y,x] -= tempWeight; 44 57 diffMask[y,x+1] += tempWeight; … … 46 59 if tempWeight <> 0 then 47 60 begin 48 PixelWeight[n] := tempWeight; 49 PixelOfs[n] := Point(x,y); 61 Pixel[n].Weight := tempWeight; 62 Pixel[n].Coord := Point(x,y); 63 Pixel[n].PtrOfs := (y-ABlurOfs.Y)*lineDelta + (x-ABlurOfs.X)*sizeof(TBGRAPixel); 50 64 Inc(n); 51 65 end; … … 61 75 62 76 //initialize arrays 63 setlength(DiffPixelWeight, n); 64 setlength(DiffPixelOfs, n); 77 setlength(DiffPixel, n); 65 78 setlength(DiffPixelArrayLineStart, maskHeight+1); //stores the first pixel of each diff line 66 79 n := 0; … … 74 87 if tempWeight <> 0 then 75 88 begin 76 DiffPixelWeight[n] := tempWeight; 77 DiffPixelOfs[n] := Point(x-1,y); 89 DiffPixel[n].Weight := tempWeight; 90 DiffPixel[n].Coord := Point(x-1,y); 91 DiffPixel[n].PtrOfs := (y-ABlurOfs.Y)*lineDelta + (x-ABlurOfs.X-1)*sizeof(TBGRAPixel); 78 92 Inc(n); 79 93 end; … … 83 97 end; 84 98 85 var 86 curScans: array of PBGRAPixel; 87 bounds: TRect; 88 89 {procedure ShowCurScans; 90 var str: string; 91 i: Integer; 92 begin 93 str := ''; 94 for i := 0 to high(curScans) do 95 begin 96 if i <> 0 then str += ', '; 97 if curScans[i]=nil then str += 'nil' else 98 str += 'bmp['+inttostr(curScans[i]-bmp.Data)+']'; 99 end; 100 ShowMessage(str); 101 end;} 102 103 function PrepareScan: boolean; 104 var 105 bmpY: integer; 106 y : Integer; 99 function PrepareScan(AWantedBounds: TRect; out AClippedBounds: TRect): boolean; 107 100 begin 108 101 //evaluate required bounds taking blur radius into acount 109 bounds := bmp.GetImageBounds;110 if IsRectEmpty( bounds) then102 AClippedBounds := bmp.GetImageBounds; 103 if IsRectEmpty(AClippedBounds) then 111 104 begin 112 105 result := false; 113 106 exit; 114 107 end; 115 bounds.Left := max(0, bounds.Left - blurOfs.X);116 bounds.Top := max(0, bounds.Top - blurOfs.Y);117 bounds.Right := min(bmp.Width, bounds.Right + maskWidth - 1 - blurOfs.X);118 bounds.Bottom := min(bmp.Height, bounds.Bottom + maskHeight - 1 - blurOfs.Y);119 if not IntersectRect( bounds, bounds, ABounds) then108 AClippedBounds.Left := max(0, AClippedBounds.Left - blurOfs.X); 109 AClippedBounds.Top := max(0, AClippedBounds.Top - blurOfs.Y); 110 AClippedBounds.Right := min(bmpWidth, AClippedBounds.Right + maskWidth - 1 - blurOfs.X); 111 AClippedBounds.Bottom := min(bmpHeight, AClippedBounds.Bottom + maskHeight - 1 - blurOfs.Y); 112 if not IntersectRect(AClippedBounds, AClippedBounds, AWantedBounds) then 120 113 begin 121 114 result := false; … … 123 116 end; 124 117 125 //init scanlines126 setlength(curScans, maskHeight);127 for y := 0 to maskHeight-1 do128 begin129 bmpY := y+bounds.Top-blurOfs.Y;130 if (bmpY < 0) or (bmpY >= bmp.Height) then131 curScans[y] := nil else132 curScans[y] := bmp.ScanLine[bmpY];133 end;134 //ShowCurScans;135 118 result := true; 136 119 end; 137 120 138 procedure ShiftScan(NewY: integer); inline;139 var y: integer;140 begin141 for y := 0 to maskHeight-2 do142 curScans[y] := curScans[y+1];143 144 //get next scanline145 if newY >= bmp.Height then146 curScans[maskHeight-1] := nil147 else148 curScans[maskHeight-1] := bmp.ScanLine[newY];149 //ShowCurScans;150 end;151 152 121 var 153 yb, xb: integer; 154 mindy, maxdy, n: integer; 155 bmpWidth,bmpX: integer; 156 pixMaskAlpha, maskAlpha: integer; 122 bounds: TRect; 123 yb, xb: NativeInt; 124 mindy, maxdy, n, nStart, nCount, nDiffStart, nDiffCount: NativeInt; 125 bmpX,bmpXBase,bmpYBase: NativeInt; 126 pixMaskAlpha, maskAlpha: NativeInt; 157 127 tempPixel: TBGRAPixel; 158 128 pdest : PBGRAPixel; 159 p t: TPoint;129 psrc : PByte; 160 130 161 131 begin 162 LoadMask; 163 164 if (ADestination.Width <> bmp.Width) or (ADestination.Height <> bmp.Height) then 132 bmpWidth := bmp.Width; 133 bmpHeight:= bmp.Height; 134 if bmp.LineOrder = riloTopToBottom then 135 lineDelta := bmpWidth*sizeof(TBGRAPixel) else 136 lineDelta := -bmpWidth*sizeof(TBGRAPixel); 137 138 if (ADestination.Width <> bmpWidth) or (ADestination.Height <> bmpHeight) then 165 139 raise exception.Create('Dimension mismatch'); 166 140 167 if not PrepareScan then exit; //nothing to do 168 169 bmpWidth := bmp.Width; 141 LoadMask(blurOfs); 142 if not PrepareScan(ABounds, bounds) then exit; //nothing to do 143 144 bmpYBase := bounds.Top - blurOfs.Y; 145 170 146 //loop through destination 171 147 for yb := bounds.Top to bounds.Bottom - 1 do 172 148 begin 173 149 if (ACheckShouldStop <> nil) and ACheckShouldStop(yb) then break; 150 psrc := PByte(bmp.ScanLine[yb]+bounds.Left); 174 151 pdest := ADestination.ScanLine[yb] + bounds.Left; 175 152 //compute vertical range 176 153 mindy := max(-blurOfs.Y, -yb); 177 maxdy := min(blurMask.Height - 1 - blurOfs.Y, bmp .Height - 1 - yb);154 maxdy := min(blurMask.Height - 1 - blurOfs.Y, bmpHeight - 1 - yb); 178 155 179 156 sumR := 0; … … 186 163 {$endif} 187 164 165 bmpXBase := bounds.Left-blurOfs.X; 166 nStart := PixelArrayLineStart[mindy+blurOfs.Y]; 167 nCount := PixelArrayLineStart[maxdy+blurOfs.Y+1]-nStart; 168 ppixel:= @Pixel[nStart]; 188 169 //go through pixel list of the current vertical range 189 for n := PixelArrayLineStart[mindy+blurOfs.Y] to PixelArrayLineStart[maxdy+blurOfs.Y+1]-1 do 190 begin 191 pt := PixelOfs[n]; 192 bmpX := bounds.Left-blurOfs.X+pt.x; 170 for n := nCount-1 downto 0 do 171 begin 172 bmpX := bmpXBase+ppixel^.Coord.x; 193 173 //check horizontal range 194 174 if (bmpX >= 0) and (bmpX < bmpWidth) then 195 175 begin 196 tempPixel := (curScans[pt.y]+bmpX)^;197 maskAlpha := PixelWeight[n];176 tempPixel := PBGRAPixel(psrc + ppixel^.PtrOfs)^; 177 maskAlpha := ppixel^.Weight; 198 178 pixMaskAlpha := maskAlpha * tempPixel.alpha; 199 179 sumA += pixMaskAlpha; … … 209 189 {$hints on} 210 190 end; 211 end; 212 213 for xb := bounds.Left to Bounds.Right - 1 do 214 begin 215 if xb > bounds.left then 216 begin 217 for n := DiffPixelArrayLineStart[mindy+blurOfs.Y] to DiffPixelArrayLineStart[maxdy+blurOfs.Y+1]-1 do 218 begin 219 pt := DiffPixelOfs[n]; 220 bmpX := xb-blurOfs.X+pt.x; 191 inc(ppixel); 192 end; 193 194 //compute average 195 if (Adiv <= 0) {$ifdef PARAM_MASKSHIFT} or (RGBdiv <= 0) {$endif} then 196 pdest^ := BGRAPixelTransparent 197 else 198 pdest^ := computeAverage; 199 200 nDiffStart := DiffPixelArrayLineStart[mindy+blurOfs.Y]; 201 nDiffCount := DiffPixelArrayLineStart[maxdy+blurOfs.Y+1]-nDiffStart; 202 203 if nDiffCount < nCount then 204 begin 205 for xb := bounds.Left+1 to Bounds.Right - 1 do 206 begin 207 Inc(pdest); 208 inc(bmpXBase); 209 inc(psrc,sizeof(TBGRAPixel)); 210 211 ppixel:= @DiffPixel[nDiffStart]; 212 for n := nDiffCount-1 downto 0 do 213 begin 214 bmpX := bmpXBase+ppixel^.Coord.x; 221 215 if (bmpX >= 0) and (bmpX < bmpWidth) then 222 216 begin 223 tempPixel := (curScans[pt.y]+bmpX)^;224 maskAlpha := DiffPixelWeight[n];217 tempPixel := PBGRAPixel(psrc + ppixel^.PtrOfs)^; 218 maskAlpha := ppixel^.Weight; 225 219 pixMaskAlpha := maskAlpha * tempPixel.alpha; 226 220 sumA += pixMaskAlpha; … … 236 230 {$hints on} 237 231 end; 238 end; 239 end; 240 241 //compute average 242 if (Adiv <= 0) {$ifdef PARAM_MASKSHIFT} or (RGBdiv <= 0) {$endif} then 243 pdest^ := BGRAPixelTransparent 244 else 245 pdest^ := computeAverage; 246 247 Inc(pdest); 248 end; 249 250 ShiftScan(yb-blurOfs.Y+maskHeight); 232 inc(ppixel); 233 end; 234 235 //compute average 236 if (Adiv <= 0) {$ifdef PARAM_MASKSHIFT} or (RGBdiv <= 0) {$endif} then 237 pdest^ := BGRAPixelTransparent 238 else 239 pdest^ := ComputeAverage; 240 end; 241 end else 242 begin 243 for xb := bounds.Left+1 to Bounds.Right - 1 do 244 begin 245 Inc(pdest); 246 inc(bmpXBase); 247 inc(psrc,sizeof(TBGRAPixel)); 248 249 sumR := 0; 250 sumG := 0; 251 sumB := 0; 252 sumA := 0; 253 Adiv := 0; 254 {$ifdef PARAM_MASKSHIFT} 255 RGBdiv := 0; 256 {$endif} 257 258 ppixel:= @Pixel[nStart]; 259 for n := nCount-1 downto 0 do 260 begin 261 bmpX := bmpXBase+ppixel^.Coord.x; 262 //check horizontal range 263 if (bmpX >= 0) and (bmpX < bmpWidth) then 264 begin 265 tempPixel := PBGRAPixel(psrc + ppixel^.PtrOfs)^; 266 maskAlpha := ppixel^.Weight; 267 pixMaskAlpha := maskAlpha * tempPixel.alpha; 268 sumA += pixMaskAlpha; 269 Adiv += maskAlpha; 270 {$ifdef PARAM_MASKSHIFT} 271 pixMaskAlpha := pixMaskAlpha shr maskShift; 272 RGBdiv += pixMaskAlpha; 273 {$endif} 274 {$hints off} 275 sumR += tempPixel.red * pixMaskAlpha; 276 sumG += tempPixel.green * pixMaskAlpha; 277 sumB += tempPixel.blue * pixMaskAlpha; 278 {$hints on} 279 end; 280 inc(ppixel); 281 end; 282 283 //compute average 284 if (Adiv <= 0) {$ifdef PARAM_MASKSHIFT} or (RGBdiv <= 0) {$endif} then 285 pdest^ := BGRAPixelTransparent 286 else 287 pdest^ := computeAverage; 288 end; 289 end; 290 291 inc(bmpYBase); 251 292 end; 252 293 ADestination.InvalidateBitmap;
Note:
See TracChangeset
for help on using the changeset viewer.