?
Solved

Convert a jpeg to HBITMAP

Posted on 2003-03-24
11
Medium Priority
?
1,010 Views
Last Modified: 2013-12-03
I've been all over the net trying to find a simple C program that uses a jpeg file.  I have also delved into IJG's source code.

Is there a simple way to use a jpeg in a C application (needs to be in plain C)?  Im having difficulties with the IJG library and duplicate declarations (conflicting with windows library).. and am not sure how to convert on such a low level (inverting scanlines plus bitmap file data).

I'm sure Im not the first person that has run into this.

Thanks in advance.
0
Comment
Question by:akascream
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 4
11 Comments
 
LVL 49

Expert Comment

by:DanRollins
ID: 8197384
The problems withIJG source code typedefs are well known.  The fixes are desribed here:
    http://www.smalleranimals.com/jpegfile.htm
And that page provides a download of a VC++ project that handles reading and writing JPG files.

-- Dan
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 8197456
The paintlib libary (also C++)
       http://www.paintlib.de/paintlib/
easilty converts a jpg to a bitmap.  In the tutorial, it shows how to do it in four lines of code.

Is there any particular reason you don't want to use C++?  Is it just becasue of the difficulties you have experienced compiling the IJG libraries?  C++ is by far the superior programming language.

-- Dan
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 8197482
Just another thought.... You can use Windows tools (the Paint program) to read a JPG file and save it as a bmp file.  So if this is a one-time thing, then that's the way to go -- because once you have a BMP file you can use the LoadImage() api to read it from disk to obtain an HBITMAP.
-- Dan
0
Get free NFR key for Veeam Availability Suite 9.5

Veeam is happy to provide a free NFR license (1 year, 2 sockets) to all certified IT Pros. The license allows for the non-production use of Veeam Availability Suite v9.5 in your home lab, without any feature limitations. It works for both VMware and Hyper-V environments

 
LVL 49

Expert Comment

by:DanRollins
ID: 8197591
If you want to avoid using external libraries, check out the IPicture COM object.  The source-code example, from  
      http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B218972
is a Win32 program (non MFC) that shows how easy it is to use.  After calling OleLoadPicture, you can use IPicture::get_Handle() to obtain an HBITMAP.  The sample code simplies all of the OLE stuff by providng a simple LoadPictureFile() function.
-- Dan
0
 

Author Comment

by:akascream
ID: 8204542
The problem I have with C++ is the same problem I have with bmp files for this project.  We are trying to save every nanobyte of size so we can email these to clients.  We are even trying different C compilers to get the smallest possible file size.
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 8205207
The smallest footprint option will be the last one (IPicture) in that all of the functionality for conversion is contained in an external system DLL.  Yes, you must use C++ (COM-object access is near to impossible with pure C).  However, C++ programs need not be any larger than C programs!  They will only be larger if you link in lots of unneeded library code.

If footprint is the major issue, then use Zip2Exe or other similar compression program.  That can often shrink an EXE file to 1/2 or even 1/4 of its actual size.  When executed, it transparently uncompresses and runs the original program.

-- Dan
0
 

Author Comment

by:akascream
ID: 8284736
I apologize for not responding for a while.. but I was working on another project.  

Anyway, I found code to do what I need.. and it works fine.  But I am loading the jpeg from a resource and need this function to work with that data instead of loading a file itself.  Any ideas?

Here is the function:

