00001 // Filename: pnmFileTypeJPGReader.cxx 00002 // Created by: mike (19Jun00) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved 00008 // 00009 // All use of this software is subject to the terms of the Panda 3d 00010 // Software license. You should have received a copy of this license 00011 // along with this source code; you will also find a current copy of 00012 // the license at http://www.panda3d.org/license.txt . 00013 // 00014 // To contact the maintainers of this program write to 00015 // panda3d@yahoogroups.com . 00016 // 00017 //////////////////////////////////////////////////////////////////// 00018 00019 #include "pnmFileTypeJPG2000.h" 00020 #include "config_pnmimagetypes.h" 00021 00022 //////////////////////////////////////////////////////////////////// 00023 // Function: PNMFileTypeJPG2000::Reader::Constructor 00024 // Access: Public 00025 // Description: 00026 //////////////////////////////////////////////////////////////////// 00027 PNMFileTypeJPG2000::Reader:: 00028 Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number) : 00029 PNMReader(type, file, owns_file) 00030 { 00031 // Put the magic number bytes back into the file 00032 file->seekg(0); 00033 00034 /* Step 1: allocate and initialize JPEG decompression object */ 00035 00036 /* We set up the normal JPEG error routines, then override error_exit. */ 00037 _cinfo.err = jpeg_std_error(&_jerr.pub); 00038 00039 /* Now we can initialize the JPEG decompression object. */ 00040 jpeg_create_decompress(&_cinfo); 00041 00042 /* Step 2: specify data source (eg, a file) */ 00043 // This is broken, and won't compile. We need to drop in an 00044 // iostream replacement, like we did for JPG. 00045 jpeg_stdio_src(&_cinfo, file); 00046 00047 /* Step 3: read file parameters with jpeg_read_header() */ 00048 00049 jpeg_read_header(&_cinfo, TRUE); 00050 /* We can ignore the return value from jpeg_read_header since 00051 * (a) suspension is not possible with the stdio data source, and 00052 * (b) we passed TRUE to reject a tables-only JPEG file as an error. 00053 * See libjpeg.doc for more info. 00054 */ 00055 00056 /* Step 4: set parameters for decompression */ 00057 _cinfo.scale_num = jpeg_scale_num; 00058 _cinfo.scale_denom = jpeg_scale_denom; 00059 00060 /* Step 5: Start decompressor */ 00061 00062 jpeg_start_decompress(&_cinfo); 00063 /* We can ignore the return value since suspension is not possible 00064 * with the stdio data source. 00065 */ 00066 00067 _num_channels = _cinfo.output_components; 00068 _x_size = (int)_cinfo.output_width; 00069 _y_size = (int)_cinfo.output_height; 00070 _maxval = MAXJSAMPLE; 00071 } 00072 00073 //////////////////////////////////////////////////////////////////// 00074 // Function: PNMFileTypeJPG2000::Reader::Destructor 00075 // Access: Public 00076 // Description: 00077 //////////////////////////////////////////////////////////////////// 00078 PNMFileTypeJPG2000::Reader:: 00079 ~Reader(void) { 00080 jpeg_destroy_decompress(&_cinfo); 00081 } 00082 00083 //////////////////////////////////////////////////////////////////// 00084 // Function: PNMFileTypeJPG2000::Reader::read_data 00085 // Access: Public, Virtual 00086 // Description: Reads in an entire image all at once, storing it in 00087 // the pre-allocated _x_size * _y_size array and alpha 00088 // pointers. (If the image type has no alpha channel, 00089 // alpha is ignored.) Returns the number of rows 00090 // correctly read. 00091 // 00092 // Derived classes need not override this if they 00093 // instead provide supports_read_row() and read_row(), 00094 // below. 00095 //////////////////////////////////////////////////////////////////// 00096 int PNMFileTypeJPG2000::Reader:: 00097 read_data(xel *array, xelval *) { 00098 JSAMPARRAY buffer; /* Output row buffer */ 00099 int row_stride; /* physical row width in output buffer */ 00100 00101 nassertr(_cinfo.output_components == 1 || _cinfo.output_components == 3, 0); 00102 00103 /* We may need to do some setup of our own at this point before reading 00104 * the data. After jpeg_start_decompress() we have the correct scaled 00105 * output image dimensions available, as well as the output colormap 00106 * if we asked for color quantization. 00107 * In this example, we need to make an output work buffer of the right size. 00108 */ 00109 /* JSAMPLEs per row in output buffer */ 00110 row_stride = _cinfo.output_width * _cinfo.output_components; 00111 /* Make a one-row-high sample array that will go away when done with image */ 00112 00113 buffer = (*_cinfo.mem->alloc_sarray) 00114 ((j_common_ptr) &_cinfo, JPOOL_IMAGE, row_stride, 1); 00115 00116 /* Step 6: while (scan lines remain to be read) */ 00117 /* jpeg_read_scanlines(...); */ 00118 00119 /* Here we use the library's state variable cinfo.output_scanline as the 00120 * loop counter, so that we don't have to keep track ourselves. 00121 */ 00122 int x = 0; 00123 while (_cinfo.output_scanline < _cinfo.output_height) { 00124 /* jpeg_read_scanlines expects an array of pointers to scanlines. 00125 * Here the array is only one element long, but you could ask for 00126 * more than one scanline at a time if that's more convenient. 00127 */ 00128 jpeg_read_scanlines(&_cinfo, buffer, 1); 00129 /* Assume put_scanline_someplace wants a pointer and sample count. */ 00130 //put_scanline_someplace(buffer[0], row_stride); 00131 JSAMPROW bufptr = buffer[0]; 00132 for (int i = 0; i < row_stride; i += _cinfo.output_components) { 00133 if (_cinfo.output_components == 1) { 00134 xelval val = (xelval)bufptr[i]; 00135 nassertr(x < _x_size * _y_size, 0); 00136 PNM_ASSIGN1(array[x], val); 00137 } else { 00138 xelval red, grn, blu; 00139 red = (xelval)bufptr[i]; 00140 grn = (xelval)bufptr[i+1]; 00141 blu = (xelval)bufptr[i+2]; 00142 nassertr(x < _x_size * _y_size, 0); 00143 PPM_ASSIGN(array[x], red, grn, blu); 00144 } 00145 x++; 00146 } 00147 } 00148 00149 /* Step 7: Finish decompression */ 00150 00151 jpeg_finish_decompress(&_cinfo); 00152 00153 /* We can ignore the return value since suspension is not possible 00154 * with the stdio data source. 00155 */ 00156 00157 /* At this point you may want to check to see whether any corrupt-data 00158 * warnings occurred (test whether jerr.pub.num_warnings is nonzero). 00159 */ 00160 if (_jerr.pub.num_warnings) { 00161 pnmimage_jpg_cat.warning() 00162 << "Jpeg data may be corrupt" << endl; 00163 } 00164 00165 return _y_size; 00166 }