zoukankan      html  css  js  c++  java
  • (转)彩图变灰度图

    将一幅图片转化成灰度图,具体来说应该分为以下几步:
    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;

  • 相关阅读:
    Java 中的POJO和JavaBean 的区别
    设计模式的六大原则
    AOP
    Jetbrains 全家桶
    centos7 如何关闭防护墙
    Java 面试题常见范围
    putty readme
    单机环境
    flask-caching缓存
    1.restful 规范与APIView
  • 原文地址:https://www.cnblogs.com/huking/p/1706786.html
Copyright © 2011-2022 走看看