00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "ioJPG.hpp"
00028 #include "ImageException.hpp"
00029
00030
00031
00032
00033 #include <sstream>
00034 #include <fstream>
00035 #include <jpeglib.h>
00036 #include <setjmp.h>
00037
00038 using namespace std;
00039
00040
00041
00042
00043 namespace kn{
00044
00045
00046
00047 int loadJPG(Image<unsigned char>& res,const std::string& filename) {
00048
00049 unsigned char* thebuffer;
00050 size_t w_size,h_size;
00051 unsigned int nb_component;
00052 std::ifstream is;
00053 std::stringstream serr;
00054
00055
00056
00057 struct jpeg_decompress_struct cinfo;
00058
00059
00060
00061
00062 struct jpeg_error_mgr jerr;
00063
00064 FILE * infile;
00065 JSAMPARRAY buffer;
00066 int row_stride;
00067 int typtmp;
00068
00069
00070 if (res.size()>0) {
00071 throw ImageException("Image already allocated. Cannot store JPG image in that image.","loadImageJPG");
00072 }
00073
00074
00075 infile = fopen(filename.c_str(),"rb");
00076 if (infile == NULL) {
00077 throw ImageException("Error could not read file "+filename,"loadImageJPG");
00078 }
00079
00080
00081
00082 cinfo.err = jpeg_std_error(&jerr);
00083
00084 jpeg_create_decompress(&cinfo);
00085
00086 jpeg_stdio_src(&cinfo, infile);
00087
00088
00089
00090
00091
00092
00093
00094 jpeg_read_header(&cinfo, TRUE);
00095
00096
00097 h_size = cinfo.image_height;
00098 w_size = cinfo.image_width;
00099 nb_component = cinfo.num_components;
00100 typtmp = cinfo.jpeg_color_space;
00101
00102 switch(typtmp) {
00103 case JCS_GRAYSCALE :
00104 if (nb_component != 1)
00105 throw ImageException("Nb of component does not match type of JPG file (L)","loadImageJPG");
00106 typtmp = L_JPG;
00107 break;
00108 case JCS_RGB :
00109 case JCS_YCbCr :
00110 if (nb_component != 3)
00111 throw ImageException("Nb of component does not match type of JPG file (RGB)","loadImageJPG");
00112 typtmp = RGB_JPG;
00113 break;
00114 case JCS_CMYK :
00115 if (nb_component != 4)
00116 throw ImageException("Nb of component does not match type of JPG file (RGBA)","loadImageJPG");
00117 typtmp = RGBA_JPG;
00118 break;
00119 case JCS_YCCK :
00120 throw ImageException("We do not handle YCCK jpg file format","loadImageJPG");
00121 case JCS_UNKNOWN :
00122 default :
00123 throw ImageException("jpg file format unknown","loadImageJPG");
00124 }
00125
00126
00127
00128
00129 (void) jpeg_start_decompress(&cinfo);
00130
00131 if ((cinfo.output_width != (unsigned int)w_size) ||
00132 (cinfo.output_height != (unsigned int)h_size) ||
00133 ((unsigned int)cinfo.out_color_components != nb_component)) {
00134 throw ImageException("JPG Loader error : Difference between header and jpg data in file","loadImageJPG");
00135 }
00136
00137 thebuffer = new unsigned char[w_size*h_size*nb_component];
00138 if (thebuffer == NULL)
00139 throw ImageException("JPG Loader error : Unable to get memory !","loadImageJPG");
00140
00141
00142
00143
00144
00145
00146
00147
00148 row_stride = w_size * nb_component;
00149
00150 buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
00151
00152
00153
00154
00155
00156
00157 unsigned char *ptr = thebuffer;
00158 while (cinfo.output_scanline < cinfo.output_height) {
00159
00160
00161
00162
00163 (void) jpeg_read_scanlines(&cinfo, buffer, 1);
00164
00165
00166
00167
00168
00169
00170
00171 memcpy(ptr,buffer[0],row_stride);
00172 ptr += row_stride;
00173 }
00174
00175
00176 (void) jpeg_finish_decompress(&cinfo);
00177
00178
00179 jpeg_destroy_decompress(&cinfo);
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 try {
00193 res.buildImageFromBuffer(w_size,h_size,nb_component,thebuffer);
00194 if (thebuffer != NULL) delete[](thebuffer);
00195 }
00196 catch (ImageException &e) {
00197
00198 if (thebuffer != NULL) delete[](thebuffer);
00199 throw ImageException("Exception when building image from buffer : "+e.errorString(),"loadFileJPG");
00200 }
00201
00202
00203 fclose(infile);
00204 return typtmp;
00205
00206 }
00207
00208
00209
00210
00211 }