zoukankan      html  css  js  c++  java
  • GDI+ 使用LockBits和指针加快处理速度

    Lock up your bits

    The Bitmap class provides the LockBits and corresponding UnlockBits methods which enable you to fix a portion of the bitmap pixel data array in memory, access it directly and finally replace the bits in the bitmap with the modified data. LockBitsreturns a BitmapData class that describes the layout and position of the data in the locked array.

    The BitmapData class contains the following important properties;

    • Scan0 The address in memory of the fixed data array
    • Stride The width, in bytes, of a single row of pixel data. This width is a multiple, or possiblysub-multiple, of the pixel dimensions of the image and may be padded out to include a few more bytes. I'll explain why shortly.
    • PixelFormat The actual pixel format of the data. This is important for finding the right bytes
    • Width The width of the locked image
    • Height The height of the locked image

    The relationship of Scan0 and Stride to the array in memory is shown in figure1.

    Figure 1: The basic layout of a locked bitmap array

    The Stride property, as shown in figure 1, holds the width of one row in bytes. The size of a row however may not be an exact multiple of the pixel size because for efficiency, the system ensures that the data is packed into rows that begin on a four byte boundary and are padded out to a multiple of four bytes. This means for example that a 24 bit per pixel image 17 pixels wide would have a stride of 52. The used data in each row would take up 3*17 = 51 bytes and the padding of 1 byte would expand each row to 52 bytes or 13*4 bytes. A 4BppIndexed image of 17 pixels wide would have a stride of 12. Nine of the bytes, or more properly eight and a half,  would contain data and the row would be padded out with a further 3 bytes to a 4 byte boundary.

    The data carrying portion of the row, as has been suggested above, is laid out according to the pixel format. A 24 bit per pixel image containing RGB data would have a new pixel every 3 bytes, a 32 bit per pixel RGBA every four bytes. Pixel formats that contain more than one pixel per byte, such as the 4 bit per pixel Indexed and 1 bit per pixel indexed, have to be processed carefully so that the pixel required is not confused with it's neigbour pixels in the same byte.

    Finding the right byte.

    Because the stride is the width of a row, to index any given row or Y coordinate you can multiply the stride by the Y coordinate to get the beginning of a particular row. Finding the correct pixel within the row is possibly more difficult and depends on knowing the layout of the pixel formats. The following examples show how to access a particular pixel for a given pixel format.

    • Format32BppArgb Given X and Y coordinates,  the address of the first element in the pixel is Scan0+(y * stride)+(x*4). This Points to the blue byte. The following three bytes contain the green, red and alpha bytes.

    • Format24BppRgb Given X and Y coordinates, the address of the first element in the pixel is Scan0+(y*Stride)+(x*3). This points to the blue byte which is followed by the green and the red.

    • Format8BppIndexed Given the X and Y coordinates the address of the byte isScan0+(y*Stride)+x. This byte is the index into the image palette.

    • Format4BppIndexed Given X and Y coordinates the byte containing the pixel data is calculated as Scan0+(y*Stride)+(x/2). The corresponding byte contains two pixels, the upper nibble is the leftmost and the lower nibble is the rightmost of two pixels. The four bits of the upper and lower nibble are used to select the colour from the 16 colour palette.

    • Format1BppIndexed Given the X and Y coordinates, the byte containing the pixel is calculated by Scan0+(y*Stride)+(x/8). The byte contains 8 bits, each bit is one pixel with the leftmost pixel in bit 8 and the rightmost pixel in bit 0. The bits select from the two entry colour palette.

    示例程序:

    public static bool GrayScale(Bitmap b)
            {
                // GDI+ still lies to us - the return format is BGR, NOT RGB.
                BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
    
                int stride = bmData.Stride;
                System.IntPtr Scan0 = bmData.Scan0;
    
                unsafe
                {
                    byte * p = (byte *)(void *)Scan0;
    
                    int nOffset = stride - b.Width*3;
    
                    byte red, green, blue;
        
                    for(int y=0;y<b.Height;++y)
                    {
                        for(int x=0; x < b.Width; ++x )
                        {
                            blue = p[0];
                            green = p[1];
                            red = p[2];
    
                            p[0] = p[1] = p[2] = (byte)(.299 * red + .587 * green + .114 * blue);
    
                            p += 3;
                        }
                        p += nOffset;
                    }
                }
    
                b.UnlockBits(bmData);
    
                return true;
            }
  • 相关阅读:
    【技术贴】每次打开excel表格都会弹出新excel。book1.xls解决方法
    【技术贴】鼠标右键盘符属性报错Volume filter WMI not found的解决办法
    解决QQ聊天QQ秀咒语为什么我不能施放咒语/看不到咒语效果?
    【java】servlet输出pdf文件到浏览器 教程
    C#抽象工厂模式的几种实现方法及比较(外摘)
    SQL 语句汇总With子句
    浅析.NET开发中代理模式的使用(外摘)
    使用设计模式构建通用数据库访问类(外摘)
    Cognos产品组件及各组件功能介绍
    游标Oracle游标汇总
  • 原文地址:https://www.cnblogs.com/feisky/p/1593985.html
Copyright © 2011-2022 走看看