head 1.4; access; symbols; locks; strict; comment @# @; 1.4 date 2002.09.07.01.50.38; author curt; state Exp; branches; next 1.3; 1.3 date 2002.08.31.19.01.54; author curt; state Exp; branches; next 1.2; 1.2 date 2002.08.31.18.54.00; author curt; state Exp; branches; next 1.1; 1.1 date 2002.02.15.17.21.56; author curt; state Exp; branches; next ; desc @@ 1.4 log @Updated doxygen docs. @ text @
Main Page Class Hierarchy Compound List File List Compound Members File Members

# jpgfactory.cxx

    00001 // jpgfactory.cxx -- jpeg frontend for TR library
    00002 //
    00003 // Written by Norman Vine, started August 2001.
    00004 //
    00005 // Copyright (C) 2001  Norman Vine - nhv@@yahoo.com
    00006 //
    00007 // This program is free software; you can redistribute it and/or
    00008 // modify it under the terms of the GNU General Public License as
    00009 // published by the Free Software Foundation; either version 2 of the
    00010 // License, or (at your option) any later version.
    00011 //
    00012 // This program is distributed in the hope that it will be useful, but
    00013 // WITHOUT ANY WARRANTY; without even the implied warranty of
    00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00015 // General Public License for more details.
    00016 //
    00017 // You should have received a copy of the GNU General Public License
    00018 // along with this program; if not, write to the Free Software
    00019 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    00020 //
    00021 // $Id:
    00022
    00023
    00024 #ifdef HAVE_WINDOWS_H
    00025 #  include <windows.h>
    00026 #endif
    00027
    00028 #include <stdlib.h>
    00029 #include <stdio.h>
    00030
    00031 #include <plib/ssg.h>
    00032
    00033 #include "jpgfactory.hxx"
    00034
    00035
    00036 #ifdef __cplusplus
    00037 extern "C" {
    00038 #endif
    00039
    00040 static void init_destination (j_compress_ptr cinfo);
    00041 static void term_destination (j_compress_ptr cinfo);
    00042 static boolean empty_output_buffer (j_compress_ptr cinfo);
    00043
    00044 #ifdef __cplusplus
    00045 }
    00046 #endif
    00047
    00048
    00049 typedef struct {
    00050     struct jpeg_destination_mgr pub; /* public fields */
    00051     unsigned char * outfile; /* target stream */
    00052     JOCTET * buffer;         /* start of buffer */
    00053     int numbytes;            /* num bytes used */
    00054     int maxsize;             /* size of outfile */
    00055     int error;               /* error flag */
    00056 } my_destination_mgr;
    00057
    00058 typedef my_destination_mgr * my_dest_ptr;
    00059
    00060 /* Where should this go <simgear/screen/tr.h> ?? */
    00061 extern void trRenderFrame( void );
    00062
    00063 trJpgFactory::trJpgFactory() {
    00064     imageWidth = imageHeight = 0;
    00065     tile       = NULL;
    00066     buffer     = NULL;
    00067     IMAGE      = NULL;
    00068     tr         = NULL;
    00069     cinfo.dest = NULL;
    00070 }
    00071
    00072 trJpgFactory::~trJpgFactory() {
    00073     destroy();
    00074 }
    00075
    00076 /*
    00077  * deallocate our dynamic parts
    00078  */
    00079
    00080 void trJpgFactory::destroy( int error )
    00081 {
    00082     if( error )
    00083         printf( "!! Malloc Failure trJpgFactory ( %d )!!\n",
    00084                 error );
    00085
    00086     if( cinfo.dest )  jpeg_destroy_compress(&cinfo);
    00087     if( tr )          trDelete(tr);
    00088     if( IMAGE )       delete [] IMAGE;
    00089     if( buffer )      delete [] buffer;
    00090     if( tile )        delete [] tile;
    00091 }
    00092
    00093 /*
    00094  * allocate and initialize the jpeg compress struct
    00095  * application needs to dealocate this
    00096  */
    00097
    00098 int trJpgFactory::jpeg_init()
    00099 {
    00100     j_compress_ptr cinfoPtr = &cinfo;
    00101
    00102     cinfoPtr->err = jpeg_std_error(&jerr);
    00103     jpeg_create_compress(cinfoPtr);
    00104
    00105     /* following taken from jpeg library exaample code */
    00106     cinfoPtr->dest = (struct jpeg_destination_mgr *)
    00107                      (*cinfoPtr->mem->alloc_small)
    00108                      ((j_common_ptr)cinfoPtr,
    00109                       JPOOL_PERMANENT,
    00110                       sizeof(my_destination_mgr));
    00111
    00112     my_dest_ptr dest = (my_dest_ptr)cinfoPtr->dest;
    00113
    00114     if( !dest ) {
    00115         destroy(5);
    00116         return 5;
    00117     }
    00118
    00119     dest->pub.init_destination    = init_destination;
    00120     dest->pub.empty_output_buffer = empty_output_buffer;
    00121     dest->pub.term_destination    = term_destination;
    00122     dest->outfile  = NULL;
    00123     dest->numbytes = 0;
    00124     dest->maxsize  = 0;
    00125
    00126     cinfoPtr->image_width      = imageWidth;
    00127     cinfoPtr->image_height     = imageHeight;
    00128     cinfoPtr->input_components = 3;
    00129     cinfoPtr->in_color_space   = JCS_RGB;
    00130     jpeg_set_defaults(cinfoPtr);
    00131     jpeg_set_quality(cinfoPtr, (100 * 90) >> 8, TRUE);
    00132
    00133     return 0;
    00134 }
    00135
    00136
    00137 /*
    00138  * may also be used as reinit() to change image size
    00139  */
    00140
    00141 int trJpgFactory::init(int width, int height )
    00142 {
    00143     destroy();
    00144
    00145     if( width <= 0 || height <= 0 ) {
    00146         imageWidth  = DEFAULT_XS;
    00147         imageHeight = DEFAULT_YS;
    00148     } else {
    00149         imageWidth  = width;
    00150         imageHeight = height;
    00151     }
    00152
    00153     int bufsize = imageWidth * imageHeight * 3 * sizeof(GLubyte);
    00154
    00155     /* allocate buffer large enough to store one tile */
    00156     tile = new GLubyte[bufsize];
    00157     if (!tile) {
    00158         destroy(1);
    00159         return 1;
    00160     }
    00161
    00162     /* allocate buffer to hold a row of tiles */
    00163     buffer = new GLubyte[ bufsize ];
    00164     if (!buffer) {
    00165         destroy(2);
    00166         return 2;
    00167     }
    00168
    00169     /* this should be big enough */
    00170     IMAGESIZE = bufsize + 1024;
    00171     IMAGE = new unsigned char[ IMAGESIZE ];
    00172     if( !IMAGE ) {
    00173         destroy(3);
    00174         return 3;
    00175     }
    00176
    00177     tr = trNew();
    00178     if( !tr ) {
    00179         destroy(4);
    00180         return 4;
    00181     }
    00182
    00183     trRowOrder(tr, TR_TOP_TO_BOTTOM);
    00184     trTileSize(tr, imageWidth, imageHeight, 0);
    00185     trImageSize(tr, imageWidth, imageHeight);
    00186     trTileBuffer(tr, GL_RGB, GL_UNSIGNED_BYTE, tile);
    00187
    00188     return jpeg_init();
    00189 }
    00190
    00191 /*
    00192  *compress the image
    00193  */
    00194
    00195 int trJpgFactory::compress()
    00196 {
    00197     JSAMPROW  row_pointer[1];
    00198     int       row_stride;
    00199
    00200     /* to keep track of jpeg library routines */
    00201     my_dest_ptr dest = (my_dest_ptr) cinfo.dest;
    00202
    00203     //printf("\tjpeg_start_compress(&cinfo, TRUE)\n");
    00204     jpeg_start_compress(&cinfo, TRUE);
    00205     if( !dest->error ) {
    00206         dest->outfile = IMAGE;
    00207         dest->maxsize = IMAGESIZE;
    00208         row_stride    = cinfo.image_width * 3;
    00209
    00210         while( cinfo.next_scanline < cinfo.image_height &&
    00211                !dest->error )
    00212         {
    00213             row_pointer[0] = buffer + (cinfo.next_scanline * row_stride);
    00214             jpeg_write_scanlines(&cinfo, row_pointer, 1);
    00215         }
    00216     }
    00217     if( !dest->error ) {
    00218         // printf("\n\tBEFORE: jpeg_finish_compress(&cinfo)\n");
    00219         jpeg_finish_compress(&cinfo);
    00220         // printf("\tAFTER: jpeg_finish_compress(&cinfo)\n");
    00221     } else {
    00222         printf("INTERNAL JPEG_FACTORY ERROR\n");
    00223         jpeg_abort_compress(&cinfo);
    00224         /* OK - I am paranoid */
    00225         dest->numbytes = 0;
    00226     }
    00227     return dest->numbytes;
    00228 }
    00229
    00230 /*
    00231  * Makes the image then calls compress()
    00232  */
    00233
    00234 int trJpgFactory::render()
    00235 {
    00236     if( !tr ) {
    00237         printf("!! NO tr !!\n   trJpgFactory::render()\n");
    00238         return 0;
    00239     }
    00240
    00241     // Make sure we have SSG projection primed for current view
    00242     glMatrixMode(GL_MODELVIEW);
    00243     glLoadIdentity();
    00244
    00245     sgFrustum *frustum = ssgGetFrustum();
    00246     trFrustum(tr,
    00247               frustum->getLeft(), frustum->getRight(),
    00248               frustum->getBot(),  frustum->getTop(),
    00249               frustum->getNear(), frustum->getFar());
    00250
    00251     /* just to be safe... */
    00252     glPixelStorei(GL_PACK_ALIGNMENT, 1);
    00253
    00254     // printf("\ttrBeginTile(tr)\n");
    00255     trBeginTile(tr);
    00256     trRenderFrame();
    00257     trEndTile(tr);
    00258
    00259     /* just to be safe */
    00260     int curTileHeight = trGet(tr, TR_CURRENT_TILE_HEIGHT);
    00261     int curTileWidth  = trGet(tr, TR_CURRENT_TILE_WIDTH);
    00262
    00263     /* reverse image top to bottom */
    00264     int bytesPerImageRow = imageWidth * 3*sizeof(GLubyte);
    00265     int bytesPerTileRow  = imageWidth * 3*sizeof(GLubyte);
    00266     int bytesPerCurrentTileRow = (curTileWidth) * 3*sizeof(GLubyte);
    00267     int i;
    00268     for (i=0;i<imageHeight;i++) {
    00269         memcpy(buffer + (curTileHeight-1-i) * bytesPerImageRow, /* Dest */
    00270                tile + i*bytesPerTileRow,              /* Src */
    00271                bytesPerCurrentTileRow);               /* Byte count*/
    00272     }
    00273
    00274     //  printf("exit trJpgFactory::render()\n");
    00275     return  compress();
    00276 }
    00277
    00278
    00279 #define OUTPUT_BUF_SIZE  4096
    00280
    00281 #ifdef __cplusplus
    00282 extern "C" {
    00283 #endif
    00284
    00285 /*
    00286  * Initialize destination --- called by jpeg_start_compress
    00287  * before any data is actually written.
    00288  */
    00289
    00290 static void init_destination (j_compress_ptr cinfo)
    00291 {
    00292     // printf("enter init_destination()\n");
    00293     my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
    00294
    00295     /* following taken from jpeg library exaample code
    00296      * Allocate the output buffer ---
    00297      * it automaically will be released when done with image */
    00298
    00299     dest->buffer = (JOCTET *)(*cinfo->mem->alloc_small)
    00300                    ((j_common_ptr)cinfo, JPOOL_IMAGE,
    00301                     OUTPUT_BUF_SIZE * sizeof(JOCTET) );
    00302
    00303     if( !dest->buffer ) {
    00304         printf("MALLOC FAILED jpegFactory init_destination()\n");
    00305         dest->error = TRUE;
    00306     } else {
    00307         dest->error = FALSE;
    00308     }
    00309     dest->pub.next_output_byte = dest->buffer;
    00310     dest->pub.free_in_buffer   = OUTPUT_BUF_SIZE;
    00311     dest->numbytes = 0;
    00312 }
    00313
    00314 /*
    00315  * Empty the output buffer --- called whenever buffer fills up.
    00316  */
    00317
    00318 static boolean empty_output_buffer (j_compress_ptr cinfo)
    00319 {
    00320     // printf("enter empty_output_buffer(%d)\n", OUTPUT_BUF_SIZE);
    00321     my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
    00322
    00323     if( (!dest->error) &&
    00324           ((dest->numbytes + OUTPUT_BUF_SIZE) < dest->maxsize) )
    00325     {
    00326         memcpy( dest->outfile+dest->numbytes, dest->buffer, (size_t)OUTPUT_BUF_SIZE);
    00327
    00328         dest->pub.next_output_byte = dest->buffer;
    00329         dest->pub.free_in_buffer   = OUTPUT_BUF_SIZE;
    00330
    00331         dest->numbytes += OUTPUT_BUF_SIZE;
    00332     } else {
    00333         printf("BUFFER OVERFLOW jpegFactory empty_output_buffer()\n");
    00334         dest->numbytes = 0;
    00335         dest->error    = TRUE;
    00336     }
    00337     return TRUE;
    00338 }
    00339
    00340 /*
    00341  * Terminate destination --- called by jpeg_finish_compress
    00342  * after all data has been written.  Usually needs to flush buffer.
    00343  *
    00344  * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
    00345  * application must deal with any cleanup that should happen even
    00346  * for error exit.
    00347  */
    00348
    00349 static void term_destination (j_compress_ptr cinfo)
    00350 {
    00351     my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
    00352
    00353     size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
    00354
    00355     if( (!dest->error) &&
    00356           ((dest->numbytes + datacount) < (unsigned int)dest->maxsize) )
    00357     {
    00358         memcpy( dest->outfile+dest->numbytes, dest->buffer, datacount);
    00359         dest->numbytes += datacount;
    00360     } else {
    00361         printf("BUFFER OVERFLOW jpegFactory term_destination()\n");
    00362         dest->numbytes = 0;
    00363         dest->error = TRUE;
    00364     }
    00365     // printf(" term_destination(%d) total %d\n", datacount, dest->numbytes );
    00366 }
    00367
    00368 #ifdef __cplusplus
    00369 }
    00370 #endif
    00371

@ 1.3 log @Oops, try again. @ text @d380 1 a380 1