// ================================================ ========================================
// Title:
// Details about iimage Image Display
// Author:
// Norains
// Date:
// Sunday 26-August-2007
// Environment:
// Evc4.0 + Windows CE 5.0 standard SDK
// ================================================ ========================================
Iimage is a COM component that is added after wince5.0. Its usage is just like its name. It is more convenient to show pictures. After wince 5.0, We can get tired of it, discard imgdecmp, and switch to iimage ~ Although I personally think that the two decoding methods have the same speed and are slow, especially when drawing large images, they are always better than nothing, so let's take a look at the main character of today!
Using iimage to display images is incredibly simple. It's nothing more than calling several functions:
Iimage * m_pimage;
Iimagingfactory * m_pimagingfactory;
Hresult hr;
// COM Initialization
If (failed (hR = coinitializeex (null, coinit_multithreaded )))
{
Goto end;
}
// Create a com instance
If (failed (hR = cocreateinstance (clsid_imagingfactory, null, clsctx_inproc_server, iid_iimagingfactory, (void **) & m_pimagingfactory )))
{
Goto end;
}
// Create an image from the file
If (failed (hR = m_pimagingfactory-> createimagefromfile (text ("test .bmp"), & m_pimage )))
{
Goto end;
}
// Draw an image
If (failed (hR = m_pimage-> draw (HDC, & rcwnd, null )))
{
Goto end;
}
End:
// Release resources
If (m_pimage! = NULL)
{
M_pimage-> release ();
M_pimage = NULL;
}
If (m_pimagingfactory! = NULL)
{
M_pimagingfactory-> release ();
M_pimagingfactory = NULL;
}
Couninitialize ();
OK, it's that simple. As long as the OS contains the corresponding decoder components, most of the above Code shows images. well, in this case, this tofu block will end ~ :-)
However, it is a pity that Microsoft has never done everything well. Otherwise, this piece of bean curd is perfect.
In this Code, it should be calm, but there is a function that looks weird and is easy to call and fails. It is iimage: Draw ()!
1) display the specific area of the source file
There is no problem in displaying the entire image. just assign the srcrect parameter null. But what if it is displaying a specific area? For example, if I only want to display half of a 800*600 image, what should I do? It is estimated that many people (well, including me) will not read the document carefully, but will directly write this statement based on experience: rect rcsrc = {0, 0, 400,600 };
M_pimage-> draw (HDC, & rcwnd, & rcsrc );
Oh, my God, run this code! What do you see? If you are lucky, you will have a small square! At this time, it is estimated that many people will greet Microsoft's parents, oh, and so on. There are many bugs in Microsoft's things, but such a simple things won't make them so confused.
Take a closer look at the description of this parameter: an optional pointer to a rect that specifies, in 0.01mm units, the portion of the image to be drawn in dstrect.
See the most important sentence: In 0.01 units !! The Unit is 01mm. It is not a pixel! Although Microsoft's starting point is good and its display accuracy is more accurate, it does bring us a lot of trouble. however, since Microsoft interfaces are defined as such, it is better for us to do something practical than to stick to Microsoft and complain about Microsoft. After all, we still need to complete the task and get the monthly salary to support our family. :-(
There is no path to death in the sky. OK. Let's take a look at the conversion of units:
M_pimage-> getimageinfo (& imageinfo );
Double ddotpermmx = imageinfo. xdpi/25.4;
Double ddotpermmy = imageinfo. ydpi/25.4;
// Psrcrect points to the area in pixels
Rect rcsrc = {(long) (psrcrect-> left/ddotpermmx/0.01 ),
(Long) (psrcrect-> top/ddotperct/0.01 ),
(Long) (psrcrect-> right/ddotpermmx/0.01 ),
(Long) (psrcrect-> bottom/ddotper.pdf/0.01 )};
M_pimage-> draw (HDC, & rcdraw, & rcsrc );
Although the specified area can be displayed normally, there are still some errors, but another problem discussed later can be solved.
2) iimage: Draw () takes a long time
This is an issue that cannot be solved, because iimage: Draw () requires some decoding before it can be drawn to the Target DC, especially when displaying some particularly large JPEG values (if it can be displayed :-)) more Obvious. if the image is only displayed once, the problem may not be so serious, but if it needs to be called multiple times, for example, dragging the image, this speed is absolutely intolerable. of course, this problem will certainly not happen in the future, and it will not be long in the future. You don't have to wait until the Internet is full or the Internet is worn out, as long as the decoding speed of embedded devices is almost the same as that of mainstream PCs. this day will not be far away, but it will not be able to solve the problem of today, so please use your skills to solve it!
The method is actually very simple. iimage: Draw () takes a long time, so we only need to save the image to the memory DC when drawing it for the first time, then, draw the data of the memory DC to the Target DC. in this way, it is only the first time you feel unhappy when drawing (if you have a bad temper, you may feel annoyed), but it is always a pleasant journey. is there anything cheaper than getting it all done once and for all? // Obtain image attributes
M_pimage-> getimageinfo (& imageinfo );
// Create a memory DC to store image data
Hbitmap = createcompatiblebitmap (HDC, imageinfo. Width, imageinfo. Height );
Hdcmem = createcompatibledc (HDC );
Holdsel = SelectObject (hdcmem, hbitmap );
...
// Store Image Data in the memory DC
Rcmemdc = {0, imageinfo. Width, imageinfo. Height };
M_pimage-> draw (hdcmem, & rcmemdc, null );
...
// Draw the image to the Target DC
Stretchblt (HDC,
Pdstrect-> left,
Pdstrect-> top,
Pdstrect-> right-pdstrect-> left,
Pdstrect-> bottom-pdstrect-> top,
Hdcmem,
Psrcrect-> left,
Psrcrect-> top,
Psrcrect-> right-psrcrect-> left,
Psrcrect-> bottom-psrcrect-> top,
Srccopy );
As long as the image data is saved to hdcmem for the first time and hdcmem data can be drawn when the image is drawn in the future, this is much faster than iimage: Draw () that requires a decoding process!
Some careful friends may notice the shape parameters of stretchblt. well, I would like to extend my sincere respect to these friends. yes, yes. After saving the image data to hdcmem, an additional benefit is that you no longer need to change the unit when drawing an image area!
Because the entire image data is stored in hdcmem, you only need to set the parameter to null. After saving the data to hedmem, use the stretchblt () function to draw data in pixels. haha, yes, that's right. We can avoid the loss caused by unit conversion. the so-called one arrow and two arms?
3) failed to draw the large image.
When calling iimage: Draw () to draw a large image, it is likely that the painting fails. the error message is e_outofmemory, with insufficient memory. this is a very helpless reality. although the memory size of my device is much larger than that of the image, the result is nothing more than a failure even if more virtual memory is allocated by the left-side channel due to the limitation of wince5.0 32 m virtual memory! No way. Well, at least I didn't find a solution.
Of course, everything is not absolute. If the image quality requirements are not high, there is still a way to display it. It is very simple, as long as you get the thumbnail instance, and then draw it.
M_pimage-> getthumbnail (width, height, & m_pthum );
M_pthum-> draw (HDC, & rcdc, null );
This iimage: Draw () should not fail. of course, if the problem persists, the only method is to reduce the width and height until the display is normal. however, as the value decreases, the image quality will also decrease.