Пpогpаммист пошел покупать свитеp, но свитеpа были неподходящих цветов.
- Hичего, - подумал пpогpаммист - Пpиду домой сменю палитpу!
Мне необходимо изменить цветовую палитру изображения с помощью
SetBitmapBits, но у меня, к сожалению, ничего не получается.
Использование SetBitmapBits - не очень хорошая идея, поскольку она имеет дело
с HBitmaps, в котором формат пикселя не определен. Несомненно, это более
безопасная операция, но никаких гарантий по ее выполнению дать невозможно.
Взамен я предлагаю использовать функции DIB API. Вот некоторый код,
позволяющий вам изменять таблицу цветов. Просто напишите метод с такими же
параметрами, как у TFiddleProc и и изменяйте ColorTable, передаваемое как
параметр. Затем просто вызовите процедуру FiddleBitmap, передающую TBitmap и ваш
fiddle-метод, например так:
FiddleBitmap( MyBitmap, Fiddler ) ;
type
TFiddleProc = procedure(var ColorTable: TColorTable) ofobject;
const
LogPaletteSize = sizeof(TLogPalette) + sizeof(TPaletteEntry) * 255;
function PaletteFromDIB(BitmapInfo: PBitmapInfo): HPalette;
var
LogPalette: PLogPalette;
i: integer;
Temp: byte;
beginwith BitmapInfo^, bmiHeader dobegin
GetMem(LogPalette, LogPaletteSize);
trywith LogPalette^ dobegin
palVersion := $300;
palNumEntries := 256;
Move(bmiColors, palPalEntry, sizeof(TRGBQuad) * 256);
for i := 0 to 255 dowith palPalEntry[i] dobegin
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 dobegin
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;
beginfor i := 0 to 255 dowith ColorTable[i] dobegin
rgbRed := rgbRed * 9 div 10;
rgbGreen := rgbGreen * 9 div 10;
rgbBlue := rgbBlue * 9 div 10;
end;
end;
Here is the translation of the content into Russian:
Программа ChangeBitmapPalette была изменена с учетом предложений и советов. Она теперь создает палету на основе нового цветового таблицы.
В процедуре FiddleBitmap добавлены операции для корректного освобождения памяти, выделенной для пикселей и функции PaletteFromDIB. Палета теперь создается на основе новой цветовой таблицы.
Пример метода "фиддл" Fiddler изменяет цвет каждого пикселя в битмапе, уменьшая его красный, зеленый и синий компоненты.
Вы можете запустить эту программу, чтобы увидеть, как она изменяет цвет битмапы.
Изменение цветовой палитры изображения с помощью функций DIB API и косвенного вызова метода для изменения таблицы цветов.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.