Bitmap Color Depth Reduction - lazarus / 39-Graphics ---------------------------------------------------------------------- TheBlackSheep · 2011-06-12 19:58 I've been playing around with the FPImage to try and get some colour reduction (24bit  [16.7 Million colors] bitmaps down to 8 bit [256 color] bitmaps and came up with this which seems to work (at least with bitmaps copied from the clipboard) Code: [Select]procedure ReduceBitmapColors(BMPFile:String); var     SourceBitmap, TargetBitmap:  TFPMemoryImage;     FPMedianCutQuantizer : TFPMedianCutQuantizer;     FPPalette : TFPPalette;     FPFloydSteinbergDitherer:TFPFloydSteinbergDitherer;     ImageReader : TFPReaderBMP;     ImageWriter : TFPWriterBMP; begin   if FileExists(BMPFile) then begin     SourceBitmap := TFPMemoryImage.Create(0,0);     TargetBitmap := TFPMemoryImage.Create(0,0);     ImageReader := TFPReaderBMP.Create;     ImageWriter := TFPWriterBMP.create;     try       SourceBitmap.LoadFromFile(BMPFile);       FPMedianCutQuantizer  := TFPMedianCutQuantizer.Create;       FPMedianCutQuantizer.Add(SourceBitmap);       FPPalette := FPMedianCutQuantizer.Quantize;       FPFloydSteinbergDitherer := TFPFloydSteinbergDitherer.Create(FPPalette);       FPFloydSteinbergDitherer.Dither(SourceBitmap, TargetBitmap);       ImageWriter.BitsPerPixel:=8;       TargetBitmap.SaveToFile(BMPFile, ImageWriter);     finally       SourceBitmap.Free;       TargetBitmap.Free;       FPMedianCutQuantizer.Free;       FPFloydSteinbergDitherer.Free;       ImageReader.Free;       ImageWriter.Free;     end;   end; end;  To be honest not sure why it does work as, in the process of generating the target bitmap other than do some quantization (what I see to be the process of gathering the information needed for the dithering process) the dithering stage doesn't specify a value to dither to (i.e. the amount of colour reduction to be done).  The only point at which this is doen is the saving of the filetype but this is effectively after the process has occured. Nevertheless, Irfanview is reporting an initial 24bit color reduced to 8 bit color without a significant loss in color (yet a relatively significant decrease in filesize to about a third the original - just separate out the source/target filename to compare if required). Chris ---------------------------------------------------------------------- TheBlackSheep · 2011-06-12 21:17 couple of additions to the above in case anyone's interested... you'd need to include the following in the uses clause; .Code: [Select]..fpimage, FPDitherer, FPQuantizer, FPReadBMP, FPWriteBMP and to incorporate copy to/from the clipboard you'd could use; Code: [Select]procedure ClipboardReduction; const   TempClipFile:String = 'clipboard.bmp'; var   ClipboardBitmap:TBitmap; begin   ClipboardBitmap := TBitmap.Create;   try     ClipboardBitmap.LoadFromClipboardFormat(cf_bitmap);     ClipboardBitmap.SaveToFile(TempClipFile);     ReduceBitmapColors(TempClipFile);     ClipboardBitmap.LoadFromFile(TempClipFile);     Clipboard.Assign(ClipboardBitmap);   finally     ClipboardBitmap.Free;   end;   if FileExists(TempClipFile) then DeleteFile(TempClipFile);      end; However, using the clipboard doesn't really show you what's happening underneath as I think that the clipboard bitmap format actually appears to be the color depth of your graphics card regardless of the depth of the file you've just copied to it (at least I think that's how it works). So a higher-depth bitmap copied to the clipboard, processed and then put back again on the clipboard will still show the same color depth as the original although in theory it should be still a smaller size - obviously needs further investigation. Chris ---------------------------------------------------------------------- circular · 2011-06-13 14:03 Nice, I did not know there was Floyd-Steinberg algorithm in FP. ---------------------------------------------------------------------- Enrique8 · 2023-01-20 22:58 Work wonders. Thank you. Do you know how to create or customize an FPPalette: TFPPalette? ---------------------------------------------------------------------- geraldholdsworth · 2023-02-01 11:17 Nice to know, thank you. I've been using my own algorithm to reduce the number of colours for an 8 bit palette. This i based on "closest colour": Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Ci:=0;RGB:=-1;for x:=0 to Length(FPalette)-1 dobegin Di:= abs(Red  -( FPalette[x]     AND$FF))     +abs(Green-((FPalette[x]>> 8)AND$FF))     +abs(Blue -((FPalette[x]>>16)AND$FF)); if(Di> 8)AND$FF;Blue :=(Colour>>16)AND$FF;I then write directly to the bitmap header, as the format is a very simple layout and easy to understand.