Changeset 494 for GraphicTest/Packages/bgrabitmap/bgradithering.pas
- Timestamp:
- Dec 22, 2016, 8:49:19 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
GraphicTest/Packages/bgrabitmap/bgradithering.pas
r472 r494 6 6 7 7 uses 8 Classes, SysUtils, BGRAFilter s, BGRAPalette, BGRABitmapTypes;8 Classes, SysUtils, BGRAFilterType, BGRAPalette, BGRABitmapTypes; 9 9 10 10 type 11 TOutputPixelProc = procedure(X,Y: NativeInt; AColorIndex: NativeInt; AColor: TBGRAPixel) of object; 11 12 12 13 { TDitheringTask } … … 17 18 FIgnoreAlpha: boolean; 18 19 FPalette: TBGRACustomApproxPalette; 20 FCurrentOutputScanline: PBGRAPixel; 21 FCurrentOutputY: NativeInt; 22 FOutputPixel : TOutputPixelProc; 23 FDrawMode: TDrawMode; 24 procedure OutputPixel(X,Y: NativeInt; {%H-}AColorIndex: NativeInt; AColor: TBGRAPixel); virtual; 25 procedure ApproximateColor(const AColor: TBGRAPixel; out AApproxColor: TBGRAPixel; out AIndex: integer); 19 26 public 27 constructor Create(ASource: IBGRAScanner; APalette: TBGRACustomApproxPalette; ADestination: TBGRACustomBitmap; AIgnoreAlpha: boolean; ABounds: TRect); overload; 20 28 constructor Create(bmp: TBGRACustomBitmap; APalette: TBGRACustomApproxPalette; AInPlace: boolean; AIgnoreAlpha: boolean; ABounds: TRect); overload; 21 29 constructor Create(bmp: TBGRACustomBitmap; APalette: TBGRACustomApproxPalette; AInPlace: boolean; AIgnoreAlpha: boolean); overload; 30 property OnOutputPixel: TOutputPixelProc read FOutputPixel write FOutputPixel; 31 property DrawMode: TDrawMode read FDrawMode write FDrawMode; 22 32 end; 23 33 … … 34 44 protected 35 45 procedure DoExecute; override; 46 end; 47 48 { TDitheringToIndexedImage } 49 50 TDitheringToIndexedImage = class 51 protected 52 FBitOrder: TRawImageBitOrder; 53 FByteOrder: TRawImageByteOrder; 54 FBitsPerPixel: integer; 55 FLineOrder: TRawImageLineOrder; 56 FPalette: TBGRACustomApproxPalette; 57 FIgnoreAlpha: boolean; 58 FTransparentColorIndex: NativeInt; 59 60 //following variables are used during dithering 61 FCurrentScanlineSize: PtrInt; 62 FCurrentData: PByte; 63 FCurrentOutputY: NativeInt; 64 FCurrentOutputScanline: PByte; 65 FCurrentBitOrderMask: NativeInt; 66 FCurrentMaxY: NativeInt; 67 68 procedure SetPalette(AValue: TBGRACustomApproxPalette); 69 procedure SetIgnoreAlpha(AValue: boolean); 70 procedure SetLineOrder(AValue: TRawImageLineOrder); 71 procedure SetBitOrder(AValue: TRawImageBitOrder); virtual; 72 procedure SetBitsPerPixel(AValue: integer); virtual; 73 procedure SetByteOrder(AValue: TRawImageByteOrder); virtual; 74 procedure OutputPixelSubByte(X,Y: NativeInt; AColorIndex: NativeInt; {%H-}AColor: TBGRAPixel); virtual; 75 procedure OutputPixelFullByte(X,Y: NativeInt; AColorIndex: NativeInt; {%H-}AColor: TBGRAPixel); virtual; 76 function GetScanline(Y: NativeInt): Pointer; virtual; 77 function GetTransparentColorIndex: integer; 78 procedure SetTransparentColorIndex(AValue: integer); 79 public 80 constructor Create(APalette: TBGRACustomApproxPalette; AIgnoreAlpha: boolean; ABitsPerPixelForIndices: integer); //use platform byte order 81 constructor Create(APalette: TBGRACustomApproxPalette; AIgnoreAlpha: boolean; ABitsPerPixelForIndices: integer; AByteOrder: TRawImageByteOrder); //maybe necessary if larger than 8 bits per pixel 82 83 function DitherImage(AAlgorithm: TDitheringAlgorithm; AImage: TBGRACustomBitmap): Pointer; overload; //use minimum scanline size 84 function DitherImage(AAlgorithm: TDitheringAlgorithm; AImage: TBGRACustomBitmap; AScanlineSize: PtrInt): Pointer; overload; 85 procedure DitherImageTo(AAlgorithm: TDitheringAlgorithm; AImage: TBGRACustomBitmap; AData: Pointer); overload; //use minimum scanline size 86 procedure DitherImageTo(AAlgorithm: TDitheringAlgorithm; AImage: TBGRACustomBitmap; AData: Pointer; AScanlineSize: PtrInt); overload; 87 function ComputeMinimumScanlineSize(AWidthInPixels: integer): PtrInt; 88 function AllocateSpaceForIndexedData(AImage: TBGRACustomBitmap; AScanlineSize: PtrInt): pointer; 89 90 //optional customization of format 91 property BitsPerPixel: integer read FBitsPerPixel write SetBitsPerPixel; 92 property BitOrder: TRawImageBitOrder read FBitOrder write SetBitOrder; 93 property ByteOrder: TRawImageByteOrder read FByteOrder write SetByteOrder; 94 property LineOrder: TRawImageLineOrder read FLineOrder write SetLineOrder; 95 96 property Palette: TBGRACustomApproxPalette read FPalette write SetPalette; 97 property IgnoreAlpha: boolean read FIgnoreAlpha write SetIgnoreAlpha; 98 99 //when there is no transparent color in the palette, or that IgnoreAlpha is set to True, 100 //this allows to define the index for the fully transparent color 101 property DefaultTransparentColorIndex: integer read GetTransparentColorIndex write SetTransparentColorIndex; 36 102 end; 37 103 … … 40 106 function CreateDitheringTask(AAlgorithm: TDitheringAlgorithm; ABitmap: TBGRACustomBitmap; APalette: TBGRACustomApproxPalette; 41 107 AIgnoreAlpha: boolean; ABounds: TRect): TDitheringTask; overload; 108 function CreateDitheringTask(AAlgorithm: TDitheringAlgorithm; ASource: IBGRAScanner; ADestination: TBGRACustomBitmap; ABounds: TRect): TDitheringTask; overload; 109 function CreateDitheringTask(AAlgorithm: TDitheringAlgorithm; ASource: IBGRAScanner; ADestination: TBGRACustomBitmap; APalette: TBGRACustomApproxPalette; 110 AIgnoreAlpha: boolean; ABounds: TRect): TDitheringTask; overload; 111 112 function DitherImageTo16Bit(AAlgorithm: TDitheringAlgorithm; ABitmap: TBGRACustomBitmap): TBGRACustomBitmap; 42 113 43 114 implementation 115 116 uses BGRABlend; 44 117 45 118 function AbsRGBADiff(const c1, c2: TExpandedPixel): NativeInt; … … 68 141 end; 69 142 143 function CreateDitheringTask(AAlgorithm: TDitheringAlgorithm; 144 ASource: IBGRAScanner; ADestination: TBGRACustomBitmap; ABounds: TRect 145 ): TDitheringTask; 146 begin 147 result := CreateDitheringTask(AAlgorithm, ASource, ADestination, nil, true, ABounds); 148 end; 149 150 function CreateDitheringTask(AAlgorithm: TDitheringAlgorithm; 151 ASource: IBGRAScanner; ADestination: TBGRACustomBitmap; 152 APalette: TBGRACustomApproxPalette; AIgnoreAlpha: boolean; ABounds: TRect 153 ): TDitheringTask; 154 begin 155 result := nil; 156 case AAlgorithm of 157 daNearestNeighbor: result := TNearestColorTask.Create(ASource, APalette, ADestination, AIgnoreAlpha, ABounds); 158 daFloydSteinberg: result := TFloydSteinbergDitheringTask.Create(ASource, APalette, ADestination, AIgnoreAlpha, ABounds); 159 else raise exception.Create('Unknown algorithm'); 160 end; 161 end; 162 163 function DitherImageTo16Bit(AAlgorithm: TDitheringAlgorithm; 164 ABitmap: TBGRACustomBitmap): TBGRACustomBitmap; 165 var 166 palette16bit: TBGRA16BitPalette; 167 dither: TDitheringTask; 168 begin 169 palette16bit := TBGRA16BitPalette.Create; 170 dither := CreateDitheringTask(AAlgorithm, ABitmap, palette16bit, false); 171 result := dither.Execute; 172 dither.Free; 173 palette16bit.Free; 174 end; 175 176 { TDitheringToIndexedImage } 177 178 procedure TDitheringToIndexedImage.SetBitsPerPixel(AValue: integer); 179 begin 180 if not (AValue in [1,2,4,8,16,32]) then 181 raise exception.Create('Invalid value for bits per pixel. Allowed values: 1,2,4,8,16,32.'); 182 if FBitsPerPixel=AValue then Exit; 183 FBitsPerPixel:=AValue; 184 end; 185 186 procedure TDitheringToIndexedImage.SetByteOrder(AValue: TRawImageByteOrder); 187 begin 188 if FByteOrder=AValue then Exit; 189 FByteOrder:=AValue; 190 end; 191 192 procedure TDitheringToIndexedImage.OutputPixelSubByte(X, Y: NativeInt; 193 AColorIndex: NativeInt; AColor: TBGRAPixel); 194 var p: PByte; 195 begin 196 if y <> FCurrentOutputY then 197 begin 198 FCurrentOutputY := y; 199 FCurrentOutputScanline := GetScanline(Y); 200 end; 201 if AColorIndex = -1 then AColorIndex := FTransparentColorIndex; 202 case FBitsPerPixel of 203 1: begin 204 p := FCurrentOutputScanline+(x shr 3); 205 p^ := p^ or ((AColorIndex and 1) shl ((x xor FCurrentBitOrderMask) and 7)); 206 end; 207 2: begin 208 p := FCurrentOutputScanline+(x shr 2); 209 p^ := p^ or ((AColorIndex and 1) shl (((x xor FCurrentBitOrderMask) and 3) shl 1)); 210 end; 211 4: begin 212 p := FCurrentOutputScanline+(x shr 1); 213 p^ := p^ or ((AColorIndex and 1) shl (((x xor FCurrentBitOrderMask) and 1) shl 2)); 214 end; 215 end; 216 end; 217 218 procedure TDitheringToIndexedImage.OutputPixelFullByte(X, Y: NativeInt; 219 AColorIndex: NativeInt; AColor: TBGRAPixel); 220 begin 221 if y <> FCurrentOutputY then 222 begin 223 FCurrentOutputY := y; 224 FCurrentOutputScanline := GetScanline(Y); 225 end; 226 if AColorIndex = -1 then AColorIndex := FTransparentColorIndex; 227 case FBitsPerPixel of 228 8: (FCurrentOutputScanline+x)^ := AColorIndex; 229 16: (PWord(FCurrentOutputScanline)+x)^ := AColorIndex; 230 32: (PDWord(FCurrentOutputScanline)+x)^ := AColorIndex; 231 end; 232 end; 233 234 function TDitheringToIndexedImage.GetScanline(Y: NativeInt): Pointer; 235 begin 236 if FLineOrder = riloTopToBottom then 237 result := FCurrentData + Y*FCurrentScanlineSize 238 else 239 result := FCurrentData + (FCurrentMaxY-Y)*FCurrentScanlineSize 240 end; 241 242 procedure TDitheringToIndexedImage.SetIgnoreAlpha(AValue: boolean); 243 begin 244 if FIgnoreAlpha=AValue then Exit; 245 FIgnoreAlpha:=AValue; 246 end; 247 248 procedure TDitheringToIndexedImage.SetTransparentColorIndex(AValue: integer); 249 begin 250 if FTransparentColorIndex=AValue then Exit; 251 FTransparentColorIndex:=AValue; 252 end; 253 254 function TDitheringToIndexedImage.GetTransparentColorIndex: integer; 255 begin 256 result := FTransparentColorIndex; 257 end; 258 259 procedure TDitheringToIndexedImage.SetPalette(AValue: TBGRACustomApproxPalette); 260 begin 261 if FPalette=AValue then Exit; 262 FPalette:=AValue; 263 end; 264 265 procedure TDitheringToIndexedImage.SetLineOrder(AValue: TRawImageLineOrder); 266 begin 267 if FLineOrder=AValue then Exit; 268 FLineOrder:=AValue; 269 end; 270 271 procedure TDitheringToIndexedImage.SetBitOrder(AValue: TRawImageBitOrder); 272 begin 273 if FBitOrder=AValue then Exit; 274 FBitOrder:=AValue; 275 end; 276 277 constructor TDitheringToIndexedImage.Create(APalette: TBGRACustomApproxPalette; AIgnoreAlpha: boolean; ABitsPerPixelForIndices: integer); 278 begin 279 BitsPerPixel:= ABitsPerPixelForIndices; 280 BitOrder := riboReversedBits; //convention in BMP format 281 {$IFDEF ENDIAN_LITTLE} 282 ByteOrder:= riboLSBFirst; 283 {$ELSE} 284 ByteOrder:= riboMSBFirst; 285 {$ENDIF} 286 Palette := APalette; 287 IgnoreAlpha:= AIgnoreAlpha; 288 end; 289 290 constructor TDitheringToIndexedImage.Create(APalette: TBGRACustomApproxPalette; AIgnoreAlpha: boolean; ABitsPerPixelForIndices: integer; 291 AByteOrder: TRawImageByteOrder); 292 begin 293 BitsPerPixel:= ABitsPerPixelForIndices; 294 BitOrder := riboReversedBits; //convention in BMP format 295 ByteOrder:= AByteOrder; 296 Palette := APalette; 297 IgnoreAlpha:= AIgnoreAlpha; 298 end; 299 300 function TDitheringToIndexedImage.ComputeMinimumScanlineSize( 301 AWidthInPixels: integer): PtrInt; 302 begin 303 result := (AWidthInPixels*FBitsPerPixel+7) shr 3; 304 end; 305 306 function TDitheringToIndexedImage.AllocateSpaceForIndexedData(AImage: TBGRACustomBitmap; 307 AScanlineSize: PtrInt): pointer; 308 var size: integer; 309 begin 310 size := AScanlineSize * AImage.Height; 311 GetMem(result, size); 312 Fillchar(result^, size, 0); 313 end; 314 315 function TDitheringToIndexedImage.DitherImage(AAlgorithm: TDitheringAlgorithm; 316 AImage: TBGRACustomBitmap): Pointer; 317 begin 318 result := DitherImage(AAlgorithm, AImage, ComputeMinimumScanlineSize(AImage.Width)); 319 end; 320 321 procedure TDitheringToIndexedImage.DitherImageTo(AAlgorithm: TDitheringAlgorithm; 322 AImage: TBGRACustomBitmap; AData: Pointer); 323 begin 324 DitherImageTo(AAlgorithm, AImage, AData, ComputeMinimumScanlineSize(AImage.Width)); 325 end; 326 327 function TDitheringToIndexedImage.DitherImage(AAlgorithm: TDitheringAlgorithm; 328 AImage: TBGRACustomBitmap; AScanlineSize: PtrInt): Pointer; 329 begin 330 result := AllocateSpaceForIndexedData(AImage, AScanlineSize); 331 DitherImageTo(AAlgorithm, AImage, result, AScanlineSize); 332 end; 333 334 procedure TDitheringToIndexedImage.DitherImageTo(AAlgorithm: TDitheringAlgorithm; 335 AImage: TBGRACustomBitmap; AData: Pointer; AScanlineSize: PtrInt); 336 var ditherTask: TDitheringTask; 337 begin 338 FCurrentOutputY := -1; 339 FCurrentOutputScanline := nil; 340 FCurrentData := AData; 341 FCurrentMaxY:= AImage.Height-1; 342 FCurrentScanlineSize:= AScanlineSize; 343 344 ditherTask := CreateDitheringTask(AAlgorithm, AImage, FPalette, FIgnoreAlpha); 345 try 346 ditherTask.Inplace := True; //do not allocate destination 347 if BitsPerPixel >= 8 then 348 ditherTask.OnOutputPixel := @OutputPixelFullByte 349 else 350 begin 351 ditherTask.OnOutputPixel:= @OutputPixelSubByte; 352 if BitOrder = riboBitsInOrder then 353 FCurrentBitOrderMask := 0 354 else 355 FCurrentBitOrderMask := $ff; 356 end; 357 ditherTask.Execute; 358 finally 359 ditherTask.Free; 360 end; 361 end; 362 70 363 { TDitheringTask } 364 365 procedure TDitheringTask.OutputPixel(X, Y: NativeInt; AColorIndex: NativeInt; 366 AColor: TBGRAPixel); 367 begin 368 if Y <> FCurrentOutputY then 369 begin 370 FCurrentOutputY := Y; 371 FCurrentOutputScanline := Destination.ScanLine[y]; 372 end; 373 PutPixels(FCurrentOutputScanline+x, @AColor, 1, FDrawMode, 255); 374 end; 375 376 procedure TDitheringTask.ApproximateColor(const AColor: TBGRAPixel; 377 out AApproxColor: TBGRAPixel; out AIndex: integer); 378 begin 379 if FPalette <> nil then 380 begin 381 AIndex := FPalette.FindNearestColorIndex(AColor, FIgnoreAlpha); 382 if AIndex = -1 then 383 AApproxColor := BGRAPixelTransparent 384 else 385 AApproxColor := FPalette.Color[AIndex]; 386 end else 387 begin 388 if AColor.alpha = 0 then 389 begin 390 AApproxColor := BGRAPixelTransparent; 391 AIndex := -1; 392 end else 393 begin 394 AApproxColor := AColor; 395 AIndex := 0; 396 end; 397 end; 398 end; 399 400 constructor TDitheringTask.Create(ASource: IBGRAScanner; 401 APalette: TBGRACustomApproxPalette; ADestination: TBGRACustomBitmap; 402 AIgnoreAlpha: boolean; ABounds: TRect); 403 begin 404 FPalette := APalette; 405 SetSource(ASource); 406 FBounds := ABounds; 407 FIgnoreAlpha:= AIgnoreAlpha; 408 FCurrentOutputY := -1; 409 FCurrentOutputScanline:= nil; 410 OnOutputPixel:= @OutputPixel; 411 Destination := ADestination; 412 FDrawMode:= dmSet; 413 end; 71 414 72 415 constructor TDitheringTask.Create(bmp: TBGRACustomBitmap; … … 75 418 begin 76 419 FPalette := APalette; 77 FSource := bmp;420 SetSource(bmp); 78 421 FBounds := ABounds; 79 422 FIgnoreAlpha:= AIgnoreAlpha; 80 if AInPlace then Destination := FSource; 423 FCurrentOutputY := -1; 424 FCurrentOutputScanline:= nil; 425 OnOutputPixel:= @OutputPixel; 426 InPlace := AInPlace; 427 FDrawMode:= dmSet; 81 428 end; 82 429 … … 85 432 begin 86 433 FPalette := APalette; 87 FSource := bmp;434 SetSource(bmp); 88 435 FBounds := rect(0,0,bmp.Width,bmp.Height); 89 436 FIgnoreAlpha:= AIgnoreAlpha; 90 if AInPlace then Destination := FSource; 437 FCurrentOutputY := -1; 438 FCurrentOutputScanline:= nil; 439 OnOutputPixel:= @OutputPixel; 440 InPlace := AInPlace; 441 FDrawMode:= dmSet; 91 442 end; 92 443 … … 125 476 126 477 var 127 p,pNext,pDest: PBGRAPixel; 478 p,pNext: PExpandedPixel; 479 destX,destY: NativeInt; 128 480 orig,cur,approxExp: TExpandedPixel; 129 481 approx: TBGRAPixel; 482 approxIndex: integer; 130 483 curPix,diff: TAccPixel; 131 484 i: NativeInt; 132 485 yWrite: NativeInt; 133 486 tempLine, currentLine, nextLine: TLine; 487 488 nextScan,curScan: PExpandedPixel; 134 489 135 490 function ClampWordDiv(AValue: NativeInt): Word; inline; … … 158 513 setlength(currentLine,w); 159 514 setlength(nextLine,w); 515 curScan := nil; 516 nextScan := RequestSourceExpandedScanLine(FBounds.Left, FBounds.Top, FBounds.Right-FBounds.Left); 160 517 for yWrite := 0 to h-1 do 161 518 begin 162 519 if GetShouldStop(yWrite) then break; 163 p := FSource.ScanLine[yWrite+FBounds.Top]+FBounds.Left; 164 pDest := FDestination.ScanLine[yWrite+FBounds.Top]+FBounds.Left; 520 ReleaseSourceExpandedScanLine(curScan); 521 curScan := nextScan; 522 nextScan := nil; 523 p := curScan; 524 destX := FBounds.Left; 525 destY := yWrite+FBounds.Top; 165 526 if yWrite < h-1 then 166 pNext := FSource.ScanLine[yWrite+FBounds.Top+1]+FBounds.Left 167 else 168 pNext := nil; 527 nextScan := RequestSourceExpandedScanLine(FBounds.Left,yWrite+FBounds.Top+1, FBounds.Right-FBounds.Left); 528 pNext := nextScan; 169 529 if odd(yWrite) then 170 530 begin 171 531 inc(p, w); 172 inc( pDest, w);532 inc(destX, w); 173 533 if pNext<>nil then inc(pNext, w); 174 534 for i := w-1 downto 0 do 175 535 begin 176 536 dec(p); 177 dec( pDest);537 dec(destX); 178 538 if pNext<>nil then dec(pNext); 179 539 if p^.alpha <> 0 then 180 540 begin 181 orig := GammaExpansion(p^);541 orig := p^; 182 542 with currentLine[i] do 183 543 begin … … 191 551 cur.blue := ClampWordDiv(curPix.blue); 192 552 end; 193 approx := FPalette.FindNearestColor(GammaCompression(cur), FIgnoreAlpha);553 ApproximateColor(GammaCompression(cur), approx, approxIndex); 194 554 approxExp := GammaExpansion(approx); 195 555 diff.alpha := Div16(curPix.alpha - (approxExp.alpha shl ErrorPrecisionShift)); … … 207 567 if i > 0 then 208 568 begin 209 if AbsRGBADiff( GammaExpansion((p-1)^),orig) < MaxColorDiffForDiffusion then569 if AbsRGBADiff((p-1)^,orig) < MaxColorDiffForDiffusion then 210 570 AddError(currentLine[i-1], diff, 7); 211 571 end; … … 214 574 if i > 0 then 215 575 begin 216 if AbsRGBADiff( GammaExpansion((pNext-1)^),orig) < MaxColorDiffForDiffusion then576 if AbsRGBADiff((pNext-1)^,orig) < MaxColorDiffForDiffusion then 217 577 AddError(nextLine[i-1], diff, 1); 218 578 end; 219 if AbsRGBADiff( GammaExpansion(pNext^),orig) < MaxColorDiffForDiffusion then579 if AbsRGBADiff(pNext^,orig) < MaxColorDiffForDiffusion then 220 580 AddError(nextLine[i], diff, 5); 221 581 if i < w-1 then 222 582 begin 223 if AbsRGBADiff( GammaExpansion((pNext+1)^),orig) < MaxColorDiffForDiffusion then583 if AbsRGBADiff((pNext+1)^,orig) < MaxColorDiffForDiffusion then 224 584 AddError(nextLine[i+1], diff, 3); 225 585 end; 226 586 end; 227 pDest^ := approx;587 OnOutputPixel(destX,destY,approxIndex,approx); 228 588 end; 229 589 end … … 234 594 if p^.alpha <> 0 then 235 595 begin 236 orig := GammaExpansion(p^);596 orig := p^; 237 597 with currentLine[i] do 238 598 begin … … 246 606 cur.blue := ClampWordDiv(curPix.blue); 247 607 end; 248 approx := FPalette.FindNearestColor(GammaCompression(cur), FIgnoreAlpha);608 ApproximateColor(GammaCompression(cur), approx, approxIndex); 249 609 approxExp := GammaExpansion(approx); 250 610 diff.alpha := Div16(curPix.alpha - (approxExp.alpha shl ErrorPrecisionShift)); … … 262 622 if i < w-1 then 263 623 begin 264 if AbsRGBADiff( GammaExpansion((p+1)^),orig) < MaxColorDiffForDiffusion then624 if AbsRGBADiff((p+1)^,orig) < MaxColorDiffForDiffusion then 265 625 AddError(currentLine[i+1], diff, 7); 266 626 end; 267 if nextLine<> nil then627 if pNext <> nil then 268 628 begin 269 629 if i > 0 then 270 630 begin 271 if AbsRGBADiff( GammaExpansion((pNext-1)^),orig) < MaxColorDiffForDiffusion then631 if AbsRGBADiff((pNext-1)^,orig) < MaxColorDiffForDiffusion then 272 632 AddError(nextLine[i-1], diff, 3); 273 633 end; 274 if AbsRGBADiff( GammaExpansion(pNext^),orig) < MaxColorDiffForDiffusion then634 if AbsRGBADiff(pNext^,orig) < MaxColorDiffForDiffusion then 275 635 AddError(nextLine[i], diff, 5); 276 636 if i < w-1 then 277 637 begin 278 if AbsRGBADiff( GammaExpansion((pNext+1)^),orig) < MaxColorDiffForDiffusion then638 if AbsRGBADiff((pNext+1)^,orig) < MaxColorDiffForDiffusion then 279 639 AddError(nextLine[i+1], diff, 1); 280 640 end; 281 641 end; 282 pDest^ := approx;642 OnOutputPixel(destX,destY,approxIndex,approx); 283 643 end; 284 644 inc(p); 285 inc( pDest);645 inc(destX); 286 646 if pNext<>nil then inc(pNext); 287 647 end; … … 300 660 end; 301 661 end; 302 FDestination.InvalidateBitmap; 662 ReleaseSourceExpandedScanLine(curScan); 663 ReleaseSourceExpandedScanLine(nextScan); 664 Destination.InvalidateBitmap; 303 665 end; 304 666 … … 306 668 307 669 procedure TNearestColorTask.DoExecute; 308 var yb,xb: integer; 309 psrc,pdest: PBGRAPixel; 670 var yb,xb: NativeInt; 671 curScan,psrc: PBGRAPixel; 672 colorIndex: LongInt; 673 colorValue: TBGRAPixel; 310 674 begin 311 675 for yb := FBounds.Top to FBounds.Bottom - 1 do 312 676 begin 313 677 if GetShouldStop(yb) then break; 314 psrc := FSource.ScanLine[yb] + FBounds.Left;315 p dest := FDestination.ScanLine[yb] + FBounds.Left;316 for xb := FBounds. Right - FBounds.Left -1 downto 0do678 curScan := RequestSourceScanLine(FBounds.Left,yb,FBounds.Right-FBounds.Left); 679 psrc := curScan; 680 for xb := FBounds.Left to FBounds.Right-1 do 317 681 begin 318 pdest^ := FPalette.FindNearestColor(psrc^, FIgnoreAlpha);319 inc(pdest);682 ApproximateColor(psrc^, colorValue, colorIndex); 683 OnOutputPixel(xb,yb,colorIndex,colorValue); 320 684 inc(psrc); 321 685 end; 322 end; 323 FDestination.InvalidateBitmap; 686 ReleaseSourceScanLine(curScan); 687 end; 688 Destination.InvalidateBitmap; 324 689 end; 325 690
Note:
See TracChangeset
for help on using the changeset viewer.