首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

DelphiX 實戰:TDIB.Greyscale 灰階化與色階壓縮

     編輯:Delphi

TDIB.Greyscale 將彩色影像轉為灰階,並支援色階數壓縮(量化),可產生從平滑灰階到極少色階的藝術效果。本文提供四種色階數對比範例。

效果預覽

Greyscale 效果

核心程式碼

unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DIB, StdCtrls;
type
  TForm1 = class(TForm)
    DXPaintBox1: TDXPaintBox;
    Button1: TButton; // 載入圖片
    Button2: TButton; // 32 階灰階
    Button3: TButton; // 4 階灰階
    Button4: TButton; // 2 階(黑白)灰階
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
  end;
var Form1: TForm1;
implementation {$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
const ImgPath1 = 'C:\Temp\DX.jpg';
begin
  DXPaintBox1.DIB.LoadFromFile(ImgPath1);
  DXPaintBox1.Width := DXPaintBox1.DIB.Width;
  DXPaintBox1.Height := DXPaintBox1.DIB.Height;
  DXPaintBox1.Repaint;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  // Greyscale(Levels: Integer)
  DXPaintBox1.DIB.Greyscale(32);
  DXPaintBox1.Repaint;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  DXPaintBox1.DIB.Greyscale(4);
  DXPaintBox1.Repaint;
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  DXPaintBox1.DIB.Greyscale(1);
  DXPaintBox1.Repaint;
end;
end.

參數與效果對照

Levels色階數視覺效果應用
256256平滑灰階標準黑白照片
6464輕微階梯感漫畫網點預處理
3232明顯色帶海報化、藝術效果
1616強烈色帶復古遊戲畫面
44僅 4 階調極簡風格、圖示化
22純黑白(無灰)閾值二值化、OCR 前置
11全白/全黑特效遮罩

演算法原理

  1. 彩色轉灰階:Gray = 0.299*R + 0.587*G + 0.114*B(ITU-R BT.601)
  2. 量化:Quantized = Round(Gray / 255 * (Levels-1)) * (255 / (Levels-1))
  3. Levels=1 為特例:通常全映射為 0 或 255

應用場景

  • **藝術風格化**:海報化、像素藝術、復古遊戲
  • **列印優化**:灰階列印、墨水節省
  • **OCR/識別前置**:二值化(Levels=2)去除干擾色彩
  • **資料壓縮**:灰階 + 低色階 = 極小調色盤索引圖
  • **遮罩生成**:高對比灰階作 Alpha 遮罩來源

進階:誤差擴散抖動

單純量化會產生色帶。Floyd-Steinberg 抖動可在低色階下保留更多細節:


procedure GreyscaleDithered(DIB: TDIB; Levels: Integer);
var x, y: Integer; c: TRGBQuad; gray, quant, err: Integer;
    errR, errG, errB: array of array of Integer;
begin
  SetLength(errR, DIB.Width, DIB.Height); // 簡化:僅灰階誤差
  for y := 0 to DIB.Height - 1 do
    for x := 0 to DIB.Width - 1 do begin
      c := DIB.Pixels[x, y];
      gray := Round(0.299*c.rgbRed + 0.587*c.rgbGreen + 0.114*c.rgbBlue) + errR[x, y];
      quant := Round(gray / 255 * (Levels-1)) * (255 / (Levels-1));
      err := gray - quant;
      // 擴散到右、下、左下、右下
      if x+1 < DIB.Width then errR[x+1, y] := errR[x+1, y] + Round(err * 7/16);
      if y+1 < DIB.Height then begin
        if x-1 >= 0 then errR[x-1, y+1] := errR[x-1, y+1] + Round(err * 3/16);
        errR[x, y+1] := errR[x, y+1] + Round(err * 5/16);
        if x+1 < DIB.Width then errR[x+1, y+1] := errR[x+1, y+1] + Round(err * 1/16);
      end;
      c.rgbRed := quant; c.rgbGreen := quant; c.rgbBlue := quant;
      DIB.Pixels[x, y] := c;
    end;
end;
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved