In fact, I have always liked to decode the image format myself (currently I have decoded about 15 image formats), but the main reason for writing this article is the post based on csdn:
Http://bbs.csdn.net/topics/390510431 with picturebox shows a black and white 8bit image, how to eliminate grain sensation
Original jpg image for test: http://files.cnblogs.com/Imageshop/img01.rar
In this post, the author needs to load a gray-scale 8-bit PG Format Image, but use it. net bitmap class Loaded Images will show obvious particle sensation, because. the bitmap class in net is based on the GDI + operation, so I also tried to use my imageshop to open this image (imageshop is also implemented using the GDI + API internally), and it also has a grain sense. Therefore, we need to solve this problem by other means.
Effect of loading under. Net Photoshop
First, I used the stdpicture object in vs6.0 to load the image and get the correct result. Then you can use PS to open it and get better results. Finally, you can use Microsoft's Image Viewer to display it correctly. Finally, you can use the mspaint (drawing) tool to open the image, which has the same effect as in. net.
Therefore, our first ideal solution is to use stdpicture in COM to solve this problem. In fact, in VB6.0, A loadpicture function can solve it, but it should be used in C, many API functions are required for processing. I tried it myself and thought it was too cumbersome, so I gave up.
Therefore, I put my hopes into the well-known image decoding software freeimage. After experiments, I found that the decoding of freeimage is consistent with that of PS.
Let's take a look at Baidu's introduction to freeimage:
Freeimage is a free, open-source, cross-platform (Windows, Linux, and Mac OS X, supports image processing libraries for over 20 image types (such as BMP, JPEG, GIF, PNG, And Tiff. Its biggest advantage is its plug-in-driven architecture, which is fast, flexible, and easy to use and widely used. The main functions of freeimage include multi-format bitmap reading and writing, convenient bitmap information acquisition, bit-depth conversion, bitmap page access, basic geometric transformation and point processing, and channel merging and mixing. Freeimage currently does not support vector graphics and advanced image processing. Bitmap rendering must be completed by users. All functions in freeimage start with freeimage _. The Read and Write Functions of image files are freeimage_load and freeimage_save. The fibitmap Data Structure stores bitmap information and pixel data, which is freeimage.
Core.
From the above, we can see that the focus of freeimage is on image decoding and encoding, and the user is responsible for displaying images, which is exactly what we need.
To be able to use freeimage in. net, I know two methods: one is to directly use the flat API of freeimage, and this requires the declaration of the used API function. Another method is to use the class library provided by freeimagenet. dll provided by freeimage (which is actually the encapsulation of functions in freeimage. dll ). Here I will briefly describe the implementation of both methods:
Public static bitmap loadimageformfreeimage (string filename) {bitmap BMP = NULL; free_image_format fif = free_image_format.__unknown; fif = freeimage_getfiletype (filename, 0); If (FIF = photo) {fif = freeimage_get1_fromfilename (filename);} If (FIF! = Free_image_format.fif_unknown) & (freeimage_fifsupportsreading (FIF )! = 0) {intptr Dib = freeimage_load (FIF, filename, 0); int bpp = freeimage_getbpp (DIB); pixelformat PF; int width, height, stride; Switch (BPP) {Case 1: pF = pixelformat. format1bppindexed; break; Case 4: pF = pixelformat. format4bppindexed; break; case 8: pF = pixelformat. format8bppindexed; break; Case 16: pF = pixelformat. format16bpprgb555; break; Case 24: pF = pixelformat. format24bpprgb; break; Case 32: pF = pixelformat. format32bppargb; break; default: freeimage_free (DIB); return NULL;} width = freeimage_getwidth (DIB); // Image Width Height = freeimage_getheight (DIB ); // Image Height stride = freeimage_getpitch (DIB); // the size of the Image scan line must be an integer multiple of 4/** solution 1: Memory leakage * freeimage_flipvertical (DIB ); // because the image starting point of freeimage is in the lower left corner, if the image is not flipped, * intptr bits = freeimage_getbits (DIB) is reversed ); // obtain the address of the image data in the memory * BMP = new Bitmap (width, height, stride, PF, BITs ); // The actually called gdipcreatebitmapfromscan0 function creates a bitmap from the memory ** // solution 2: intptr bits = freeimage_getbits (DIB); BMP = new Bitmap (width, height, stride, PF, BITs); BMP. rotateflip (rotatefliptype. rotatenoneflipy); // call the GDI + self-rotating function if (BPP <= 8) {colorpalette pal = BMP. palette; // set the color palette rgbquad * gdipal = freeimage_getpalette (DIB); int clrused = freeimage_getcolorsused (DIB); For (INT I = 0; I <clrused; I ++) {pal. entries [I] = color. fromargb (255, gdipal [I]. red, gdipal [I]. green, gdipal [I]. blue);} BMP. palette = pal;} freeimage_free (DIB); // solution 2 can immediately release return BMP;} return NULL ;}}
In the above Code, we will explain why solution 1 has memory leakage.
In solution 1, the BMP = new Bitmap (width, height, stride, PF, BITs) statement actually calls the GDI + function gdipcreatebitmapfromscan0 to create a bitmap from the memory, the bitmap created in this way does not allocate a new memory to the created bitmap, but is bound to the memory corresponding to bits. You can verify this with the following code:
Bitmapdata bmp data = BMP. lockbits (New rectangle (0, 0, BMP. width, BMP. height), imagelockmode. readwrite, BMP. pixelformat); If (BMP data. scan0 = bits) MessageBox. show ("the image created through GDI + shares the same memory as the dib object of freeimage. ") BMP. unlockbits (BMP data );
For this reason, if solution 1 is used, we cannot immediately release the dib object created by freeimage after creating the GDI + bitmap, that is, freeimage_free (DIB) cannot be called ); if yes, the corresponding BMP object is actually an empty object.
In this case, it may be irrelevant. We only need to call BMP in the appropriate place. dispose, isn't it enough? You can perform a test, use this code, and then open new images constantly. You will find that the memory occupied by the program is constantly increasing without being released. Therefore, let's take a look at how msdn explains the gdipcreatebitmapfromscan0 function, especially the last parameter:
-
Scan0[In]
-
Type:Byte *
Pointer to an array of bytes that contains the pixel data. The caller is responsible for allocating and freeing the block of memory pointed to by this parameter.
The above text indicates that the user needs to release the allocated memory, that is, the dispose method cannot release this part of memory.
With the above problem, we switched to solution 2 and solution 2 using a BMP statement. rotateflip (rotatefliptype. rotatenoneflipy); this statement will create a new bitmap, that is, the rotated image will no longer use the same memory as freeimage. In this case, you can safely release the freeimage Dib object.
I thought the rotateflip function would reduce the efficiency. On the test surface, Microsoft still performed this function very efficiently. In fact, the function of this function can be quickly implemented by using the copymemory function.
When the image depth is less than 8, you need to obtain the color palette data. However, I think the freeimage_getpalette function used to obtain the color palette has memory leakage and cannot release the memory allocated by rgbquad. Freeimage should consider using a method similar to obtaining palette data in GDI +.
Using the class library provided in freeimagenet. dll makes it easier to write code. The second method is recommended. You can refer to the attachment.
In fact, freeimage also has many powerful functions, such as color-depth conversion, making full use of its image-washing software. Format batch processing is fast and convenient.
The image dragging method in the attachment is also worth learning.
Http://files.cnblogs.com/Imageshop/FreeImage.rar
Http://files.cnblogs.com/Imageshop/FreeImageApi.rar
* ******** Basically, I do not provide source code, however, I will try to use text to clearly describe the corresponding algorithm or provide the reference documentation ***************
* ********* The result of your own efforts and practices is exactly what you did, people must rely on their own *******************
* ******** Author: laviewpbt time: 2013.7.5 contact QQ: 33184777 reprint please keep the bank's information *************