Recent

Author Topic: Bitmap Color Depth Reduction -  (Read 9229 times)

TheBlackSheep

  • Jr. Member
  • **
  • Posts: 93
Bitmap Color Depth Reduction -
« on: June 12, 2011, 09:58:06 pm »

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

  • Jr. Member
  • **
  • Posts: 93
Re: Bitmap Color Depth Reduction -
« Reply #1 on: June 12, 2011, 11:17:12 pm »

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

  • Hero Member
  • *****
  • Posts: 4181
    • Personal webpage
Re: Bitmap Color Depth Reduction -
« Reply #2 on: June 13, 2011, 04:03:59 pm »
Nice, I did not know there was Floyd-Steinberg algorithm in FP.
Conscience is the debugger of the mind

Enrique8

  • Newbie
  • Posts: 2
Re: Bitmap Color Depth Reduction -
« Reply #3 on: January 20, 2023, 11:58:39 pm »
Work wonders. Thank you.

Do you know how to create or customize an FPPalette: TFPPalette?  :)

geraldholdsworth

  • Full Member
  • ***
  • Posts: 195
Re: Bitmap Color Depth Reduction -
« Reply #4 on: February 01, 2023, 12:17:41 pm »
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][+][-]
  1. Ci:=0;
  2. RGB:=-1;
  3. for x:=0 to Length(FPalette)-1 do
  4. begin
  5.  Di:= abs(Red  -( FPalette[x]     AND$FF))
  6.      +abs(Green-((FPalette[x]>> 8)AND$FF))
  7.      +abs(Blue -((FPalette[x]>>16)AND$FF));
  8.  if(Di<Ci)or(RGB=-1)then
  9.  begin
  10.   Ci:=Di;
  11.   RGB:=x;
  12.  end;
  13. end;
This is lifted (almost) straight from my code:
FPalette is a Cardinal array containing the reference colours
RGB is the eventual colour reference (from the palette)
Red, Green and Blue are the starting colour components:
Code: Pascal  [Select][+][-]
  1. Red  := Colour     AND$FF;
  2. Green:=(Colour>> 8)AND$FF;
  3. 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.

 

TinyPortal © 2005-2018