00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <yafray_config.h>
00024
00025 #ifdef HAVE_JPEG
00026
00027 #include <iostream>
00028 #include <cstdio>
00029 #include <cstdlib>
00030 using namespace std;
00031
00032 extern "C"
00033 {
00034 #include <setjmp.h>
00035 #include <jpeglib.h>
00036 }
00037 #include <utilities/buffer.h>
00038
00039
00040 __BEGIN_YAFRAY
00041
00042
00043
00044
00045
00046 METHODDEF(void) _jpeg_errmsg(j_common_ptr cinfo)
00047 {
00048 #ifdef __DEBUG__
00049 char buffer[JMSG_LENGTH_MAX];
00050 (*cinfo->err->format_message)(cinfo, buffer);
00051 cout << "JPEG Library Error: " << buffer << endl;
00052 #endif
00053 }
00054
00055 struct my_jpeg_error_mgr {
00056 struct jpeg_error_mgr pub;
00057 jmp_buf setjmp_buffer;
00058 };
00059
00060
00061 typedef struct my_jpeg_error_mgr *error_ptr;
00062
00063 void my_jpeg_error_exit(j_common_ptr cinfo)
00064 {
00065 error_ptr myerr = (error_ptr)cinfo->err;
00066 (*cinfo->err->output_message)(cinfo);
00067 longjmp(myerr->setjmp_buffer, 1);
00068 }
00069
00070
00071
00072 gBuf_t<unsigned char, 4> * load_jpeg(const char *name)
00073 {
00074 struct jpeg_decompress_struct cinfo;
00075 struct my_jpeg_error_mgr jerr;
00076 FILE *input;
00077 gBuf_t<unsigned char, 4> *image;
00078 unsigned char *p;
00079 unsigned char **arr;
00080
00081 input = fopen(name,"rb");
00082 if (input==NULL) {
00083 cout << "File " << name << " not found\n";
00084 return NULL;
00085 }
00086
00087
00088 cinfo.err = jpeg_std_error(&jerr.pub);
00089 cinfo.err->output_message = _jpeg_errmsg;
00090 jerr.pub.error_exit = my_jpeg_error_exit;
00091
00092 if (setjmp(jerr.setjmp_buffer)) {
00093 jpeg_destroy_decompress(&cinfo);
00094 fclose(input);
00095 return NULL;
00096 }
00097
00098 jpeg_create_decompress(&cinfo);
00099 jpeg_stdio_src(&cinfo, input);
00100 jpeg_read_header(&cinfo, TRUE);
00101
00102 jpeg_start_decompress(&cinfo);
00103
00104 bool is_gray = ((cinfo.out_color_space==JCS_GRAYSCALE) & (cinfo.output_components==1));
00105 bool is_rgb = ((cinfo.out_color_space==JCS_RGB) & (cinfo.output_components==3));
00106
00107 bool is_cmyk = ((cinfo.out_color_space==JCS_CMYK) & (cinfo.output_components==4));
00108
00109 #ifdef __DEBUG__
00110 cout << "Loading image " << cinfo.output_width << " x " << cinfo.output_height << endl;
00111 cout << "color depth is " << cinfo.output_components*8 << " bits.\n";
00112 #endif
00113
00114 if ((!is_gray) && (!is_rgb) && (!is_cmyk)) {
00115 cout << "Unsupported color space: " << cinfo.out_color_space
00116 << " depth: " << cinfo.output_components << endl;
00117 jpeg_finish_decompress(&cinfo);
00118 jpeg_destroy_decompress(&cinfo);
00119 return NULL;
00120 }
00121
00122 image = new gBuf_t<unsigned char, 4>(cinfo.output_width, cinfo.output_height);
00123 if (image==NULL)
00124 {
00125 cout << "Error allocating memory\n";
00126 longjmp(jerr.setjmp_buffer, 2);
00127 }
00128
00129 p = (*image)(0,0);
00130
00131
00132 unsigned char* gbuf=NULL;
00133 if (is_gray)
00134 gbuf = new unsigned char[cinfo.image_width];
00135 else if (is_rgb)
00136 gbuf = new unsigned char[cinfo.image_width*3];
00137 else
00138 gbuf = new unsigned char[cinfo.image_width*4];
00139 if (gbuf==NULL) {
00140 cout << "Error allocating memory for temporary scanline buffer\n";
00141 return 0;
00142 }
00143
00144 while (cinfo.output_scanline < cinfo.output_height) {
00145 arr = &gbuf;
00146 jpeg_read_scanlines(&cinfo, arr, 1);
00147 if (is_gray) {
00148 for (unsigned int x=0;x<cinfo.image_width;x++) {
00149 *p++ = gbuf[x];
00150 *p++ = gbuf[x];
00151 *p++ = gbuf[x];
00152 *p++ = 255;
00153 }
00154 }
00155 else if (is_rgb) {
00156 for (unsigned int x=0;x<cinfo.image_width*3;x+=3) {
00157 *p++ = gbuf[x];
00158 *p++ = gbuf[x+1];
00159 *p++ = gbuf[x+2];
00160 *p++ = 255;
00161 }
00162 }
00163 else {
00164
00165 for (unsigned int x=0;x<cinfo.image_width*4;x+=4) {
00166
00167 p[3] = gbuf[x+3];
00168 unsigned char nk = 255-p[3];
00169 p[0] = max(0, min(gbuf[x]-nk, 255));
00170 p[1] = max(0, min(gbuf[x+1]-nk, 255));
00171 p[2] = max(0, min(gbuf[x+2]-nk, 255));
00172 p += 4;
00173
00174 }
00175 }
00176 }
00177 delete[] gbuf;
00178
00179 jpeg_finish_decompress(&cinfo);
00180 jpeg_destroy_decompress(&cinfo);
00181 fclose(input);
00182 return image;
00183 }
00184
00185 __END_YAFRAY
00186
00187 #endif