00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_WINDOWS_H
00025 # include <windows.h>
00026 #endif
00027
00028 #include <plib/ssg.h>
00029
00030 #include "jpgfactory.hxx"
00031
00032
00033 #ifdef __cplusplus
00034 extern "C" {
00035 #endif
00036
00037 static void init_destination (j_compress_ptr cinfo);
00038 static void term_destination (j_compress_ptr cinfo);
00039 static boolean empty_output_buffer (j_compress_ptr cinfo);
00040
00041 #ifdef __cplusplus
00042 }
00043 #endif
00044
00045
00046 typedef struct {
00047 struct jpeg_destination_mgr pub;
00048 unsigned char * outfile;
00049 JOCTET * buffer;
00050 int numbytes;
00051 int maxsize;
00052 int error;
00053 } my_destination_mgr;
00054
00055 typedef my_destination_mgr * my_dest_ptr;
00056
00057 void (*jpgRenderFrame)(void) = NULL;
00058
00059 trJpgFactory::trJpgFactory() {
00060 imageWidth = imageHeight = 0;
00061 tile = NULL;
00062 buffer = NULL;
00063 IMAGE = NULL;
00064 tr = NULL;
00065 cinfo.dest = NULL;
00066 }
00067
00068 trJpgFactory::~trJpgFactory() {
00069 destroy();
00070 }
00071
00072
00073
00074
00075
00076 void trJpgFactory::destroy( int error )
00077 {
00078 if( error )
00079 printf( "!! Malloc Failure trJpgFactory ( %d )!!\n",
00080 error );
00081
00082 if( cinfo.dest ) jpeg_destroy_compress(&cinfo);
00083 if( tr ) trDelete(tr);
00084 if( IMAGE ) delete [] IMAGE;
00085 if( buffer ) delete [] buffer;
00086 if( tile ) delete [] tile;
00087 }
00088
00089
00090
00091
00092
00093
00094 int trJpgFactory::jpeg_init()
00095 {
00096 j_compress_ptr cinfoPtr = &cinfo;
00097
00098 cinfoPtr->err = jpeg_std_error(&jerr);
00099 jpeg_create_compress(cinfoPtr);
00100
00101
00102 cinfoPtr->dest = (struct jpeg_destination_mgr *)
00103 (*cinfoPtr->mem->alloc_small)
00104 ((j_common_ptr)cinfoPtr,
00105 JPOOL_PERMANENT,
00106 sizeof(my_destination_mgr));
00107
00108 my_dest_ptr dest = (my_dest_ptr)cinfoPtr->dest;
00109
00110 if( !dest ) {
00111 destroy(5);
00112 return 5;
00113 }
00114
00115 dest->pub.init_destination = init_destination;
00116 dest->pub.empty_output_buffer = empty_output_buffer;
00117 dest->pub.term_destination = term_destination;
00118 dest->outfile = NULL;
00119 dest->numbytes = 0;
00120 dest->maxsize = 0;
00121
00122 cinfoPtr->image_width = imageWidth;
00123 cinfoPtr->image_height = imageHeight;
00124 cinfoPtr->input_components = 3;
00125 cinfoPtr->in_color_space = JCS_RGB;
00126 jpeg_set_defaults(cinfoPtr);
00127 jpeg_set_quality(cinfoPtr, (100 * 90) >> 8, TRUE);
00128
00129 return 0;
00130 }
00131
00132
00133
00134
00135
00136
00137 int trJpgFactory::init(int width, int height )
00138 {
00139 destroy();
00140
00141 if( width <= 0 || height <= 0 ) {
00142 imageWidth = DEFAULT_XS;
00143 imageHeight = DEFAULT_YS;
00144 } else {
00145 imageWidth = width;
00146 imageHeight = height;
00147 }
00148
00149 int bufsize = imageWidth * imageHeight * 3 * sizeof(GLubyte);
00150
00151
00152 tile = new GLubyte[bufsize];
00153 if (!tile) {
00154 destroy(1);
00155 return 1;
00156 }
00157
00158
00159 buffer = new GLubyte[ bufsize ];
00160 if (!buffer) {
00161 destroy(2);
00162 return 2;
00163 }
00164
00165
00166 IMAGESIZE = bufsize + 1024;
00167 IMAGE = new unsigned char[ IMAGESIZE ];
00168 if( !IMAGE ) {
00169 destroy(3);
00170 return 3;
00171 }
00172
00173 tr = trNew();
00174 if( !tr ) {
00175 destroy(4);
00176 return 4;
00177 }
00178
00179 trRowOrder(tr, TR_TOP_TO_BOTTOM);
00180 trTileSize(tr, imageWidth, imageHeight, 0);
00181 trImageSize(tr, imageWidth, imageHeight);
00182 trTileBuffer(tr, GL_RGB, GL_UNSIGNED_BYTE, tile);
00183
00184 return jpeg_init();
00185 }
00186
00187
00188
00189
00190
00191 int trJpgFactory::compress()
00192 {
00193 JSAMPROW row_pointer[1];
00194 int row_stride;
00195
00196
00197 my_dest_ptr dest = (my_dest_ptr) cinfo.dest;
00198
00199
00200 jpeg_start_compress(&cinfo, TRUE);
00201 if( !dest->error ) {
00202 dest->outfile = IMAGE;
00203 dest->maxsize = IMAGESIZE;
00204 row_stride = cinfo.image_width * 3;
00205
00206 while( cinfo.next_scanline < cinfo.image_height &&
00207 !dest->error )
00208 {
00209 row_pointer[0] = buffer + (cinfo.next_scanline * row_stride);
00210 jpeg_write_scanlines(&cinfo, row_pointer, 1);
00211 }
00212 }
00213 if( !dest->error ) {
00214
00215 jpeg_finish_compress(&cinfo);
00216
00217 } else {
00218 printf("INTERNAL JPEG_FACTORY ERROR\n");
00219 jpeg_abort_compress(&cinfo);
00220
00221 dest->numbytes = 0;
00222 }
00223 return dest->numbytes;
00224 }
00225
00226
00227
00228
00229
00230 int trJpgFactory::render()
00231 {
00232 if( !tr || !jpgRenderFrame ) {
00233 printf("!! NO tr !!\n trJpgFactory::render()\n");
00234 return 0;
00235 }
00236
00237
00238 glMatrixMode(GL_MODELVIEW);
00239 glLoadIdentity();
00240
00241 sgFrustum *frustum = ssgGetFrustum();
00242 trFrustum(tr,
00243 frustum->getLeft(), frustum->getRight(),
00244 frustum->getBot(), frustum->getTop(),
00245 frustum->getNear(), frustum->getFar());
00246
00247
00248 glPixelStorei(GL_PACK_ALIGNMENT, 1);
00249
00250
00251 trBeginTile(tr);
00252 jpgRenderFrame();
00253 trEndTile(tr);
00254
00255
00256 int curTileHeight = trGet(tr, TR_CURRENT_TILE_HEIGHT);
00257 int curTileWidth = trGet(tr, TR_CURRENT_TILE_WIDTH);
00258
00259
00260 int bytesPerImageRow = imageWidth * 3*sizeof(GLubyte);
00261 int bytesPerTileRow = imageWidth * 3*sizeof(GLubyte);
00262 int bytesPerCurrentTileRow = (curTileWidth) * 3*sizeof(GLubyte);
00263 int i;
00264 for (i=0;i<imageHeight;i++) {
00265 memcpy(buffer + (curTileHeight-1-i) * bytesPerImageRow,
00266 tile + i*bytesPerTileRow,
00267 bytesPerCurrentTileRow);
00268 }
00269
00270
00271 return compress();
00272 }
00273
00274
00275 #define OUTPUT_BUF_SIZE 4096
00276
00277 #ifdef __cplusplus
00278 extern "C" {
00279 #endif
00280
00281
00282
00283
00284
00285
00286 static void init_destination (j_compress_ptr cinfo)
00287 {
00288
00289 my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
00290
00291
00292
00293
00294
00295 dest->buffer = (JOCTET *)(*cinfo->mem->alloc_small)
00296 ((j_common_ptr)cinfo, JPOOL_IMAGE,
00297 OUTPUT_BUF_SIZE * sizeof(JOCTET) );
00298
00299 if( !dest->buffer ) {
00300 printf("MALLOC FAILED jpegFactory init_destination()\n");
00301 dest->error = TRUE;
00302 } else {
00303 dest->error = FALSE;
00304 }
00305 dest->pub.next_output_byte = dest->buffer;
00306 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
00307 dest->numbytes = 0;
00308 }
00309
00310
00311
00312
00313
00314 static boolean empty_output_buffer (j_compress_ptr cinfo)
00315 {
00316
00317 my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
00318
00319 if( (!dest->error) &&
00320 ((dest->numbytes + OUTPUT_BUF_SIZE) < dest->maxsize) )
00321 {
00322 memcpy( dest->outfile+dest->numbytes, dest->buffer, (size_t)OUTPUT_BUF_SIZE);
00323
00324 dest->pub.next_output_byte = dest->buffer;
00325 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
00326
00327 dest->numbytes += OUTPUT_BUF_SIZE;
00328 } else {
00329 printf("BUFFER OVERFLOW jpegFactory empty_output_buffer()\n");
00330 dest->numbytes = 0;
00331 dest->error = TRUE;
00332 }
00333 return TRUE;
00334 }
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345 static void term_destination (j_compress_ptr cinfo)
00346 {
00347 my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
00348
00349 size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
00350
00351 if( (!dest->error) &&
00352 ((dest->numbytes + datacount) < (unsigned int)dest->maxsize) )
00353 {
00354 memcpy( dest->outfile+dest->numbytes, dest->buffer, datacount);
00355 dest->numbytes += datacount;
00356 } else {
00357 printf("BUFFER OVERFLOW jpegFactory term_destination()\n");
00358 dest->numbytes = 0;
00359 dest->error = TRUE;
00360 }
00361
00362 }
00363
00364 #ifdef __cplusplus
00365 }
00366 #endif
00367