2009-08-06 89 views
2

我已經搜索了幾個小時的網,但我無法找到如何從TPicture.Graphic得到調色板東西。我還需要獲取顏色值,以便我可以將這些值傳遞給TStringList以在Color Picker中填充單元格。如何訪問TPicture.Graphic的調色板?

這裏是我目前擁有的代碼:我繪製ABitmap與包含在Image1.Picture.Graphic圖像畫布

procedure TFormMain.OpenImage1Click(Sender: TObject); 
var 
    i: integer; 
    S: TStringList; 
    AColor: TColor; 
    AColorCount: integer; 
    N: string; 
    Pal: PLogPalette; 
    HPal: hPalette; 
begin 
    if OpenPictureDialog1.Execute then 
    begin 
    Screen.Cursor := crHourGlass; 
    try 
     Pal := nil; 
     try 
     S := TStringList.Create; 
     ABitmap.Free; // Release any existing bitmap 
     ABitmap := TBitmap.Create; 
     Image1.Picture.LoadFromFile(OpenPictureDialog1.Filename); 
     ABitmap.Canvas.Draw(0, 0, Image1.Picture.Graphic); 
     GetMem(Pal, Sizeof(TLogPalette) + Sizeof(TPaletteEntry) * 255); 
     Pal.palversion := $300; 
     Pal.palnumentries := 256; 
     for i := 0 to 255 do 
     begin 
      AColor := Pal.PalPalEntry[ i ].PeRed shl 16 + Pal.PalPalEntry[ i ].PeGreen shl 8 + Pal.PalPalEntry[ i ].PeBlue; 
      N := ColorToString(AColor); 
      S.Add(N); 
     end; 
     HPal := CreatePalette(Pal^); 
     ABitmap.Palette := HPal; 
     Memo1.Lines := S; 
     finally; FreeMem(Pal); end; 
     S.Free; 
    finally; Screen.Cursor := crDefault; end; 
    end; 
end; 

,因爲我要支持所有TPicture的圖像類型如Bitmap ,Jpeg,PngImage和GIfImg。

任何援助將不勝感激。我在正確的道路上還是需要不同的東西?

+0

我編輯了您的問題標題並刪除了第一個句子,因爲問題似乎是隻能訪問現有的調色板,而不是創建一個。 – mghie 2009-08-08 07:32:31

回答

3

您發佈的代碼不會真的沒什麼。你要麼必須閱讀調色板從位圖後面,然後才能訪問它,或者你需要創建一個調色板並將其分配給一個位圖 - 你的代碼既不。

下面的代碼或多或少是你的,其操作結果爲fBitmapfBitmapPalEntries。我評論的一切,我改變了線路:

if OpenPictureDialog1.Execute then 
    begin 
    Screen.Cursor := crHourGlass; 
    try 
     Pal := nil; 
     try 
     S := TStringList.Create; 
     fBitmap.Free; // Release any existing bitmap 
     fBitmap := TBitmap.Create; 
// if you want a 256 colour bitmap with a palette you need to say so 
     fBitmap.PixelFormat := pf8bit; 
     Image1.Picture.LoadFromFile(OpenPictureDialog1.Filename); 
     fBitmap.Canvas.Draw(0, 0, Image1.Picture.Graphic); 
// access the palette only if bitmap has indeed one 
     if fBitmap.Palette <> 0 then begin 
      GetMem(Pal, Sizeof(TLogPalette) + Sizeof(TPaletteEntry) * 255); 
      Pal.palversion := $300; 
      Pal.palnumentries := 256; 
// read palette data from bitmap 
      fBitmapPalEntries := GetPaletteEntries(fBitmap.Palette, 0, 256, 
      Pal.palPalEntry[0]); 
      for i := 0 to fBitmapPalEntries - 1 do 
      begin 
      AColor := Pal.PalPalEntry[ i ].PeRed shl 16 
        + Pal.PalPalEntry[ i ].PeGreen shl 8 
        + Pal.PalPalEntry[ i ].PeBlue; 
      N := ColorToString(AColor); 
      S.Add(N); 
      end; 
// doesn't make sense, the palette is already there 
//  HPal := CreatePalette(Pal^); 
//  fBitmap.Palette := HPal; 
      Memo1.Lines := S; 
     end; 
     finally; FreeMem(Pal); end; 
     S.Free; 
    finally; Screen.Cursor := crDefault; end; 
    end; 

支持調色板用更少的條目很容易,你只需要你知道後有多少項有重新分配內存,類似

ReallocMem(Pal, SizeOf(TLogPalette) + SizeOf(TPaletteEntry) * (fBitmapPalEntries - 1)); 

創建一個調色板,如果你想在pf4Bitpf8Bit格式寫一個位圖只會是必要的。您需要確定調色板條目的16或256種顏色,可能通過減少顏色數量(抖動)。然後,您將使用顏色值填充調色板顏色槽,最後使用我在代碼中註釋掉的兩條線。您必須確保位圖的像素格式和調色板條目數匹配。

+0

感謝您的回答。我正在研究由mghie重寫的代碼。任何想法如何獲得像素格式的fBitmap,因爲它不直接從文件加載? – 2009-08-06 21:41:27

0

我不知道我自己,但你可以看看XN Resource Editor,它顯示調色板信息,是用Delphi編寫的,並有源代碼可用。

+0

我已經花了幾個小時與這個源代碼,其中一些是不完整的,我認爲。該代碼是爲Delphi 7而且非常複雜....至少對我來說是這樣的。 – 2009-08-06 20:28:37

1

圖形alogithms的一個美妙的資源可用efg's reference library其中包括一個特定部分處理的只是顏色。具體來說,this文章(含源代碼)討論了計算可用顏色並可能是最佳用法。

0

謝謝大家....尤其是mghie。我們設法讓代碼很好地工作BMP,PNG和GIF文件和pf1bit,pf4bit,pf8bit,pf16bit和pf24bit圖像。我們仍在測試代碼,但迄今爲止它似乎工作得很好。希望這段代碼也能幫助其他開發者。

var 
    i: integer; 
    fStringList: TStringList; 
    fColor: TColor; 
    fColorString: string; 
    fPal: PLogPalette; 
    fBitmapPalEntries: Cardinal; 
begin 
    if OpenPictureDialog1.Execute then 
    begin 
    Screen.Cursor := crHourGlass; 
    try 
     fPal := nil; 
     try 
     fStringList := TStringList.Create; 
     Image1.Picture.LoadFromFile(OpenPictureDialog1.Filename); 
     if Image1.Picture.Graphic.Palette <> 0 then 
     begin 
      GetMem(fPal, Sizeof(TLogPalette) + Sizeof(TPaletteEntry) * 255); 
      fPal.palversion := $300; 
      fPal.palnumentries := 256; 
      fBitmapPalEntries := GetPaletteEntries(Image1.Picture.Graphic.Palette, 0, 256, fPal.palPalEntry[ 0 ]); 
      for i := 0 to fBitmapPalEntries - 1 do 
      begin 
      fColor := fPal.PalPalEntry[ i ].PeBlue shl 16 
       + fPal.PalPalEntry[ i ].PeGreen shl 8 
       + fPal.PalPalEntry[ i ].PeRed; 
      fColorString := ColorToString(fColor); 
      fStringList.Add(fColorString); 
      end; 
     end; 
     finally; FreeMem(fPal); end; 
     if fStringList.Count = 0 then 
     ShowMessage('No palette entries!') 
     else 
     // add the colors to the colorpicker here 
     fStringList.Free; 
    finally; Screen.Cursor := crDefault; end; 
    end;