• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1035
  • Last Modified:

Convert a jpeg to HBITMAP

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
akascream
Asked:
akascream
  • 7
  • 4
1 Solution
 
DanRollinsCommented:
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
 
DanRollinsCommented:
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
 
DanRollinsCommented:
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 expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

 
DanRollinsCommented:
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
 
akascreamAuthor Commented:
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
 
DanRollinsCommented:
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
 
akascreamAuthor Commented:
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
 
DanRollinsCommented:
>> 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
 
akascreamAuthor Commented:
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
 
DanRollinsCommented:
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
 
akascreamAuthor Commented:
huzzah!.. thanks for your help =)
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 7
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now