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;
            }
  • 相关阅读:
    iOS 手势操作:拖动、捏合、旋转、点按、长按、轻扫、自定义
    一个基于MVVM的TableView组件化实现方案
    代码审查和不良编程习惯
    十二步创建你的第一个JavaScript库
    可简单避免的三个 JavaScript 发布错误
    巧用Javascript将相对路径地址转换为绝对路径
    jquery 事件对象属性小结
    26个Jquery使用小技巧
    应用于网站导航中的 12 个 jQuery 插件
    使用 jQuery 避免鼠标双击
  • 原文地址:https://www.cnblogs.com/feisky/p/1593985.html
Copyright © 2011-2022 走看看