HBITMAP ReadJpegFile( LPSTR pFile )
   {
   HANDLE hFile;
   HBITMAP hBmp;
   DWORD dwSize;
   DWORD dwRead;
   HGLOBAL hMemJpeg;
   LPSTREAM lpStream;
   OLE_HANDLE hJpegBmp;
   HRESULT hr;
   LPPICTURE lpPicture = NULL;
   void *pMemJpeg;

   /* Open the file and get the size. */
   if((hFile = CreateFile(pFile, GENERIC_READ, FILE_SHARE_READ,
     NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
     return NULL;
   if((dwSize = GetFileSize(hFile, NULL)) == 0xFFFFFFFF)
      {
      CloseHandle(hFile);
      return NULL;
      }

   /* Allocate space for file, read it in, and then close the file again. */
   if((hMemJpeg = GlobalAlloc(GMEM_MOVEABLE, dwSize)) == NULL)
      {
      CloseHandle(hFile);
      return NULL;
      }
   if((pMemJpeg = GlobalLock(hMemJpeg)) == NULL)
      {
      CloseHandle(hFile);
      GlobalFree(hMemJpeg);
      return NULL;
      }
   if(!ReadFile(hFile, pMemJpeg, dwSize, &dwRead, NULL))
      {
      CloseHandle(hFile);
      GlobalFree(hMemJpeg);
      return NULL;
      }
   CloseHandle(hFile);
   GlobalUnlock(hMemJpeg);

   /* Create the stream and load the picture. */
   if((hr = CreateStreamOnHGlobal(hMemJpeg, TRUE, &lpStream)) != S_OK)
      {
      GlobalFree(hMemJpeg);
      return NULL;
      }
   if(OleLoadPicture(lpStream, dwSize, FALSE, &IID_IPicture, &lpPicture) != S_OK)
      {
      GlobalFree(hMemJpeg);
      lpStream->lpVtbl->Release(lpStream);
      return NULL;
      }

   /* Get the handle to the image, and then copy it. */
   if((lpPicture->lpVtbl->get_Handle(lpPicture, &hJpegBmp)) != S_OK)
      {
      GlobalFree(hMemJpeg);
      lpStream->lpVtbl->Release(lpStream);
      lpPicture->lpVtbl->Release(lpPicture);
      return NULL;
      }
   if((hBmp = CopyImage((HANDLE *) hJpegBmp, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG)) == NULL)
      {
      GlobalFree(hMemJpeg);
      lpStream->lpVtbl->Release(lpStream);
      lpPicture->lpVtbl->Release(lpPicture);
      return NULL;
      }

   /* Free the original image and memory. */
   GlobalFree(hMemJpeg);
   lpStream->lpVtbl->Release(lpStream);
   lpPicture->lpVtbl->Release(lpPicture);
   return hBmp;
} /* End of ReadJpegFile(). */
0
 
LVL 49

Accepted Solution

by:
DanRollins earned 300 total points
ID: 8286451
>> Anyway, I found code to do what I need.. and it works fine.  

That code boils down to a call to OleLoadPicture exactly as I described.  If you want to load it from a resource rather than an external file, then replace all of the code that reads it from the file with code that reades it from the resource.  The key APIs are

   FindResource()     ... use the returned handle in a call to...
   LoadResource()   ... and use ...
   SizeofResource() ... to learn the size in bytes.  And use ...
   LockResource()    ... to get a pointer to the data.

knowing the size and the pointer to the data, you can create an IStream, using the same technique used in the code you gave in your last post.

-- Dan
0
 

Author Comment

by:akascream
ID: 8287512
something like this?

test = LoadResource(NULL, FindResource(NULL, "SKIN","JPEG") );
dwSize = SizeofResource(NULL, test);
hMemJpeg = GlobalAlloc(GMEM_MOVEABLE, dwSize);
pMemJpeg = GlobalLock( LockResource(test) );

forgive my ignorance concerning the win32 API.. I'm working on it :P
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 8289168
You will not need to allocate any memory -- LoadResource and LockResource will provide the data in a buffer.  Other than that, it looks pretty good.

The actual arguments to the FindResource call will depend upon how you stored the JPG into your resource and the ID that you used when you did that.

-- Dan
0
 

Author Comment

by:akascream
ID: 8292873
huzzah!.. thanks for your help =)
0

Featured Post

NFR key for Veeam Backup for Microsoft Office 365

Veeam is happy to provide a free NFR license (for 1 year, up to 10 users). This license allows for the non‑production use of Veeam Backup for Microsoft Office 365 in your home lab without any feature limitations.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this article, I will show how to use the Ribbon IDs Tool Window to assign the built-in Office icons to a ribbon button.  This tool will help us to find the OfficeImageId that corresponds to our desired built-in Office icon. The tool is part of…
After several hours of googling I could not gather any information on this topic. There are several ways of controlling the USB port connected to any storage device. The best example of that is by changing the registry value of "HKEY_LOCAL_MACHINE\S…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
In this video we outline the Physical Segments view of NetCrunch network monitor. By following this brief how-to video, you will be able to learn how NetCrunch visualizes your network, how granular is the information collected, as well as where to f…

765 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question