{"id":221,"date":"2009-11-19T08:51:14","date_gmt":"2009-11-19T13:51:14","guid":{"rendered":"http:\/\/www.e-consystems.com\/blog\/?p=221"},"modified":"2023-08-15T12:34:55","modified_gmt":"2023-08-15T07:04:55","slug":"creating-an-effective-image-viewer-in-windows-ce","status":"publish","type":"post","link":"https:\/\/www.e-consystems.com\/blog\/system-on-module-som\/creating-an-effective-image-viewer-in-windows-ce\/","title":{"rendered":"Creating an effective image viewer in Windows CE"},"content":{"rendered":"<p style=\"text-align: justify;\"><span style=\"color: #000000;\">There are some cases where we may need to develop a DLL or application to show  the images on the devices. For example, an Image viewer will be needed to show  the picture after taking a snap shot from the camera using a direct show camera application. Windows Mobile  supports the image viewer for this purpose, However if you are developing a  custom camera application<strong><em> <\/em><\/strong> in Windows CE\/Windows  Mobile, you have to show the captured image with a custom developed image viewer. There you  may need additional image manipulation functionality like zooming, rotation and  cropping etc. Unfortunately Windows CE 6.0 doesn\u2019t have an image viewer  application at all. But Windows CE supports Imaging APIs to handle the various  file types like JPG, BMP, TIFF and GIF etc\u2026<\/span><\/p>\n<p class=\"MsoNormal\" style=\"text-align: justify;\"><span style=\"color: #000000;\"><strong>Effective way of handing the JPEG images on Image  viewer<\/strong><\/span><\/p>\n<p class=\"MsoNormal\" style=\"text-align: justify;\"><span style=\"color: #000000;\">Imaging APIs are accessed through COM interfaces. To Load the  image you have to use <em><span style=\"font-size: 10pt;\">IImagingFactory<\/span> <\/em>Interface with the class ID  <em><span style=\"font-size: 10pt;\">CLSID_ImagingFactory<\/span>.<\/em> Following code  snippet show the procedure to load the imaging COM interfaces.<\/span><\/p>\n<p class=\"MsoNormal\" style=\"text-align: justify;\"><span style=\"color: #000000;\"><em><span style=\"font-size: 10pt;\">CoCreateInstance  (CLSID_ImagingFactory, NULL,CLSCTX_INPROC_SERVER, IID_IImagingFactory, (void **)&amp;m_pImgFactory).<\/span><\/em><strong><span style=\"font-size: 10pt;\"> <\/span><\/strong>The m_pImgFactory  is the pointer to the <em><span style=\"font-size: 10pt;\">IImagingFactory. <\/span><\/em><\/span><\/p>\n<p class=\"MsoNormal\" style=\"text-align: justify;\"><span style=\"color: #000000;\"><strong>Opening an image file<\/strong><\/span><\/p>\n<p class=\"MsoNormal\" style=\"text-align: justify;\"><span style=\"color: #000000;\">Use the <em><span style=\"font-size: 10pt;\">IImagingFactory ::CreateImageFromFile(const WCHAR* filename,  IImage** image) <\/span><\/em>to open  the file.<\/span><\/p>\n<p class=\"MsoNormal\" style=\"text-align: justify;\"><span style=\"color: #000000;\"><strong> <\/strong><\/span><\/p>\n<p class=\"MsoNormal\" style=\"text-align: justify;\"><span style=\"color: #000000;\"><strong>Simple way to draw the Image on the  Screen<\/strong><\/span><\/p>\n<p class=\"MsoNormal\" style=\"text-align: justify;\"><span style=\"color: #000000;\">We can use the<em> <\/em><span style=\"font-size: 10pt;\"><em>IImage :: Draw( HDC <\/em><em>hdc, const  RECT* <\/em><em>dstRect,OPTIONAL const RECT* <\/em><em>srcRect)<\/em><\/span><strong><span style=\"font-size: 10pt;\"> <\/span><\/strong>to draw the image on the screen with the required  <em>dstRect <\/em>size. But when our application Menu area may over write some part  of the image, we may need to redraw the image in WM_PAINT on our window proc.  <em>IImage::Draw() <\/em>function will decode the image and draw every time, while  calling the function. This makes your application slow, while clicking the  Menu.<\/span><\/p>\n<p class=\"MsoNormal\" style=\"text-align: justify;\"><span style=\"color: #000000;\">To avoid this, we can use the<strong> <\/strong><em><span style=\"font-size: 10pt;\">Image::SetImageFlags(ImageFlagsCaching) <\/span><\/em>to cache the bitmap area and to reuse it  for the next time. The disadvantage is,<em> <\/em><em><span style=\"font-size: 10pt;\">IImage::Draw()<\/span><\/em> may fail because of\u00a0 insufficient memory to cache the  higher Mega Pixel files. This will happen in Windows Mobile (virtual memory  limitations for each process). So we need to find the alternate solution, that  should be effectively handling the memory and to maintain the  performance.<strong><br \/>\n<\/strong><\/span><\/p>\n<p class=\"MsoNormal\" style=\"text-align: justify;\"><span style=\"color: #000000;\"><strong>Effective way to draw the image  on the screen<\/strong><\/span><\/p>\n<p class=\"MsoNormal\" style=\"text-align: justify;\"><span style=\"color: #000000;\">The Effective way is, creating the bitmap for the exact  required screen size once and uses it for several times. Following are the steps  to create and draw the bitmap.<\/span><\/p>\n<ul style=\"text-align: justify;\">\n<li><span style=\"color: #000000;\"><span style=\"font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;\"> <\/span>Passing <em><span style=\"font-size: 10pt; line-height: 115%;\">IImage<\/span><span style=\"font-size: 10pt; line-height: 115%;\"> <\/span><\/em>interface<span style=\"font-size: 10pt; line-height: 115%;\"> <\/span>to<span style=\"font-size: 10pt; line-height: 115%;\"> <em>IImagingFactory::CreateBitmapFromImage(IImage* <\/em><em>image, OPTIONAL UINT <\/em><em>width, OPTIONAL UINT <\/em><em>height, OPTIONAL PixelFormatID <\/em><em>pixelFormat,\u00a0 InterpolationHint <\/em><em>hints, IBitmapImage** <\/em><em>bitmap)<\/em> <\/span>will provide <em><span style=\"font-size: 10pt; line-height: 115%;\">IBitmapImage<\/span><\/em><strong><span style=\"font-size: 10pt; line-height: 115%;\">. <\/span><\/strong>We can create the bitmap to the required  size. (ie) your required screen size. It will consume memory only to the width,  height and the required <em><span style=\"font-size: 10pt; line-height: 115%;\">pixelFormat <\/span><\/em><strong><em><span style=\"font-size: 10pt; line-height: 115%;\">. <\/span><\/em><\/strong>Using this you can show higher Mega  pixels images.<\/span><\/li>\n<\/ul>\n<ul style=\"text-align: justify;\">\n<li><span style=\"color: #000000;\">Using this <em><span style=\"font-size: 10pt; line-height: 115%;\">IBitmapImage::LockBits(const  RECT*rect,UINT\u00a0 flags,\u00a0 PixelFormatID pixelFormat,  BitmapData*\u00a0\u00a0 lockedBitmapData)<\/span><span style=\"font-size: 10pt; line-height: 115%;\"> <\/span><\/em>we can get the<span style=\"font-size: 10pt; line-height: 115%;\"> <em>BitmapData <\/em><\/span>class, containing the width, height, scan0  ( bitmap area starting address) and other necessary data. Release the bitmap  area by calling <em><span style=\"font-size: 10pt; line-height: 115%;\">IBitmapImage::UnlockBits<\/span><\/em> function.<\/span><\/li>\n<\/ul>\n<ul style=\"text-align: justify;\">\n<li><span style=\"color: #000000;\">Using this <em><span style=\"font-size: 10pt; line-height: 115%;\">BitmapData<\/span><\/em><em> <\/em>information, we can create the <em><span style=\"font-size: 10pt; line-height: 115%;\">BITMAPINFO<\/span><\/em> structure as follows:<span style=\"font-size: 10pt; line-height: 115%;\"><br \/>\n<\/span><\/span><\/li>\n<\/ul>\n<p class=\"MsoListParagraph\" style=\"text-align: justify;\"><span style=\"color: #000000;\"><em><span style=\"font-size: 10pt; line-height: 115%;\">m_pBitMapInfo =(BITMAPINFO*) new  char[sizeof(BITMAPINFO)+ 4];<\/span><\/em><\/span><\/p>\n<p class=\"MsoListParagraph\" style=\"text-align: justify;\"><span style=\"color: #000000;\"><em><span style=\"font-size: 10pt; line-height: 115%;\">\/\/Now  write the BITMAPINFOHEADER<\/span><\/em><\/span><\/p>\n<p class=\"MsoListParagraph\" style=\"text-align: justify;\"><span style=\"color: #000000;\"><em><span style=\"font-size: 10pt; line-height: 115%;\">m_pBitMapInfo-&gt;bmiHeader.biSize =  sizeof(BITMAPINFOHEADER);<\/span><\/em><\/span><\/p>\n<p class=\"MsoListParagraph\" style=\"text-align: justify;\"><span style=\"color: #000000;\"><em><span style=\"font-size: 10pt; line-height: 115%;\">m_pBitMapInfo-&gt;bmiHeader.biWidth =  m_Bitmapdata.Width;<\/span><\/em><\/span><\/p>\n<p class=\"MsoListParagraph\" style=\"text-align: justify;\"><span style=\"color: #000000;\"><em><span style=\"font-size: 10pt; line-height: 115%;\">m_pBitMapInfo-&gt;bmiHeader.biHeight  = -(LONG)m_Bitmapdata.Height;<\/span><\/em><\/span><\/p>\n<p class=\"MsoListParagraph\" style=\"text-align: justify;\"><span style=\"color: #000000;\"><em><span style=\"font-size: 10pt; line-height: 115%;\">m_pBitMapInfo-&gt;bmiHeader.biPlanes  = 1;<\/span><\/em><\/span><\/p>\n<p class=\"MsoListParagraph\" style=\"text-align: justify;\"><span style=\"color: #000000;\"><em><span style=\"font-size: 10pt; line-height: 115%;\">m_pBitMapInfo-&gt;bmiHeader.biBitCount  = 16;<\/span><\/em><\/span><\/p>\n<p class=\"MsoListParagraph\" style=\"text-align: justify;\"><span style=\"color: #000000;\"><em><span style=\"font-size: 10pt; line-height: 115%;\">m_pBitMapInfo-&gt;bmiHeader.biCompression  = BI_BITFIELDS;<\/span><\/em><\/span><\/p>\n<p class=\"MsoListParagraph\" style=\"text-align: justify;\"><span style=\"color: #000000;\"><em><span style=\"font-size: 10pt; line-height: 115%;\">m_pBitMapInfo-&gt;bmiHeader.biSizeImage  = m_Bitmapdata.Width*m_Bitmapdata.Height;<\/span><\/em><\/span><\/p>\n<p class=\"MsoListParagraph\" style=\"text-align: justify;\"><span style=\"color: #000000;\"><em><span style=\"font-size: 10pt; line-height: 115%;\">m_pBitMapInfo-&gt;bmiHeader.biClrImportant  = 0;<\/span><\/em><\/span><\/p>\n<p class=\"MsoListParagraph\" style=\"text-align: justify;\"><span style=\"color: #000000;\"><em><span style=\"font-size: 10pt; line-height: 115%;\">m_pBitMapInfo-&gt;bmiHeader.biClrUsed  = 1;<\/span><\/em><\/span><\/p>\n<p class=\"MsoListParagraph\" style=\"text-align: justify;\"><span style=\"color: #000000;\"><em><span style=\"font-size: 10pt; line-height: 115%;\">unsigned long *ptr = (unsigned long  *)(m_pBitMapInfo-&gt;bmiColors);<\/span><\/em><\/span><\/p>\n<p class=\"MsoListParagraph\" style=\"text-align: justify;\"><span style=\"color: #000000;\"><em><span style=\"font-size: 10pt; line-height: 115%;\"> ptr[0] = 0xf800;<\/span><\/em><\/span><\/p>\n<p class=\"MsoListParagraph\" style=\"text-align: justify;\"><span style=\"color: #000000;\"><em><span style=\"font-size: 10pt; line-height: 115%;\"> ptr[1] = 0x07e0;<\/span><\/em><\/span><\/p>\n<p class=\"MsoListParagraph\" style=\"text-align: justify;\"><span style=\"color: #000000;\"><em><span style=\"font-size: 10pt; line-height: 115%;\"> ptr[2] = 0x001f;<\/span><\/em><\/span><\/p>\n<ul style=\"text-align: justify;\">\n<li><span style=\"color: #000000;\">Passing the <span style=\"font-size: 10pt; line-height: 115%;\"><em>BITMAPINFO <\/em>with <em>BitmapData::scan0 <\/em><\/span>to <em><span style=\"font-size: 10pt; line-height: 115%;\">StretchDIBits<\/span><\/em><span style=\"font-size: 14pt; line-height: 115%; font-family: 'Lucida Console';\"> <\/span>function to draw the image. Since we have the  bitmap data, we can simply redraw during the WM_PAINT without any image decoding  process. It will avoid the unnecessary overhead of the  application.<\/span><\/li>\n<\/ul>\n<ul style=\"text-align: justify;\">\n<li><span style=\"color: #000000;\"><span style=\"font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;\"> <\/span>For zooming and panning process, we can  simply create the bitmap for the necessary size and we can show the part of the  image, also moving and showing the image seamlessly with above described  APIs.<\/span><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>There are some cases where we may need to develop a DLL or application to&#8230;<\/p>\n","protected":false},"author":12,"featured_media":1250,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[213,215],"tags":[85,96],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.e-consystems.com\/blog\/system-on-module-som\/wp-json\/wp\/v2\/posts\/221"}],"collection":[{"href":"https:\/\/www.e-consystems.com\/blog\/system-on-module-som\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.e-consystems.com\/blog\/system-on-module-som\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.e-consystems.com\/blog\/system-on-module-som\/wp-json\/wp\/v2\/users\/12"}],"replies":[{"embeddable":true,"href":"https:\/\/www.e-consystems.com\/blog\/system-on-module-som\/wp-json\/wp\/v2\/comments?post=221"}],"version-history":[{"count":1,"href":"https:\/\/www.e-consystems.com\/blog\/system-on-module-som\/wp-json\/wp\/v2\/posts\/221\/revisions"}],"predecessor-version":[{"id":2951,"href":"https:\/\/www.e-consystems.com\/blog\/system-on-module-som\/wp-json\/wp\/v2\/posts\/221\/revisions\/2951"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.e-consystems.com\/blog\/system-on-module-som\/wp-json\/wp\/v2\/media\/1250"}],"wp:attachment":[{"href":"https:\/\/www.e-consystems.com\/blog\/system-on-module-som\/wp-json\/wp\/v2\/media?parent=221"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.e-consystems.com\/blog\/system-on-module-som\/wp-json\/wp\/v2\/categories?post=221"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.e-consystems.com\/blog\/system-on-module-som\/wp-json\/wp\/v2\/tags?post=221"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}