将彩色位图转为pf8bit灰度图:设置像素格式后图像失真问题
解决pf8bit灰度图失真问题
你遇到的问题本质是:直接修改PixelFormat为pf8bit时,TBitmap会自动做通用颜色量化——它不知道你已经把图像转成灰度了,会把所有灰度色当成独立彩色压缩,自然出现类似GIF的失真。
要生成正确的pf8bit灰度图,不能靠自动格式转换,得手动把灰度值映射到预设的灰度调色板索引上,具体实现如下:
function CreateGrayPalette(NumColors: Integer = 256): HPALETTE; VAR i : Integer; lp : TMaxLogPalette; Grey: Byte; begin lp.palVersion := $300; lp.palNumEntries := NumColors; for i := 0 to NumColors - 1 do begin Grey := i * 255 DIV NumColors; lp.palPalEntry[i].peRed := Grey; lp.palPalEntry[i].peGreen := Grey; lp.palPalEntry[i].peBlue := Grey; lp.palPalEntry[i].peFlags := PC_RESERVED; end; Result := CreatePalette(pLogPalette(@lp)^); end; // 直接创建带灰度调色板的pf8bit Bitmap function CreateGray8BitBitmap(Width, Height: Integer): TBitmap; begin Result := TBitmap.Create; Result.PixelFormat := pf8bit; Result.Width := Width; Result.Height := Height; // 绑定灰度调色板 var GrayPalette := CreateGrayPalette; if GrayPalette <> 0 then begin Result.Palette := GrayPalette; DeleteObject(GrayPalette); // 绑定后释放调色板对象 end; end; {$R-} function GetGrayValue(Color: TColor): Byte; CONST LuminanceR = 54; // 亮度权重系数 LuminanceG = 184; LuminanceB = 18; begin Result := (((Color AND $00FF0000) SHR 16 * LuminanceR) + ((Color AND $0000FF00) SHR 8 * LuminanceG) + ((Color AND $000000FF) * LuminanceB)) SHR 8; end; {$R+} procedure ConvertToGrayscale(BMP: TBitmap); var GrayBMP: TBitmap; Row, Col: Integer; SrcLine: PDWord; DstLine: PByte; GrayVal: Byte; begin // 先把原图像转成32位方便读取像素 BMP.PixelFormat := pf32bit; // 创建目标8位灰度图 GrayBMP := CreateGray8BitBitmap(BMP.Width, BMP.Height); try // 逐行复制并转换灰度索引 for Row := 0 to BMP.Height - 1 do begin SrcLine := PDWord(BMP.ScanLine[Row]); DstLine := PByte(GrayBMP.ScanLine[Row]); for Col := 0 to BMP.Width - 1 do begin GrayVal := GetGrayValue(SrcLine^); DstLine^ := GrayVal; // 直接用灰度值作为调色板索引 Inc(SrcLine); Inc(DstLine); end; end; // 把结果替换回原BMP BMP.Assign(GrayBMP); finally GrayBMP.Free; end; end;
关键说明:
- 不再依赖TBitmap自动转换格式,手动创建pf8bit位图并绑定灰度调色板
- 每个像素的灰度值直接对应调色板索引(调色板索引i对应灰度值i),无需量化,直接映射避免失真
- 绑定调色板后调用
DeleteObject释放资源,防止内存泄漏
内容的提问来源于stack exchange,提问作者Error - CPU Not Foud
相关产品推荐
相关产品推荐

