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

DelphiX 實戰:TDIB.DoPosterize 海報化/色階量化

     編輯:Delphi

TDIB.DoPosterize 將影像每個色彩通道量化到指定階數,產生海報化效果(色帶分明、層次簡化)。本文提供三種階數對比範例。

效果預覽

DoPosterize 效果

核心程式碼

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; // 50 階
    Button3: TButton; // 150 階
    Button4: TButton; // 250 階
    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
  // DoPosterize(Levels: Integer)  // 每通道量化階數
  DXPaintBox1.DIB.DoPosterize(50);
  DXPaintBox1.Repaint;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  DXPaintBox1.DIB.DoPosterize(150);
  DXPaintBox1.Repaint;
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  DXPaintBox1.DIB.DoPosterize(250);
  DXPaintBox1.Repaint;
end;
end.

參數與效果對照

Levels每通道色階總理論色數視覺效果
228極度抽象、波普藝術
4464強烈色帶、向量插畫感
88512明顯海報化
16164K輕度簡化
5050125K中度海報化(範例)
1501503.3M接近真彩、細微色帶
25025015.6M極接近原圖、極細色帶
25625616.7M無量化(原圖)

演算法原理

各通道獨立量化:Quantized = Round(Original / 255 * (Levels-1)) * (255 / (Levels-1))

  • 不同於 Greyscale(Levels):Posterize 保留彩色,各通道獨立量化
  • 不同於 DoColorize:Posterize 不映射到指定雙色,保留原相對色彩關係

應用場景

  • **藝術風格化**:波普藝術、安迪·沃荷風、平面插畫
  • **向量化預處理**:位圖轉向量前簡化色階
  • **色彩壓縮**:減少調色盤大小、檔案體積
  • **視覺化簡化**:複雜照片轉簡潔示意圖
  • **復古遊戲風**:模擬舊世代主機有限調色盤

進階:自適應海報化(K-means 量化)

固定階數量化不考慮圖像色彩分佈。K-means 聚類可找到最具代表性的顏色:


procedure AdaptivePosterize(DIB: TDIB; K: Integer);
var Palette: array of TColor; Labels: array of Byte; // 簡化版
    x, y, i, iter: Integer; c: TRGBQuad; dist, minDist: Integer; centroid: TColor;
begin
  SetLength(Palette, K); SetLength(Labels, DIB.Width * DIB.Height);
  // 1. 隨機初始化 K 個質心
  for i := 0 to K-1 do Palette[i] := DIB.Pixels[Random(DIB.Width), Random(DIB.Height)];
  // 2. 迭代收斂(簡化:固定 10 迭代)
  for iter := 0 to 9 do begin
    // 指派
    for y := 0 to DIB.Height - 1 do
      for x := 0 to DIB.Width - 1 do begin
        c := DIB.Pixels[x, y]; minDist := MaxInt;
        for i := 0 to K-1 do begin
          dist := Sqr(c.rgbRed - GetRValue(Palette[i])) +
                  Sqr(c.rgbGreen - GetGValue(Palette[i])) +
                  Sqr(c.rgbBlue - GetBValue(Palette[i]));
          if dist < minDist then begin minDist := dist; Labels[y*DIB.Width+x] := i; end;
        end;
      end;
    // 更新質心
    for i := 0 to K-1 do begin
      var cnt := 0; var sr, sg, sb: Integer;
      for y := 0 to DIB.Height - 1 do
        for x := 0 to DIB.Width - 1 do
          if Labels[y*DIB.Width+x] = i then begin
            c := DIB.Pixels[x, y]; Inc(sr, c.rgbRed); Inc(sg, c.rgbGreen); Inc(sb, c.rgbBlue); Inc(cnt);
          end;
      if cnt > 0 then Palette[i] := RGB(sr div cnt, sg div cnt, sb div cnt);
    end;
  end;
  // 3. 套用
  for y := 0 to DIB.Height - 1 do
    for x := 0 to DIB.Width - 1 do
      DIB.Pixels[x, y] := Palette[Labels[y*DIB.Width+x]];
end;
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved