Sign in to follow this  
Koobazaur

Problem with JPEG using IJG

Recommended Posts

Hey, I am using the Independant JPEG Group developer sources to save and load a JPEG file. I have originally created my program for Dev-C++ on which it worked great but now, switching to MS Visual c++ 2003 I keep getting unhandled exceptions with my old .dll.a file. Well, I tried using a Win32 port fromhere which generates a static library file, but when I add that file to my project I get a whole bunch of linker errors:
SignatureGenerator error LNK2019: unresolved external symbol _jpeg_write_scanlines referenced in function "bool __cdecl SaveJPEG(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct HBITMAP__ *,int)" (?SaveJPEG@@YA_NV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@PAUHBITMAP__@@H@Z)
SignatureGenerator error LNK2019: unresolved external symbol _jpeg_read_header referenced in function "struct HBITMAP__ * __cdecl LoadJPEG(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?LoadJPEG@@YAPAUHBITMAP__@@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)
SignatureGenerator error LNK2019: unresolved external symbol _jpeg_read_scanlines referenced in function "struct HBITMAP__ * __cdecl LoadJPEG(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?LoadJPEG@@YAPAUHBITMAP__@@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)
SignatureGenerator error LNK2019: unresolved external symbol _jpeg_set_defaults referenced in function "bool __cdecl SaveJPEG(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct HBITMAP__ *,int)" (?SaveJPEG@@YA_NV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@PAUHBITMAP__@@H@Z)
SignatureGenerator error LNK2019: unresolved external symbol _jpeg_set_quality referenced in function "bool __cdecl SaveJPEG(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct HBITMAP__ *,int)" (?SaveJPEG@@YA_NV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@PAUHBITMAP__@@H@Z)
SignatureGenerator error LNK2019: unresolved external symbol _jpeg_start_compress referenced in function "bool __cdecl SaveJPEG(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct HBITMAP__ *,int)" (?SaveJPEG@@YA_NV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@PAUHBITMAP__@@H@Z)
SignatureGenerator error LNK2019: unresolved external symbol _jpeg_start_decompress referenced in function "struct HBITMAP__ * __cdecl LoadJPEG(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?LoadJPEG@@YAPAUHBITMAP__@@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)
SignatureGenerator error LNK2019: unresolved external symbol _jpeg_std_error referenced in function "bool __cdecl SaveJPEG(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct HBITMAP__ *,int)" (?SaveJPEG@@YA_NV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@PAUHBITMAP__@@H@Z)
SignatureGenerator error LNK2019: unresolved external symbol _jpeg_stdio_dest referenced in function "bool __cdecl SaveJPEG(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct HBITMAP__ *,int)" (?SaveJPEG@@YA_NV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@PAUHBITMAP__@@H@Z)
SignatureGenerator error LNK2019: unresolved external symbol _jpeg_stdio_src referenced in function "struct HBITMAP__ * __cdecl LoadJPEG(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?LoadJPEG@@YAPAUHBITMAP__@@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)


FYI My full code looks like this: Header:
/*
    JPEG Save / Load

 This file provides functions for saving and loading a JPEG file.
 This is based on the IJG dlls for JPEG manipulation.
 
 Headers Required: jpeglib.h,  jconfig.h, jmorecfg.h, jerror.h,

*/
#ifndef JPEGSAVELOAD_H_
#define JPEGSAVELOAD_H_

#include <windows.h>
#include <string> 

#include "jpeglib.h"
#include "kBitmaps.h"

using namespace std;

//=============== SaveJPEG ========================
// Saves a 24 bit DIB bitmap to a JPEG file
// string szFilename - filename under which we want to 
//                     save the file
// HBITMAP bmp       - bitmap we want to save
// int quality       - quality of the jpeg (0-100)
// RETURN: 1 if succeded, 0 if failed
//==================================================  
bool SaveJPEG(string szFilename, HBITMAP bmp, int quality);


//=============== LoadJPEG ========================
// Loads a JPEG and returns it as a DIB bitmap
// string szFilename - filename of the image
// RETURN: returns the loaded DIB HBITMAP. 0 if failed
//==================================================  
HBITMAP LoadJPEG(string szFilename);
#endif



Cpp:
#include "jpegloadsave.h"


using namespace std;

//=============== SaveJPEG =====================================================
// Saves a 24 bit DIB bitmap to a JPEG file
// string szFilename - filename under which we want to save the file
// HBITMAP bmp       - bitmap we want to save
// int quality       - quality of the jpeg (0-100)
// RETURN: 1 if succeded, 0 if failed
//==============================================================================  
bool SaveJPEG(string szFilename, HBITMAP hbmp, int quality)
{     
 kBMPWrapper wBmp;       //wrapper for our bitmap
 JSAMPLE * image_buffer; //the image buffer that holds our image
 JSAMPLE * scanline;     //a buffer that will hold just single scanline. 
                         //Remember that in a BMP the colors are stored as BGR
                         //thus we must modify the order to get RGB this is 
                         //why we re-do each scanline separately  
   
 struct jpeg_compress_struct cinfo; //jpeg compression structure
 struct jpeg_error_mgr jerr;        //jpeg error structure
 FILE * outfile;                    //the file we are saving to (we use FILE 
                                    //instead of fstream as that what the
                                    //the JPEG library expects)

 //wrap wrapper around the bitmap
 wBmp.Wrap(hbmp);              
 //set the image buffer to the bitmap's data
 image_buffer = (JSAMPLE *)wBmp.GetPixelPointer();


  //STEP 1

  //Create the JPEG structures
  jpeg_create_compress(&cinfo);
  cinfo.err = jpeg_std_error(&jerr);
 
  //step 2

  //open the file for writing, make sure it works
  if( (outfile = fopen(szFilename.c_str(), "wb" )) == 0 ) 
	  return 0; 

  //set the file as the destination
  jpeg_stdio_dest(&cinfo, outfile);
  
  
  //Step 3: set parameters for compression

  cinfo.image_width = wBmp.GetWidth();      //width
  cinfo.image_height = wBmp.GetHeight();    //height
  cinfo.input_components = 3;               //bytes per pixel (24 bit)
  cinfo.in_color_space = JCS_RGB;           //RGB coloring 

  jpeg_set_defaults(&cinfo);                //defaults
  jpeg_set_quality(&cinfo, quality, TRUE);  //quality

  // Step 4: Start compressor 
  jpeg_start_compress(&cinfo, 1);
  
  //for each scanline; we are going from top to bottom because the
  //bitmap data is stored upside down relative to the JPEG
  for(int y=cinfo.image_height-1; y >= 0; y--)
  {
   //create a new scanline of the proper width (24bit)     
   scanline = new JSAMPLE[cinfo.image_width*3];  
   
   //now, for each pixel (NOT BYTE) in the scanline
   for(int x=0; x<cinfo.image_width; x++)
           {
            //fill the scanline with pixels from the current scanline
            scanline[x*3] = GetRValue(wBmp.GetPixel(x,y));
            scanline[x*3+1] = GetGValue(wBmp.GetPixel(x,y));
            scanline[x*3+2] = GetBValue(wBmp.GetPixel(x,y));    
           }    

   //pass it in
   jpeg_write_scanlines(&cinfo, &scanline, 1);
   
   //delete scanline 
   delete scanline;
  }
  
  //Step 6: Finish compression 
  
  jpeg_finish_compress(&cinfo); //finish 
  fclose(outfile);              //close file
  jpeg_destroy_compress(&cinfo);//destroy JPEG compression object

  //And we're done!  
  return 1; 
}

//=============== LoadJPEG ====================================================
// Loads a JPEG and returns it as a DIB bitmap
// string szFilename - filename of the image
// RETURN: returns the loaded DIB HBITMAP. 0 if failed
//==============================================================================  
HBITMAP LoadJPEG(string szFilename)
{
  	struct jpeg_decompress_struct cinfo; //JPEG decompression structure
	struct jpeg_error_mgr jerr;          //JPEG error structure    
	FILE * infile;                       //file we will read from (we use FILE 
                                         //instead of fstream as that what the
                                         //the JPEG library expects)
	HBITMAP Bitmap=NULL;                 //our bitmap we will load to
	kBMPWrapper wBmp;                    //bitmap wrapper
    JSAMPLE * image_buffer=0; 	         //the image buffer to which we'll write
    JSAMPLE * scanline=0;                //this will hold a single scanline

	
    //open file
	if ((infile = fopen(szFilename.c_str(), "rb")) == NULL)    
	    return NULL;
        	
    //Create the JPEG structures
	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_decompress(&cinfo); 	

	//set the source to our file
	jpeg_stdio_src(&cinfo, infile);
	
	//load the header
	jpeg_read_header(&cinfo, TRUE);

	//start decompression
	jpeg_start_decompress(&cinfo);
	
	//create the DIB bitmap, my good sir!
	Bitmap = CreateDIBBitmap(cinfo.output_width, cinfo.output_height);
	
	//wrap the wrapper so that we can write data
	wBmp.Wrap(Bitmap);
	
    //set the image buffer to the bitmap's data
	image_buffer = (JSAMPLE *)wBmp.GetPixelPointer();
	
//Remember that in a BMP the colors are stored as BGR
//thus we must modify the order to get RGB this is 
//why we re-do each scanline separately. Also, we are going 
//from top to bottom because the bitmap data is stored 
//upside down relative to the JPEG
  for(int y = cinfo.output_height-1; y >=0; y--)
        {  
         //create a scanline   
         scanline = new JSAMPLE[cinfo.output_width * cinfo.output_components];     
         
         //read it                        
         jpeg_read_scanlines(&cinfo, &scanline ,1);
         
         //for every pixel in the scanline
         for(int x=0; x<cinfo.output_width; x++)
           {
            //fill the scanline with pixels from the current scanline, switching order around    
            wBmp.SetPixel(x, y, RGB(scanline[x*3], scanline[x*3+1], scanline[x*3+2]));
           }  
             
          //delete scanline 
          delete scanline;
         }
            
 
	//end decompression
	jpeg_finish_decompress(&cinfo);
	
	//destroy the object because it's evil
	jpeg_destroy_decompress(&cinfo);
	
	//return the prepared ready bitmap	
	return Bitmap;
}


[Edited by - Koobazaur on April 6, 2007 3:16:39 AM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this