2009-08-06 6 views
2

몇 시간 동안 웹을 검색했지만 TPicture.Graphic에서 팔레트를 가져 오는 방법을 찾을 수 없습니다. colorpicker에 셀을 채우기 위해이 값들을 TStringList에 전달할 수 있도록 색상 값을 가져와야합니다. 나는 그런 비트 맵 모든 TPicture 이미지 형식을 지원하기 원하기 때문에TPicture.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; 

내가 Image1.Picture.Graphic에 포함 된 이미지와 ABitmap의 캔버스에 그리기 오전 : 여기

내가 현재 가지고있는 코드입니다 , Jpeg, PngImage 및 GIfImg.

도움을 주시면 감사하겠습니다. 나는 올바른 길을 가고 있는가? 아니면 뭔가 다른 것이 필요한가?

+0

문제가 기존 팔레트에 대한 액세스 권한을 얻는 것이지 문제가있는 것 같기 때문에 질문 제목을 편집하고 첫 번째 문장을 제거했습니다. – mghie

답변

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)); 

같은 뭔가가 필요 : 나는 변경 모든 라인을 주석 팔레트를 만들려면 pf4Bit 또는 pf8Bit 형식의 비트 맵을 작성해야합니다. 색상 수 (디더링)를 줄임으로써 팔레트 항목 인 16 또는 256 색상을 결정해야합니다. 그런 다음 색상 값으로 팔레트 색상 슬롯을 채우고 마지막으로 코드에서 주석 처리 한 두 줄을 사용합니다. 비트 맵의 ​​픽셀 형식과 팔레트 항목 수가 일치하는지 확인해야합니다.

+0

답변 해 주셔서 감사합니다. mghie가 작성한 코드를 연구 중입니다. 파일에서 직접로드되지 않기 때문에 fBitmap의 pixelformat을 얻는 방법에 대한 아이디어가 있습니까? –

0

자신을 잘 모르지만 팔레트 정보를 표시하는 XN Resource Editor을보고 델파이로 작성되었으며 소스를 사용할 수 있습니다.

+0

나는이 소스 코드로 몇 시간을 보냈는데 그 중 일부는 불완전하다고 생각한다. 이 코드는 Delphi 7 용이며 매우 복잡합니다 .... 적어도 저에게는 있습니다. –

1

그림 논리 알고리즘의 멋진 리소스는 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; 
관련 문제