function ColorFill(Bitmap: TBitmap; FillColor: TColor): Boolean; (************************************************************************ This function is PUBLIC DOMAIN. The function takes a VCL TBitmap object and the FillColor (as TColor value) as parameters. There is the limitation, that the following color values are simply senseless and therefore unsupported: clNone and clDefault. Result: - If the Bitmap parameter contains a bitmap other than 24 or 32bit the function returns False and GetLastError yields ERROR_INVALID_DATA - If the FillColor is invalid, the function returns False and GetLastError will yield a value of ERROR_INVALID_PARAMETER - Else the function will signal success by returning True If it is intended to use the function on other pixel format's for now, there's the only workaround of changing the pixel format of the bitmap to one of the supported values and change it back afterwards ... e.g.: Bitmap.PixelFormat:=pf24bit; [v1.01 - Last update: 2003-06-27] Assarbad AT gmx DOT info | http://assarbad.net | http://assarbad.org ---------------------------------------------------------------------- History v1.01 [2003-06-27] - Fixed a bug with 24bit format which (as a side effect) increases speed for this pixel format. The old code always read 4 bytes instead of 3 - which read beyond the reserved memory and thus raised an exception! v1.00 [2003-06-22] - Initial public release ************************************************************************) var format: TPixelFormat; pxsize, x, y: Integer; pszBmp: PChar; begin result := False; // Save pixel format (we read only once but use it multiple times) format := Bitmap.PixelFormat; // Check if the input data is valid! Handle only 24 and 32 byte bitmaps case format of // Set pixel size pf24Bit: pxsize := 3; pf32bit: pxsize := 4; else SetLastError(ERROR_INVALID_DATA); // Fehler ... exit; // ... und raus! end; // Normalize the color value case FillColor of // Standard Windows colors can be queried through the GetSysColor API! clScrollBar, clBackground, clActiveCaption, clInactiveCaption, clMenu, clWindow, clWindowFrame, clMenuText, clWindowText, clCaptionText, clActiveBorder, clInactiveBorder, clAppWorkSpace, clHighlight, clHighlightText, clBtnFace, clBtnShadow, clGrayText, clBtnText, clInactiveCaptionText, clBtnHighlight, cl3DDkShadow, cl3DLight, clInfoText, clInfoBk: FillColor := GetSysColor(FillColor and (not $80000000)); // Invalid color values ... clNone, // We don't fill none ... clDefault: // We don't know what's default! begin SetLastError(ERROR_INVALID_PARAMETER); exit; end; end; // This case is obsolete for now ... but it will be needed if you extend the // number of supported pixel formats! case format of pf24Bit: // Do the job for full height for y := Bitmap.Height - 1 downto 0 do // ... and full width for x := Bitmap.Width - 1 downto 0 do try // Calculate offset of the DWORD to read pszBmp := PChar(Bitmap.ScanLine[y]) + x * pxsize; asm // Save registers push eax push esi // Actual routine mov esi, [pszBmp]; // Load fill color into eax mov eax, FillColor // TColor and Bitmap in memory have different byte order -> swap bytes bswap eax // Write back into the memory position (byte by byte to not raise an exception) mov [esi+0], ah shr eax, 16 mov [esi+1], ax // Restore registers pop esi pop eax end; except; end; pf32Bit: // Do the job for full height for y := Bitmap.Height - 1 downto 0 do // ... and full width for x := Bitmap.Width - 1 downto 0 do try // Calculate offset of the DWORD to read pszBmp := PChar(Bitmap.ScanLine[y]) + x * pxsize; asm // Save registers push eax push edx push esi // Actual routine mov esi, [pszBmp]; // Load color value (i.e. DWORD at pointer position) into edx mov edx, [esi] // Save the upper byte (next pixel for 24bit, Alpha for 32bit) and edx, $FF000000 // Load fill color into eax mov eax, FillColor // TColor and Bitmap in memory have different byte order -> swap bytes bswap eax // Now shift right by 8 bits because the important (previously lower) // 3 bytes are now the 3 upper ones -> shift them back // At this point the upper byte is $00 shr eax, 8 // Combine old upper byte and our fill color or eax, edx // Write back into the memory position mov [esi], eax // Restore registers pop esi pop edx pop eax end; except; end; end; // Force update on the bitmap Bitmap.Modified := True; result := True; end; function ColorMix(Bitmap: TBitmap; FillColor: TColor): Boolean; (************************************************************************ This function is PUBLIC DOMAIN. The function takes a VCL TBitmap object and the FillColor (as TColor value) as parameters. There is the limitation, that the following color values are simply senseless and therefore unsupported: clNone and clDefault. Result: - If the Bitmap parameter contains a bitmap other than 24 or 32bit the function returns False and GetLastError yields ERROR_INVALID_DATA - If the FillColor is invalid, the function returns False and GetLastError will yield a value of ERROR_INVALID_PARAMETER - Else the function will signal success by returning True If it is intended to use the function on other pixel format's for now, there's the only workaround of changing the pixel format of the bitmap to one of the supported values and change it back afterwards ... e.g.: Bitmap.PixelFormat:=pf24bit; [v1.00 - Last update: 2003-06-27] Assarbad AT gmx DOT info | http://assarbad.net | http://assarbad.org ---------------------------------------------------------------------- History v1.00 [2003-06-27] - Initial public release - Derived from ColorFill() ************************************************************************) var format: TPixelFormat; pxsize, x, y: Integer; pszBmp: PChar; begin result := False; // Save pixel format (we read only once but use it multiple times) format := Bitmap.PixelFormat; // Check if the input data is valid! Handle only 24 and 32 byte bitmaps case format of // Set pixel size pf24Bit: pxsize := 3; pf32bit: pxsize := 4; else SetLastError(ERROR_INVALID_DATA); // Fehler ... exit; // ... und raus! end; // Normalize the color value case FillColor of // Standard Windows colors can be queried through the GetSysColor API! clScrollBar, clBackground, clActiveCaption, clInactiveCaption, clMenu, clWindow, clWindowFrame, clMenuText, clWindowText, clCaptionText, clActiveBorder, clInactiveBorder, clAppWorkSpace, clHighlight, clHighlightText, clBtnFace, clBtnShadow, clGrayText, clBtnText, clInactiveCaptionText, clBtnHighlight, cl3DDkShadow, cl3DLight, clInfoText, clInfoBk: FillColor := GetSysColor(FillColor and (not $80000000)); // Invalid color values ... clNone, // We don't fill none ... clDefault: // We don't know what's default! begin SetLastError(ERROR_INVALID_PARAMETER); exit; end; end; // This case is obsolete for now ... but it will be needed if you extend the // number of supported pixel formats! case format of pf24Bit: // Do the job for full height for y := Bitmap.Height - 1 downto 0 do // ... and full width for x := Bitmap.Width - 1 downto 0 do try // Calculate offset of the DWORD to read pszBmp := PChar(Bitmap.ScanLine[y]) + x * pxsize; asm // Save registers push eax push edx push esi // Actual routine mov esi, [pszBmp]; // Zero out edx xor edx, edx // Copy original color value mov dl, [esi+2] shl edx, 16 mov dx, [esi+0] // Load fill color into eax mov eax, FillColor // TColor and Bitmap in memory have different byte order -> swap bytes bswap eax // Upper byte in eax is zero after next instruction shr eax, 8 // Combine the both color values ... or eax, edx // Write back into the memory position (byte by byte to not raise an exception) mov [esi+0], ax shr eax, 16 mov [esi+2], al // Restore registers pop esi push edx pop eax end; except; end; pf32Bit: // Do the job for full height for y := Bitmap.Height - 1 downto 0 do // ... and full width for x := Bitmap.Width - 1 downto 0 do try // Calculate offset of the DWORD to read pszBmp := PChar(Bitmap.ScanLine[y]) + x * pxsize; asm // Save registers push eax push edx push esi // Actual routine mov esi, [pszBmp]; // Load color value (i.e. DWORD at pointer position) into edx mov edx, [esi] // Save the upper byte (next pixel for 24bit, Alpha for 32bit) // and edx, $FF000000 // Load fill color into eax mov eax, FillColor // TColor and Bitmap in memory have different byte order -> swap bytes bswap eax // Now shift right by 8 bits because the important (previously lower) // 3 bytes are now the 3 upper ones -> shift them back // At this point the upper byte is $00 shr eax, 8 // Combine old upper byte and our fill color or eax, edx // Write back into the memory position mov [esi], eax // Restore registers pop esi pop edx pop eax end; except; end; end; // Force update on the bitmap Bitmap.Modified := True; result := True; end;