Technology Learning

导航

(转)彩图变灰度图

将一幅图片转化成灰度图,具体来说应该分为以下几步:
1.提取图片的每一个象素的值,然后建立三个数据表,1->G 2->R 3->B.
2.为每一种颜色值建立一附图.
方法如下:
    若源图一点为 (R100,G200,B210),这相应的三附图的点颜色为1_(100,100,100), 2_(200,200,200),3_(210,210,210).
3. 你说希望寻求一种高效率的方法,但我个人认为什么方法可能都需要提取图片的每一个象素,你也不可能只是要将一幅图片转化成灰度图(否则这可用专门的software),往后来还是要知道每一个象素的数据.我做过这个程序,速度还可以(在386上).


上面是基于图片在屏幕上的方法,如果你的图片是文件就简单多了,在读文件时只分别读RGB,再写屏就可以了.



改palette最快, 灰度只有256阶, 用256色位图, 改掉palette就改变全图了.(只要循环256次).

你看这样行不行,速度比不上Another_eYes的方法快.但可以满足我的要求.



type
  TFColor  = record
              b,g,r:Byte
             end;
 
  PFColor  =^TFColor;

procedure Gray(srcBmp,DstBmp:TBitMap);
var
  x,y:                      Integer;
  Gr:                       Byte;
  incRow,Gap:               integer;
  DstTmp,SrcTmp:            PFColor;
  SrcBmInfo,DstBmInfo:      TBitmapInfo;
  SrcBmHeader,DstBmHeader:  TBitmapInfoHeader;
  width,height,Size:        integer;
  SrcBits,DstBits:          pointer;
  mDC:                      Integer;
begin
  Width:=SrcBmp.Width;
  Height:=SrcBmp.Height;
  Size:=((Width*3)+(Width mod 4))*Height;
  incRow:=((Width*3)+(Width mod 4));
  Gap:=Width mod 4;
  DstBmp.Assign(SrcBmp);//这句可要可不要,看情况定
  getMem(srcBits,size);
  getMem(DstBits,size);
  with SrcbmHeader do begin
    biSize:=SizeOf(SrcbmHeader);
    biWidth:=Width;
    biHeight:=-Height;
    biPlanes:=1;
    biBitCount:=24;
    biCompression:=BI_RGB;
  end;
  SrcbmInfo.bmiHeader:=srcbmHeader;

  with DstbmHeader do begin
    biSize:=SizeOf(DstbmHeader);
    biWidth:=Width;
    biHeight:=-Height;
    biPlanes:=1;
    biBitCount:=24;
    biCompression:=BI_RGB;
  end;
  DstbmInfo.bmiHeader:=DstbmHeader;

  try
    mDC:=GetDC(0);
    GetDIBits(mDC,srcBmp.Handle,0,Height,srcBits,srcbmInfo,DIB_RGB_COLORS);

    DstTmp:=DstBits;
    for y:=0 to Height-1 do begin
      for x:=0 to Width-1 do begin
        SrcTmp:=pointer(integer(SrcBits)+(y*IncRow+x*3));
        Gr := HiByte(SrcTmp^.r * 77 + SrcTmp^.g * 151 + SrcTmp^.b * 28);
        DstTmp^.r:=Gr;
        DstTmp^.g:=Gr;
        DstTmp^.b:=Gr;
        Inc(DstTmp);
      end;
      DstTmp:=Pointer(Integer(DstTmp)+Gap);
    end;
    SetDIBits(mDC,DstBmp.Handle,0,Height,DstBits,DstbmInfo,DIB_RGB_COLORS);
    ReleaseDC(0,mDC);
  finally
    freemem(SrcBits);
    freemem(DstBits);
  end;
end;

其中GetDIBBits和SetDIBBits函数可以看API帮助.这个方法与显存有关,
如果你的显存不够大,大图象就处理不,600X600的图象需要
600x600x3=1080000Bytes的显存.

DIB不是device independant bitmap吗?
和设备无关的, 在内存中.
DDB才和显存有关.
不用palette的话:
onedolphi的程序稍微修改了一下:
procedure Gray(bmp: TBitmap);
var
  p: PByteArray;
  w: Integer;
  i, j: Integer;
begin
  bmp.pixelformat := pf24bit;
  for i := 0 to bmp.height - 1 do
  begin
    p := bmp.scanline[i];
    j := 0;
    while j < (bmp.width-1) * 3 do
    begin
      w :=(p[j] * 28 + p[j+1] * 151 + p[j+2]*77);
      w := w shr 8;
      p[j] := byte(w);
      p[j+1] := byte(w);
      p[j+2] := byte(w);
 end;

end;

end;

posted on 2010-04-07 22:47  浔阳渔夫  阅读(3499)  评论(1编辑  收藏  举报