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