在一个比较大的图形中 能够快速的检测指定的像素的像素值,如果能在jpg类型图形中检测更好?

解决方案 »

  1.   

    请学习 JPg编码格式  XXX ++ XXXX
      

  2.   

    关键字:BMP
    SCANLINE将目标图像转换成为bmp-pf24bit再调用SCANLINE方法处理;SCANLINE效率很高的;
      

  3.   

    bmp: procedure   TForm1.SpeedButton3Click(Sender:   TObject);
    var
        pixblack:cardinal;//黑色象素個數
        pixwhite:cardinal;//白色象素個數
        x,y:integer;//y是行數,x是列數
        bitmap1:TBitmap;
        pixcolo:PByteArray;
        BytePP:Integer;   //修改
        begin
            bitmap1:=TBitmap.create;
            try
                bitmap1.loadfromfile(filename1);
                case   bitmap.pixelformat   of   //修改
                  pf8bit:   bytepp:=1;   //不是pf8bit可能是pf8Bits,不對的話請查一下pixelformat的幫助
                  pf16bit:   bytepp:=2;
                  pf24bit:   bytepp:=3;
                  pf32bit:   bytepp:=4;
                  else   exit;   //如果是其他格式,則有特殊情況
              end;
                pixblack:=0;
                pixwhite:=0;
                for   y:=0   to   bitmap1.height-1   do  
                    begin   //開始掃描
                        pixcolo:=bitmap1.ScanLine[y];
                        for   x:=0   to   (bitmap1.width   div   BytePP)-1   do   //修改
                            if   pixcolo[x*BytePP]=0   then   pixblack:=pixblack+1   //修改
                            else   pixwhite:=pixwhite+1;
                    end;   //掃描結束
                showmessage(inttostr(pixblack));
                showmessage(inttostr(pixwhite));
            finally   bitmap2.free;
        end;end;黑白圖:
    procedure   TForm1.SpeedButton3Click(Sender:   TObject);
    var
        pixblack:cardinal;//黑色象素個數
        pixwhite:cardinal;//白色象素個數
        x,y,z:integer;//y是行數,x是列數   ////修改
        bitmap1:TBitmap;
        pixcolo:PByteArray;
        begin
            bitmap1:=TBitmap.create;
            try
                bitmap1.loadfromfile(filename1);
                pixblack:=0;
                pixwhite:=0;
                for   y:=0   to   bitmap1.height-1   do  
                    begin   //開始掃描
                        pixcolo:=bitmap1.ScanLine[y];
                        for   x:=0   to   (bitmap1.width   div   8)-1   do   //修改
                          for   z:=0   to   7   do
                            if   (pixcolo[x]   shr   z)   and   1   =0   then   pixblack:=pixblack+1   //修改
                            else   pixwhite:=pixwhite+1;
                    end;   //掃描結束
                showmessage(inttostr(pixblack));
                showmessage(inttostr(pixwhite));
            finally   bitmap2.free;
        end;end;
      

  4.   

    function   Jpg2Bmp(Jpg:   TJpegImage):   TBitmap;
    begin
    //功能說明:     圖片檔轉化由Jpg格式轉化為Bmp格式
    //參數說明:     Jpg:   Jpg格式的圖片內容
    //返   回   值:     成功返回一個TBitmap物件
        Result   :=   nil;
        if   JPg   =   nil   then     Exit;
        try
            if   Assigned(Jpg)   then
            begin
                Result   :=   TBitmap.Create;
                Jpg.DIBNeeded;
                Result.Assign(Jpg);
            end;   //end   of   if..then
        except
            on   E:   Exception   do
                MessageBox(FMainHandle,   PChar(   Err_JpgToBmp
                                                                          +   Msg_ErrorDetail
                                                                          +   E.Message),   Msg_ErrCaption,   MB_OK   +   MB_ICONSTOP);
        end;   //end   of   try..except
    end;
      

  5.   

    ScanLine的效率如何,因为像素是不均匀的分布在图像中的,每调取一个像素的颜色都要调用一次ScanLine。频繁的调用ScanLine影响效率吗?
    另外如何高效率的切割一个大的图片成为多个小图片,感觉delphi自带函数效率一般,有没有gdi+的函数,效率是不是更高些?
      

  6.   

        pByte(CurrRow + h*OffSet+w*3);   //  h 高  w  宽
    procedure TForm1.Button2Click(Sender: TObject);
    var w, h: integer;
      x: byte; pRed, pGreen, pBlue: PByte;
        CurrRow, OffSet: integer;begin
      bmp1:=tbitmap.Create;
      bmp1.LoadFromFile('未命名hh.bmp');  CurrRow := Integer(bmp1.ScanLine[0]);
        OffSet := Integer(bmp1.ScanLine[1]) - CurrRow;    for h := 0 to bmp1.Height - 1 do
        begin
          for w := 3 to bmp1.Width - 3 do
          begin
            pBlue  := pByte(CurrRow + h*OffSet+w*3);
            pGreen := pByte(CurrRow + h*OffSet+w*3 + 1);
            pRed   := pByte(CurrRow + h*OffSet+w*3 + 2);        pBlue^  := 255;
            pGreen^ := 255;
            pRed^   := 255;
          end;
      
        end;
       image1.Picture.Bitmap.Assign(bmp1);
       bmp1.Free;
       image1.Refresh;end;
      

  7.   

    CurrRow := Integer(bmp1.ScanLine[0]);    缓冲区首地址  只使用ScanLine[0]  2次,以后直接计算像素指针
      

  8.   

    不知道是不是我代码写的不好,我以前也研究过颜色取值,用的就是7L的ScanLine,但效率很慢,后来感觉对于特定格式的bmp研究其结构后,用pchar直接取颜色点的值快一些,不知道大家的意见如何?以下是网上摘抄的一段按格式取值的代码var
     pic:TPicture;
     pMem:PByteArray;
     hFile:Integer;
     i,ibmpsize,PicW,PicH:Integer;
     iBytesRead: Integer;
     lpPalette :pLOGPALETTE;
     hPal : hPalette;
    begin
     pic:=TPicture.Create;  //创建Tpicture对象
     hFile:=FileOpen(FileName,fmOpenRead); //打开图像数据文件
     ibmpsize := FileSeek(hFile,0,2); //获得数据长度
     FileSeek(hFile,0,0); //指针移至开始处
     pMem:=AllocMem(ibmpsize );//定义pMem维数
     iBytesRead:=FileRead(hFile, pMem[0], ibmpsize);//读取数据
     FileClose(hFile);//关闭文件
    //这里是从图片最后一行读至第一行,你可以加一段调整使之倒过来
    //如定义pMem2, pmem2[i]=pmem[1024*768-i];
      with pic.Bitmap do
      begin
      Height:=768;//图片高
      Width:=1024;//图片宽
      PixelFormat:=pf1bit;  //设置图像的比特深度,2色、8色、256色等
      SetBitmapBits(
      Handle,        // handle to bitmap
      ibmpsize,        // number of bytes in bitmap array
      pMem); //将数据PMem赋给pic
      end;
      image1.Height:=picH;
      image1.Width:=picW;
      image1.Picture:=pic;  //pic赋给image1控件显示
      pic.Free;
      FreeMem(pMem);//以下是更改调色板
    image1.Picture.Bitmap.PixelFormat:=pf8bit;
    GetMem(lpPalette,sizeof(TLogPalette) + (255 * sizeof(TPaletteEntry)));
    lpPalette^.palVersion := $300;
    lpPalette^.palNumEntries := 256;
    for i:=0 to 255 do
    begin
    lpPalette^.PalPalEntry[i].peRed :=rr;
    lpPalette^.PalPalEntry[i].peGreen :=gg;
    lpPalette^.PalPalEntry[i].peBlue :=bb;
    end;
    hPal := CreatePalette(lpPalette^);
    image1.Picture.Bitmap.Palette:=hpal;
    FreeMem(lpPalette,sizeof(TLogPalette) + (255 * sizeof(TPaletteEntry)));
    DeleteObject(hPal);
    end;  
    ================================================
    bmp文件格式
    1、  第一部分为位图文件头BITMAPFILEHEADER,它是一个结构,其定义如下:
    typedef struc tagBITMAPFILEHEADER{
             WORD  bfType;
             WORD  bfSize;
             WORD  bfReserved1;
             WORD  bfReserved2;
             WORD  bfOffBits;
    }BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;
     该结构的长度是固定的,为14个字节,各个域的说明如下:
    Ø  bfType:指定文件类型,必须是0x4d42,即字符串“BM”。
    Ø  bfSize:指定文件大小,包括这14个字节。
    Ø  bfReserved1,bfReserved2:保留字,为0。
    Ø  bfOffBits:从文件头到实际的位图数据的偏移字节数,即图1中前三个部分的长度之和。
    2、  第二部分为位图信息头BITMAPINFOHEADER,它也是一个结构,其定义如下:
    typedef struc tagBITMAPINFOHEADER{
              DWORD  biSize;
              LONG   biWidth;
              LONG   biHeight;
              WORD   biPlanes;
              WORD   biBitCount;
              DWORD  biCompression;
              DWORD  biSizeImage;
              LONG   biXPelsPerMeter;
              LONG   biYPelsPerMeter;
              DWORD  biClrUsed;
              DWORD  biClrImportant;
    }BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;
    该结构的长度也是固定的,为40个字节,各个域的说明如下:
    Ø  biSize:指定这个结构的长度,为40个字节。
    Ø  biWidth:指定图像的宽度,单位是象素。
    Ø  biHeight:指定图像的高度,单位是象素。
    Ø  biPlanes:必须是1。
    Ø  biBitCount:指定表示颜色时用到的位数,常用的值为1(黑白二色图)、4(16色图)、8(256色图)、24(真彩色图)。
    Ø  biCompression:指定位图是否压缩,有效值为BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS。Windows位图可采用RLE4和RLE8的压缩格式,BI_RGB表示不压缩。
    Ø  biSizeImage:指定实际的位图数据占用的字节数,可用以下的公式计算出来:
                 biSizeImage = biWidth’× biHeight
        要注意的是:上述公式中的biWidth’必须是4的整数倍(不是biWidth,而是大于或等于biWidth的离4最近的整数倍)。如果biCompression为BI_RGB,则该项可能为0。
    Ø  biXPelsPerMeter:指定目标设备的水平分辨率。
    Ø  biYPelsPerMeter:指定目标设备的垂直分辨率。
    Ø  biClrUsed:指定本图像实际用到的颜色数,如果该值为0,则用到的颜色数为2的biBitCount次幂。
    Ø  biClrImportant:指定本图像中重要的颜色数,如果该值为0,则认为所有的颜色数都是重要的。
    3、  第三部分为调色板。有些位图需要调色板,有些位图,如真彩色图,不需要调色板,
    它们的BITMAPINFOHEADER后面直接是位图数据。
    调色板实际上是一个数组,共有biClrUsed个元素(如果该值为0,则有2的biBitCount次幂个元素)。数组中每个元素的类型是一个RGBQUAD结构,占4个字节,其定义如下:
    typedef struct tagRGBQUAD{
             BYTE   rgbBlue;
             BYTE   rgbGreen;
             BYTE   rgbRed;
             BYTE   rgbReserved;
    }RGBQUAD;
    其中:
    Ø  rgbBlue:该颜色的蓝色分量。
    Ø  rgbGreen:该颜色的绿色分量。
    Ø  rgbRed:该颜色的红色分量。
    Ø  rgbReserved:保留值。
    4、  第四部分就是实际的图像数据。对于用到调色板的位图,图像数据就是该象素颜色
    在调色板中的索引值,对于真彩色图,图像数据就是实际的R、G、B值。
    Ø  对于2色图,用1位就可以表示该象素的颜色,所以1个字节可以表示8个象素。
    Ø  对于16色图,用4位可以表示一个象素的颜色,所以1个字节可以表示2个象素。
    Ø  对于256色图,1个字节刚好可以表示1个象素。
    Ø  对于真彩色图,3个字节才能表示1个象素。
      

  9.   

    切割一个大的图片成为多个小图片可以用image加载后用copyrect,效率确实一般,不过目前不知道好的方法,不过据说delphi image加载图像效率非常高,暂时还没经历去研究它的代码