00001 // Filename: pnmFileTypeJPGWriter.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 #include "pnmImage.h" 00023 #include "pnmWriter.h" 00024 00025 extern "C" { 00026 #include <jpeglib.h> 00027 } 00028 00029 //////////////////////////////////////////////////////////////////// 00030 // Function: PNMFileTypeJPG2000::Writer::Constructor 00031 // Access: Public 00032 // Description: 00033 //////////////////////////////////////////////////////////////////// 00034 PNMFileTypeJPG2000::Writer:: 00035 Writer(PNMFileType *type, ostream *file, bool owns_file) : 00036 PNMWriter(type, file, owns_file) 00037 { 00038 } 00039 00040 00041 //////////////////////////////////////////////////////////////////// 00042 // Function: PNMFileTypeJPG2000::Writer::write_data 00043 // Access: Public, Virtual 00044 // Description: Writes out an entire image all at once, including the 00045 // header, based on the image data stored in the given 00046 // _x_size * _y_size array and alpha pointers. (If the 00047 // image type has no alpha channel, alpha is ignored.) 00048 // Returns the number of rows correctly written. 00049 // 00050 // It is the user's responsibility to fill in the header 00051 // data via calls to set_x_size(), set_num_channels(), 00052 // etc., or copy_header_from(), before calling 00053 // write_data(). 00054 // 00055 // It is important to delete the PNMWriter class after 00056 // successfully writing the data. Failing to do this 00057 // may result in some data not getting flushed! 00058 // 00059 // Derived classes need not override this if they 00060 // instead provide supports_streaming() and write_row(), 00061 // below. 00062 //////////////////////////////////////////////////////////////////// 00063 int PNMFileTypeJPG2000::Writer:: 00064 write_data(xel *array, xelval *) { 00065 if (_y_size<=0 || _x_size<=0) { 00066 return 0; 00067 } 00068 00069 /* This struct contains the JPEG compression parameters and pointers to 00070 * working space (which is allocated as needed by the JPEG library). 00071 * It is possible to have several such structures, representing multiple 00072 * compression/decompression processes, in existence at once. We refer 00073 * to any one struct (and its associated working data) as a "JPEG object". 00074 */ 00075 struct jpeg_compress_struct cinfo; 00076 /* This struct represents a JPEG error handler. It is declared separately 00077 * because applications often want to supply a specialized error handler 00078 * (see the second half of this file for an example). But here we just 00079 * take the easy way out and use the standard error handler, which will 00080 * print a message on stderr and call exit() if compression fails. 00081 * Note that this struct must live as long as the main JPEG parameter 00082 * struct, to avoid dangling-pointer problems. 00083 */ 00084 struct jpeg_error_mgr jerr; 00085 /* More stuff */ 00086 JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ 00087 int row_stride; /* physical row width in image buffer */ 00088 00089 /* Step 1: allocate and initialize JPEG compression object */ 00090 00091 /* We have to set up the error handler first, in case the initialization 00092 * step fails. (Unlikely, but it could happen if you are out of memory.) 00093 * This routine fills in the contents of struct jerr, and returns jerr's 00094 * address which we place into the link field in cinfo. 00095 */ 00096 cinfo.err = jpeg_std_error(&jerr); 00097 00098 /* Now we can initialize the JPEG compression object. */ 00099 jpeg_create_compress(&cinfo); 00100 00101 /* Step 2: specify data destination (eg, a file) */ 00102 /* Note: steps 2 and 3 can be done in either order. */ 00103 00104 /* Here we use the library-supplied code to send compressed data to a 00105 * stdio stream. You can also write your own code to do something else. 00106 * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that 00107 * requires it in order to write binary files. 00108 */ 00109 // This is broken, and won't compile. We need to drop in an 00110 // iostream replacement, like we did for JPG. 00111 jpeg_stdio_dest(&cinfo, _file); 00112 00113 /* Step 3: set parameters for compression */ 00114 00115 /* First we supply a description of the input image. 00116 * Four fields of the cinfo struct must be filled in: 00117 */ 00118 cinfo.image_width = _x_size; /* image width and height, in pixels */ 00119 cinfo.image_height = _y_size; 00120 if (is_grayscale()) { 00121 cinfo.input_components = 1; 00122 cinfo.in_color_space = JCS_GRAYSCALE; 00123 } else { 00124 cinfo.input_components = 3; 00125 cinfo.in_color_space = JCS_RGB; 00126 } 00127 /* Now use the library's routine to set default compression parameters. 00128 * (You must set at least cinfo.in_color_space before calling this, 00129 * since the defaults depend on the source color space.) 00130 */ 00131 jpeg_set_defaults(&cinfo); 00132 /* Now you can set any non-default parameters you wish to. 00133 * Here we just illustrate the use of quality (quantization table) scaling: 00134 */ 00135 jpeg_set_quality(&cinfo, jpeg_quality, TRUE /* limit to baseline-JPEG values */); 00136 00137 /* Step 4: Start compressor */ 00138 00139 /* TRUE ensures that we will write a complete interchange-JPEG file. 00140 * Pass TRUE unless you are very sure of what you're doing. 00141 */ 00142 jpeg_start_compress(&cinfo, TRUE); 00143 00144 /* Step 5: while (scan lines remain to be written) */ 00145 /* jpeg_write_scanlines(...); */ 00146 00147 /* Here we use the library's state variable cinfo.next_scanline as the 00148 * loop counter, so that we don't have to keep track ourselves. 00149 * To keep things simple, we pass one scanline per call; you can pass 00150 * more if you wish, though. 00151 */ 00152 row_stride = _x_size * cinfo.input_components; /* JSAMPLEs per row in image_buffer */ 00153 00154 int x = 0; 00155 JSAMPROW row = new JSAMPLE[row_stride]; 00156 while (cinfo.next_scanline < cinfo.image_height) { 00157 /* jpeg_write_scanlines expects an array of pointers to scanlines. 00158 * Here the array is only one element long, but you could pass 00159 * more than one scanline at a time if that's more convenient. 00160 */ 00161 for (int i = 0; i < row_stride; i += cinfo.input_components) { 00162 if (cinfo.input_components == 1) { 00163 row[i] = (JSAMPLE)(MAXJSAMPLE * PPM_GETB(array[x])/_maxval); 00164 } else { 00165 row[i] = (JSAMPLE)(MAXJSAMPLE * PPM_GETR(array[x])/_maxval); 00166 row[i+1] = (JSAMPLE)(MAXJSAMPLE * PPM_GETG(array[x])/_maxval); 00167 row[i+2] = (JSAMPLE)(MAXJSAMPLE * PPM_GETB(array[x])/_maxval); 00168 } 00169 x++; 00170 } 00171 //row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride]; 00172 //(void) jpeg_write_scanlines(&cinfo, row_pointer, 1); 00173 row_pointer[0] = row; 00174 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); 00175 } 00176 delete row; 00177 00178 /* Step 6: Finish compression */ 00179 00180 jpeg_finish_compress(&cinfo); 00181 00182 /* Step 7: release JPEG compression object */ 00183 00184 /* This is an important step since it will release a good deal of memory. */ 00185 jpeg_destroy_compress(&cinfo); 00186 00187 return _y_size; 00188 }