Tips for using GDI + bitmap data scanning lines to process images: C/C ++ 2071 people read comments (4) collect reports
In GDI + image processing, we often use the bitmapdata structure to scan the line of image data. This method is used in most of my Bolg articles. Using its lockbits method and unlockbits method, GDI + bitmap is used to lock (obtain) and unlock (release) bitmapdata data respectively. We generally operate the scanned line of image data between these two methods, for example:
[CPP]View plaincopyprint?
- Bitmap * BMP = new Bitmap (l "d: // 001-1.jpg ");
- Bitmapdata data;
- Gdiplus: rect R (0, 0, BMP-> getwidth (), BMP-> getheight ());
- // The lock is in 32-bit pixel format.
- BMP-> lockbits (& R, imagelockmoderead | imagelockmodewrite, pixelformat32bppargb, & data );
- // Scan the image data line here. Many methods cannot be called because BMP is locked.
- BMP-> unlockbits (& data); // unlock
- Gdiplus: Graphics * g = new gdiplus: Graphics (canvas-> handle );
- G-> drawimage (BMP, 0, 0 );
- Delete g;
- Delete BMP;
Because the bitmap object is locked between the lockbits method and the unlockbits method, many methods cannot be called, and sometimes it is inconvenient or even cumbersome. For example, if you want to display or save the scanned lines of image data multiple times, you have to call these two methods repeatedly; in addition, images with a bitmap format lower than the 24-bit format cannot be locked to 24-bit or 32-bit data for operations (we mostly use 24-bit or 32-bit pixel scanning lines for image processing.
You can use some tips to avoid the inconvenience caused by the locking of Bitmap objects. You can also scan images of 24 or 32 bits or smaller than 24 bits. See the following example:
[CPP]View plaincopyprint?
- Gdiplus: Graphics * g = new gdiplus: Graphics (canvas-> handle );
- Bitmap * BMP = new Bitmap (l "d: // 001-1.jpg ");
- Bitmapdata data;
- Gdiplus: rect R (0, 0, BMP-> getwidth (), BMP-> getheight ());
- // Pre-set Scan Line Length and Image Data
- Data. stride = R. Width * 4;
- Data. scan0 = (void *) New char [R. Height * Data. stride];
- // Create a 32-bit Custom Data bitmap object
- Bitmap * BMP 2 = new Bitmap (R. Width, R. Height, Data. stride,
- Pixelformat32bppargb, (byte *) data. scan0 );
- // Use the imagelockmoderead tag to copy BMP image data to data. scan0.
- // Use imagelockmodeuserinputbuf to mark and lock the image BMP so that BMP and BMP 2 Share the image data.
- // Use the imagelockmodewrite mark to synchronize BMP and BMP 2, that is, when Image Data Processing
- // Apply to BMP and BMP 2. After imagelockmodewrite is removed, the BMP image remains unchanged,
- // Remove imagelockmodewrite from images in less than 24 bits.
- BMP-> lockbits (& R, imagelockmoderead | imagelockmodewrite | imagelockmodeuserinputbuf,
- Pixelformat32bppargb, & data );
- // You can perform step-by-step operations on the image scanning line, and also display BMP 2, or call any methods of BMP 2.
- Imagegray (& data); // grayscale images. The specific process is omitted.
- G-> drawimage (BMP 2, 0, 0); // draw an image (or call other methods)
- Imagetwovalues (& Dada, 127); // binarization of images. The specific process is omitted.
- G-> drawimage (BMP 2, 200, 0); // draw an image (or call other methods)
- BMP-> unlockbits (& data );
- Delete g;
- Delete BMP;
- Delete BMP 2;
- Delete [] data. scan0; // must be released
The code in the above example is described in detail and will not be explained.
The code in the above example Seems messy to explain the bitmap object sharing and data processing synchronization.Remember: In this example, after the custom bitmap object BMP 2 acquires data through the BMP-> lockbits method, BMP can be unlocked or even deleted without special requirements, in this case, you no longer need to lock BMP 2. You can change the image data contained in BMP 2 by processing the data.
Re-plan the code above to make it clearer:
[CPP]View plaincopyprint?
- Bool getbitmapdata (wchar * filename, pixelformat, bitmapdata * Data)
- {
- Bitmap * BMP = new Bitmap (filename );
- If (BMP-> getlaststatus ()! = OK)
- Return false;
- Gdiplus: rect R (0, 0, BMP-> getwidth (), BMP-> getheight ());
- Uint pixelsize = getpixelformatsize (pixelformat );
- Data-> stride = (pixelsize * R. Width + 31) & 0xffffffe0)> 3;
- Data-> scan0 = (void *) New char [R. Height * Data-> stride];
- BMP-> lockbits (& R, imagelockmoderead | imagelockmodeuserinputbuf,
- Pixelformat, data );
- BMP-> unlockbits (data );
- Delete BMP;
- Return true;
- }
- Void _ fastcall tform2: button1click (tobject * sender)
- {
- // Obtain the 24-bit pixel data of the image
- Bitmapdata data;
- If (! Getbitmapdata (l "d: // 001-1.jpg", pixelformat24bpprgb, & Data ))
- Return;
- // Create a user-defined data bitmap object in 24-bit pixel format
- Bitmap * BMP = new Bitmap (data. Width, Data. Height, Data. stride,
- Data. pixelformat, (byte *) data. scan0 );
- Gdiplus: Graphics * g = new gdiplus: Graphics (canvas-> handle );
- // Scan lines of image data can be operated here, so you do not have to lock BMP, and you can also display BMP, or call any methods of BMP.
- Imagegray (& data); // grayscale images. The specific process is omitted.
- G-> drawimage (BMP, 0, 0); // draw an image (or call other methods)
- Imagetwovalues (& Dada, 127); // binarization of images. The specific process is omitted.
- G-> drawimage (BMP, 200, 0); // draw an image (or call other methods)
- Delete g;
- Delete BMP;
- Delete [] data. scan0; // must be released
- }
Through the code above, we can see that after getbitmapdata is called, all the image data information is included in the bitmapdata structure, so we can perform any operation on this data structure, instead of relying on any GDI + object, this avoids the inconvenience mentioned above. To create a custom data bitmap object, you only need to use it for image display, storage, and other operations.
You can also perform the puzzle operation by using code similar to the previous example:
[CPP]View plaincopyprint?
- Gdiplus: Graphics * g = new gdiplus: Graphics (canvas-> handle );
- Bitmap * BMP = new Bitmap (l "d: // 001-1.jpg ");
- Bitmapdata data;
- Gdiplus: rect R (0, 0, BMP-> getwidth (), BMP-> getheight ());
- // Pre-set the scanning line length and image data. The scanning line is the width of two images.
- Data. stride = R. Width * 2*4;
- Data. scan0 = (void *) New char [R. Height * Data. stride];
- // Copy the image to the left. Note that only data is read here, So imagelockmodewrite is not used.
- BMP-> lockbits (& R, imagelockmoderead | imagelockmodeuserinputbuf,
- Pixelformat32bppargb, & data );
- BMP-> unlockbits (& data );
- // Splice the image to the right. to simplify the image, use the same image.
- // If the image size is different, as long as the size of the r is the same (cannot be larger than the source image)
- (Char *) data. scan0 + = (R. Width * 4); // The scanned line address moves to the right.
- BMP-> lockbits (& R, imagelockmoderead | imagelockmodeuserinputbuf,
- Pixelformat32bppargb, & data );
- BMP-> unlockbits (& data );
- (Char *) data. scan0-= (R. Width * 4); // restore the scanned line address
- Data. width = R. Width * 2; // reset the tile width.
- // The tiled graph data information is included in data. You can continue to perform any operations on data.
- // Create a custom data bitmap object
- Bitmap * BMP 2 = new Bitmap (data. Width, Data. Height, Data. stride,
- Data. pixelformat, (byte *) data. scan0 );
- // Display the spliced image.
- G-> drawimage (BMP 2, 0, 0 );
- Delete g;
- Delete BMP;
- Delete BMP 2;
- Delete [] data. scan0; // must be released
The code in this article uses the BCB compiler. If there is an error, you can send a letter to correct, and please make suggestions: maozefa@hotmail.com