1 // jpgfactory.cxx -- jpeg frontend for TR library
3 // Written by Norman Vine, started August 2001.
5 // Copyright (C) 2001 Norman Vine - nhv@yahoo.com
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 # include <simgear_config.h>
32 #include "jpgfactory.hxx"
39 static void init_destination (j_compress_ptr cinfo);
40 static void term_destination (j_compress_ptr cinfo);
41 static boolean empty_output_buffer (j_compress_ptr cinfo);
47 // OSGFIME: offscreenrendering on osg - completely new context ...
50 struct jpeg_destination_mgr pub; /* public fields */
51 unsigned char * outfile; /* target stream */
52 JOCTET * buffer; /* start of buffer */
53 int numbytes; /* num bytes used */
54 int maxsize; /* size of outfile */
55 int error; /* error flag */
58 typedef my_destination_mgr * my_dest_ptr;
60 void (*jpgRenderFrame)(void) = NULL;
62 trJpgFactory::trJpgFactory() {
63 imageWidth = imageHeight = 0;
71 trJpgFactory::~trJpgFactory() {
76 * deallocate our dynamic parts
79 void trJpgFactory::destroy( int error )
82 printf( "!! Malloc Failure trJpgFactory ( %d )!!\n",
85 if( cinfo.dest ) jpeg_destroy_compress(&cinfo);
86 if( tr ) trDelete(tr);
87 if( IMAGE ) delete [] IMAGE;
88 if( buffer ) delete [] buffer;
89 if( tile ) delete [] tile;
93 * allocate and initialize the jpeg compress struct
94 * application needs to dealocate this
97 int trJpgFactory::jpeg_init()
99 j_compress_ptr cinfoPtr = &cinfo;
101 cinfoPtr->err = jpeg_std_error(&jerr);
102 jpeg_create_compress(cinfoPtr);
104 /* following taken from jpeg library exaample code */
105 cinfoPtr->dest = (struct jpeg_destination_mgr *)
106 (*cinfoPtr->mem->alloc_small)
107 ((j_common_ptr)cinfoPtr,
109 sizeof(my_destination_mgr));
111 my_dest_ptr dest = (my_dest_ptr)cinfoPtr->dest;
118 dest->pub.init_destination = init_destination;
119 dest->pub.empty_output_buffer = empty_output_buffer;
120 dest->pub.term_destination = term_destination;
121 dest->outfile = NULL;
125 cinfoPtr->image_width = imageWidth;
126 cinfoPtr->image_height = imageHeight;
127 cinfoPtr->input_components = 3;
128 cinfoPtr->in_color_space = JCS_RGB;
129 jpeg_set_defaults(cinfoPtr);
130 jpeg_set_quality(cinfoPtr, (100 * 90) >> 8, TRUE);
137 * may also be used as reinit() to change image size
140 int trJpgFactory::init(int width, int height )
144 if( width <= 0 || height <= 0 ) {
145 imageWidth = DEFAULT_XS;
146 imageHeight = DEFAULT_YS;
149 imageHeight = height;
152 int bufsize = imageWidth * imageHeight * 3 * sizeof(GLubyte);
154 /* allocate buffer large enough to store one tile */
155 tile = new GLubyte[bufsize];
161 /* allocate buffer to hold a row of tiles */
162 buffer = new GLubyte[ bufsize ];
168 /* this should be big enough */
169 IMAGESIZE = bufsize + 1024;
170 IMAGE = new unsigned char[ IMAGESIZE ];
182 trRowOrder(tr, TR_TOP_TO_BOTTOM);
183 trTileSize(tr, imageWidth, imageHeight, 0);
184 trImageSize(tr, imageWidth, imageHeight);
185 trTileBuffer(tr, GL_RGB, GL_UNSIGNED_BYTE, tile);
194 int trJpgFactory::compress()
196 JSAMPROW row_pointer[1];
199 /* to keep track of jpeg library routines */
200 my_dest_ptr dest = (my_dest_ptr) cinfo.dest;
202 //printf("\tjpeg_start_compress(&cinfo, TRUE)\n");
203 jpeg_start_compress(&cinfo, TRUE);
205 dest->outfile = IMAGE;
206 dest->maxsize = IMAGESIZE;
207 row_stride = cinfo.image_width * 3;
209 while( cinfo.next_scanline < cinfo.image_height &&
212 row_pointer[0] = buffer + (cinfo.next_scanline * row_stride);
213 jpeg_write_scanlines(&cinfo, row_pointer, 1);
217 // printf("\n\tBEFORE: jpeg_finish_compress(&cinfo)\n");
218 jpeg_finish_compress(&cinfo);
219 // printf("\tAFTER: jpeg_finish_compress(&cinfo)\n");
221 printf("INTERNAL JPEG_FACTORY ERROR\n");
222 jpeg_abort_compress(&cinfo);
223 /* OK - I am paranoid */
226 return dest->numbytes;
230 * Makes the image then calls compress()
233 int trJpgFactory::render()
235 if( !tr || !jpgRenderFrame ) {
236 printf("!! NO tr !!\n trJpgFactory::render()\n");
240 // Make sure we have SSG projection primed for current view
241 glMatrixMode(GL_MODELVIEW);
244 /* just to be safe... */
245 glPixelStorei(GL_PACK_ALIGNMENT, 1);
247 // printf("\ttrBeginTile(tr)\n");
252 /* just to be safe */
253 int curTileHeight = trGet(tr, TR_CURRENT_TILE_HEIGHT);
254 int curTileWidth = trGet(tr, TR_CURRENT_TILE_WIDTH);
256 /* reverse image top to bottom */
257 int bytesPerImageRow = imageWidth * 3*sizeof(GLubyte);
258 int bytesPerTileRow = imageWidth * 3*sizeof(GLubyte);
259 int bytesPerCurrentTileRow = (curTileWidth) * 3*sizeof(GLubyte);
261 for (i=0;i<imageHeight;i++) {
262 memcpy(buffer + (curTileHeight-1-i) * bytesPerImageRow, /* Dest */
263 tile + i*bytesPerTileRow, /* Src */
264 bytesPerCurrentTileRow); /* Byte count*/
267 // printf("exit trJpgFactory::render()\n");
272 #define OUTPUT_BUF_SIZE 4096
279 * Initialize destination --- called by jpeg_start_compress
280 * before any data is actually written.
283 static void init_destination (j_compress_ptr cinfo)
285 // printf("enter init_destination()\n");
286 my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
288 /* following taken from jpeg library exaample code
289 * Allocate the output buffer ---
290 * it automaically will be released when done with image */
292 dest->buffer = (JOCTET *)(*cinfo->mem->alloc_small)
293 ((j_common_ptr)cinfo, JPOOL_IMAGE,
294 OUTPUT_BUF_SIZE * sizeof(JOCTET) );
296 if( !dest->buffer ) {
297 printf("MALLOC FAILED jpegFactory init_destination()\n");
302 dest->pub.next_output_byte = dest->buffer;
303 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
308 * Empty the output buffer --- called whenever buffer fills up.
311 static boolean empty_output_buffer (j_compress_ptr cinfo)
313 // printf("enter empty_output_buffer(%d)\n", OUTPUT_BUF_SIZE);
314 my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
316 if( (!dest->error) &&
317 ((dest->numbytes + OUTPUT_BUF_SIZE) < dest->maxsize) )
319 memcpy( dest->outfile+dest->numbytes, dest->buffer, (size_t)OUTPUT_BUF_SIZE);
321 dest->pub.next_output_byte = dest->buffer;
322 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
324 dest->numbytes += OUTPUT_BUF_SIZE;
326 printf("BUFFER OVERFLOW jpegFactory empty_output_buffer()\n");
334 * Terminate destination --- called by jpeg_finish_compress
335 * after all data has been written. Usually needs to flush buffer.
337 * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
338 * application must deal with any cleanup that should happen even
342 static void term_destination (j_compress_ptr cinfo)
344 my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
346 size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
348 if( (!dest->error) &&
349 ((dest->numbytes + datacount) < (unsigned int)dest->maxsize) )
351 memcpy( dest->outfile+dest->numbytes, dest->buffer, datacount);
352 dest->numbytes += datacount;
354 printf("BUFFER OVERFLOW jpegFactory term_destination()\n");
358 // printf(" term_destination(%d) total %d\n", datacount, dest->numbytes );