Изменение цветовой палитры изображения

Мне необходимо изменить цветовую палитру изображения с помощью SetBitmapBits, но у меня, к сожалению, ничего не получается.
Использование SetBitmapBits - не очень хорошая идея, поскольку она имеет дело с HBitmaps, в котором формат пикселя не определен. Несомненно, это более безопасная операция, но никаких гарантий по ее выполнению дать невозможно.
Взамен я предлагаю использовать функции DIB API. Вот некоторый код, позволяющий вам изменять таблицу цветов. Просто напишите метод с такими же параметрами, как у TFiddleProc и и изменяйте ColorTable, передаваемое как параметр. Затем просто вызовите процедуру FiddleBitmap, передающую TBitmap и ваш fiddle-метод, например так:

FiddleBitmap( MyBitmap, Fiddler ) ;

type
 TFiddleProc = procedure(var ColorTable: TColorTable) of object;
const
 LogPaletteSize = sizeof(TLogPalette) + sizeof(TPaletteEntry) * 255;
function PaletteFromDIB(BitmapInfo: PBitmapInfo): HPalette;
var
 LogPalette: PLogPalette;
 i: integer;
 Temp: byte;
begin
 with BitmapInfo^, bmiHeader do
 begin
  GetMem(LogPalette, LogPaletteSize);
  try
  with LogPalette^ do
  begin
  palVersion := $300;
  palNumEntries := 256;
  Move(bmiColors, palPalEntry, sizeof(TRGBQuad) * 256);
  for i := 0 to 255 do
  with palPalEntry[i] do
  begin
  Temp := peBlue;
  peBlue := peRed;
  peRed := Temp;
  peFlags := PC_NOCOLLAPSE;
  end;
  { создаем палитру }
  Result := CreatePalette(LogPalette^);
  end;
  finally
  FreeMem(LogPalette, LogPaletteSize);
  end;
 end;
end;
{ Следующая процедура на основе изображения создает DIB,
изменяет ее таблицу цветов, создавая тем самым новую палитру,
после чего передает ее обратно изображению. При этом
используется метод косвенного вызова, с помощью которого
изменяется палитра цветов - ей передается array[ 0..255 ] of TRGBQuad. }

procedure FiddleBitmap(Bitmap: TBitmap; FiddleProc: TFiddleProc);
const
 BitmapInfoSize = sizeof(TBitmapInfo) + sizeof(TRGBQuad) * 255;
var
 BitmapInfo: PBitmapInfo;
 Pixels: pointer;
 InfoSize: integer;
 ADC: HDC;
 OldPalette: HPalette;
begin
 { получаем DIB }
 GetMem(BitmapInfo, BitmapInfoSize);
 try
  { меняем таблицу цветов - ПРИМЕЧАНИЕ: она использует 256 цветов DIB }
  FillChar(BitmapInfo^, BitmapInfoSize, 0);
  with BitmapInfo^.bmiHeader do
  begin
  biSize := sizeof(TBitmapInfoHeader);
  biWidth := Bitmap.Width;
  biHeight := Bitmap.Height;
  biPlanes := 1;
  biBitCount := 8;
  biCompression := BI_RGB;
  biClrUsed := 256;
  biClrImportant := 256;
  GetDIBSizes(Bitmap.Handle, InfoSize, biSizeImage);
  { распределяем место для пикселей }
  Pixels := GlobalAllocPtr(GMEM_MOVEABLE, biSizeImage);
  try
  { получаем пиксели DIB }
  ADC := GetDC(0);
  try
  OldPalette := SelectPalette(ADC, Bitmap.Palette, false);
  try
  RealizePalette(ADC);
  GetDIBits(ADC, Bitmap.Handle, 0, biHeight, Pixels, BitmapInfo^,
  DIB_RGB_COLORS);
  finally
  SelectPalette(ADC, OldPalette, true);
  end;
  finally
  ReleaseDC(0, ADC);
  end;
  { теперь изменяем таблицу цветов }
  FiddleProc(PColorTable(@BitmapInfo^.bmiColors)^);
  { создаем палитру на основе новой таблицы цветов }
  Bitmap.Palette := PaletteFromDIB(BitmapInfo);
  OldPalette := SelectPalette(Bitmap.Canvas.Handle, Bitmap.Palette,
  false);
  try
  RealizePalette(Bitmap.Canvas.Handle);
  StretchDIBits(Bitmap.Canvas.Handle, 0, 0, biWidth, biHeight, 0, 0,
  biWidth, biHeight,
  Pixels, BitmapInfo^, DIB_RGB_COLORS, SRCCOPY);
  finally
  SelectPalette(Bitmap.Canvas.Handle, OldPalette, true);
  end;
  finally
  GlobalFreePtr(Pixels);
  end;
  end;
 finally
  FreeMem(BitmapInfo, BitmapInfoSize);
 end;
end;
{ Пример "fiddle"-метода }
procedure TForm1.Fiddler(var ColorTable: TColorTable);
var
 i: integer;
begin
 for i := 0 to 255 do
  with ColorTable[i] do
  begin
  rgbRed := rgbRed * 9 div 10;
  rgbGreen := rgbGreen * 9 div 10;
  rgbBlue := rgbBlue * 9 div 10;
  end;
end;


Взято с http://delphiworld.narod.ru

Отправить комментарий

Проверка
Антиспам проверка
Image CAPTCHA
...