2 Copyright 2004-2005 Chris Tallon
4 This file is part of VOMP.
6 VOMP is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 VOMP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with VOMP; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
30 jpeg_memio_src (j_decompress_ptr cinfo, void * userdata);
32 jpeg_memio_cleanup (j_decompress_ptr cinfo);
36 ULONG WindowsResourceJpegReader::initRead(const char *filename)
38 HRSRC res=FindResource(NULL,filename,RT_RCDATA);
39 hres=LoadResource(NULL,res);
40 buffer=LockResource(hres);
41 size=SizeofResource(NULL,res);
46 ULONG WindowsResourceJpegReader::readChunk(ULONG offset,ULONG len,char **buf)
48 if (offset>size) return 0;
49 ULONG toread=min(size-offset,len);
50 char* buffy=(char*)malloc(toread);
51 memcpy(buffy,((char*)buffer)+offset,toread);
56 WindowsResourceJpegReader::~WindowsResourceJpegReader(){
71 useImageDimensions=true;
81 if (fileName) delete fileName;
84 int WJpeg::init(char* tfileName,bool useImage, JpegReader *rdr)
87 if (fileName) delete fileName;
90 fileName = new char[strlen(tfileName)+1];
91 strcpy(fileName,tfileName);
102 useImageDimensions=useImage;
107 ULONG WJpeg::getJpegInfo(ULONG tag){
128 int WJpeg::getJpegInfo(ULONG tag, char * buffer) {
131 strncpy(buffer,fileName,INFO_BUFFER-1);
132 buffer[INFO_BUFFER-1]=0;
139 void WJpeg::setRotate(int amount) {
148 struct my_error_mgr {
149 struct jpeg_error_mgr pub; /* "public" fields */
150 FILE *infile; /* to be used in error handler */
152 jmp_buf setjmp_buffer; /* for return to caller */
155 typedef struct my_error_mgr * my_error_ptr;
158 * Here's the routine that will replace the standard error_exit method:
162 my_error_exit (j_common_ptr cinfo)
164 /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
165 my_error_ptr myerr = (my_error_ptr) cinfo->err;
167 /* Always display the message. */
168 /* We could postpone this until after returning, if we chose. */
169 (*cinfo->err->output_message) (cinfo);
170 if (myerr->infile) fclose(myerr->infile);
171 /* Return control to the setjmp point */
172 longjmp(myerr->setjmp_buffer, 1);
177 bool WJpeg::hasError() {
183 if (drawJpeg() != 0) {
185 drawTextCentre(tr("Jpeg ERROR"), 240, 180, Colour::LIGHTTEXT);
189 /* handle picture rotation
197 void WJpeg::drawPixel(int x, int y,int w,int h,int xpos, int ypos, const Colour& c){
220 if (xb < 0 || yb < 0 ) {
221 Log::getInstance()->log("WJpeg:drawPixel",Log::ERR,"pixpos < 0 x=%d, y=%d",xb,yb);
224 Boxx::drawPixel((UINT)xb,(UINT)yb,c);
227 int WJpeg::drawJpeg() {
229 Log* logger = Log::getInstance();
230 unsigned char* buffer =NULL;
231 struct jpeg_decompress_struct cinfo;
232 struct my_error_mgr jerr;
234 cinfo.err = jpeg_std_error(&jerr.pub);
235 jerr.pub.error_exit = my_error_exit;
236 /* Establish the setjmp return context for my_error_exit to use. */
237 if (setjmp(jerr.setjmp_buffer)) {
238 /* If we get here, the JPEG code has signaled an error.
239 * We need to clean up the JPEG object, close the input file, and return.
241 if (reader) jpeg_memio_cleanup(&cinfo);
242 jpeg_destroy_decompress(&cinfo);
243 logger->log("BJpeg", Log::ERR, "JPEG error");
244 if (buffer) free(buffer);
249 jpeg_create_decompress(&cinfo);
250 if (fileName && ! reader) {
251 jsize=0; //TODO: compute size for local files
253 jerr.infile=fopen(fileName+1, "rb");
255 jerr.infile=fopen(fileName, "rb");
257 if (jerr.infile == NULL)
259 logger->log("BJpeg", Log::ERR, "Can't open JPEG");
260 jpeg_destroy_decompress(&cinfo);
263 logger->log("BJpeg", Log::DEBUG, "File opened");
264 jpeg_stdio_src(&cinfo, jerr.infile);
267 jsize=reader->initRead(fileName);
269 logger->log("BJpeg", Log::ERR, "Can't init JPEG transfer");
270 jpeg_destroy_decompress(&cinfo);
273 jpeg_memio_src(&cinfo,(void *)reader);
276 logger->log("BJpeg", Log::ERR, "neither filename nor reader set");
277 jpeg_destroy_decompress(&cinfo);
280 jpeg_read_header(&cinfo, TRUE);
281 logger->log("BJpeg", Log::DEBUG, "JPEG read header w=%i h=%i, rot=%i", cinfo.image_width, cinfo.image_height, rotate);
282 int picturew=cinfo.image_width;
283 int pictureh=cinfo.image_height;
287 pictureh=cinfo.image_width;
288 picturew=cinfo.image_height;
291 if (! useImageDimensions) {
292 //scale - we can have factors 1,2,4,8
293 int scalew=getWidth()*1000/picturew;
294 int scaleh=getHeight()*1000/pictureh;
296 if (scalew < scaleh) scale=scalew;
298 //we allow for 10% bigger...
299 if (scale >= 900) fac=1;
300 else if (scale >= 450 ) fac=2;
301 else if (scale >= 225 ) fac=4;
302 cinfo.scale_denom=fac;
303 logger->log("BJpeg", Log::DEBUG, "JPEG scaling (1/1000) pw=%i ph=%i w=%i h=%i r=%i f=%i",
306 scalew,scaleh,scale,fac);
310 //remember picture parameters
314 jpeg_start_decompress(&cinfo);
315 //recompute width based on rotation (consider scale)
316 picturew=cinfo.output_width;
317 pictureh=cinfo.output_height;
321 pictureh=cinfo.output_width;
322 picturew=cinfo.output_height;
325 //if our image is smaller - center it
326 if (! useImageDimensions) {
327 xpos=(((int)getWidth())-picturew)/2;
329 ypos=(((int)getHeight())-pictureh)/2;
332 //center point for rotation
333 int w=cinfo.output_width;
334 int h=cinfo.output_height;
335 logger->log("BJpeg", Log::DEBUG, "JPEG startup done pw=%i ph=%i, xo=%i,yo=%i, iw=%i, ih=%i", picturew, pictureh,xpos,ypos,w,h);
338 if (useImageDimensions) setDimensions(picturew, pictureh);
339 fillColour(backgroundColour);
342 //line len in bytes (3 bytes per Pixel) - for buffer (can be bigger then surface)
343 int linelen=cinfo.output_width*3;
346 buffer = (unsigned char*)malloc(config.output_height * linelen);
347 logger->log("BJpeg", Log::DEBUG, "Buffer allocated at %p, width = %i height = %i", buffer, cinfo.output_height, linelen);
348 if (buffer == NULL) {
349 if (reader) jpeg_memio_cleanup(&cinfo);
350 jpeg_destroy_decompress(&cinfo);
351 if (jerr.infile) fclose(jerr.infile);
352 logger->log("BJpeg", Log::ERR, "JPEG error - no room for buffer");
357 //unsigned char* bufferPointers[area.h];
358 //for(UINT ps = 0; ps < area.h; ps++) bufferPointers[ps] = buffer + (ps * area.w * 3);
360 logger->log("BJpeg", Log::DEBUG, "header w=%d,h=%d",cinfo.output_width,cinfo.output_height);
362 //unsigned char lbuf[linelen];
363 unsigned char *lbuf=new unsigned char[linelen];
364 unsigned char * ptr=lbuf;
366 unsigned char * ptr=buffer;
372 startFastDraw();//Tell the surface, that we will draw a lot of pixel,
373 //so that performance, can be optimized
374 while (cinfo.output_scanline < cinfo.output_height)
376 // logger->log("BJpeg", Log::DEBUG, "%i", rowsread);
377 rowsread += jpeg_read_scanlines(&cinfo,&ptr,1);
382 for (unsigned char * lp=ptr;lp < (ptr+linelen);lp+=3,x++) {
386 drawPixel(x, rowsread-1,w,h,xpos,ypos, c);
393 logger->log("BJpeg", Log::DEBUG, "Done all jpeg_read");
395 jpeg_finish_decompress(&cinfo);
396 if (reader) jpeg_memio_cleanup(&cinfo);
397 jpeg_destroy_decompress(&cinfo);
399 if (jerr.infile) fclose(jerr.infile);
401 logger->log("BJpeg", Log::DEBUG, "jpeg shutdown done, x, y %u %u", area.w, area.h);
406 surface->startFastDraw();//Tell the surface, that we will draw a lot of pixel,
407 //so that performance, can be optimized
408 for (y = 0; y < numlines; y++)
410 p = bufferPointers[y];
412 for (x = 0; x < sfclen; x++)
416 // c = ( (0xFF000000 )
417 // | (p[xoff ] << 16)
418 // | (p[xoff + 1] << 8)
419 // | (p[xoff + 2] ) );
422 c.green = p[xoff + 1];
423 c.blue = p[xoff + 2];
425 drawPixel(x, y, w,h,xpos,ypos,c);
428 surface->endFastDraw();
432 logger->log("BJpeg", Log::DEBUG, "deleted buffer");
438 ((SurfaceWin*)surface)->drawJpeg(fileName+1,offsetX,offsetY,&width,&height);//This should went into the abstract base classes?
439 //Windows has a problem with the leading / fixme
442 jsize=reader->initRead(fileName);
444 if (jsize==reader->readChunk(0,jsize,&buffer))
446 ((SurfaceWin*)surface)->drawJpeg(buffer,jsize,offsetX,offsetY,&width,&height);//This should went into the abstract base classes?
452 // setDimensions(width, height);
462 ULONG jpeg_call_reader(ULONG offset,ULONG size,char ** buf,void *cb) {
463 JpegReader *rd=(JpegReader *)cb;
464 return rd->readChunk(offset,size,buf);
467 //the memory buffer reader for the jpeg lib
468 //taken from jdatasrc.c
471 /* Expanded data source object for stdio input */
472 #include "jinclude.h"
474 #include "jerror.h"/* Expanded data source object for stdio input */
477 struct jpeg_source_mgr pub; /* public fields */
479 JOCTET * buffer; /* start of buffer */
480 boolean start_of_file; /* have we gotten any data yet? */
481 void * userdata; /* used for callback */
485 typedef my_source_mgr * my_src_ptr;
487 #define INPUT_BUF_SIZE (64*4096) /* choose an efficiently fread'able size */
491 * Initialize source --- called by jpeg_read_header
492 * before any data is actually read.
496 linit_source (j_decompress_ptr cinfo)
498 my_src_ptr src = (my_src_ptr) cinfo->src;
500 /* We reset the empty-input-file flag for each image,
501 * but we don't clear the input buffer.
502 * This is correct behavior for reading a series of images from one source.
504 src->start_of_file = TRUE;
510 * Fill the input buffer --- called whenever buffer is emptied.
512 * In typical applications, this should read fresh data into the buffer
513 * (ignoring the current state of next_input_byte & bytes_in_buffer),
514 * reset the pointer & count to the start of the buffer, and return TRUE
515 * indicating that the buffer has been reloaded. It is not necessary to
516 * fill the buffer entirely, only to obtain at least one more byte.
518 * There is no such thing as an EOF return. If the end of the file has been
519 * reached, the routine has a choice of ERREXIT() or inserting fake data into
520 * the buffer. In most cases, generating a warning message and inserting a
521 * fake EOI marker is the best course of action --- this will allow the
522 * decompressor to output however much of the image is there. However,
523 * the resulting error message is misleading if the real problem is an empty
524 * input file, so we handle that case specially.
526 * In applications that need to be able to suspend compression due to input
527 * not being available yet, a FALSE return indicates that no more data can be
528 * obtained right now, but more may be forthcoming later. In this situation,
529 * the decompressor will return to its caller (with an indication of the
530 * number of scanlines it has read, if any). The application should resume
531 * decompression after it has loaded more data into the input buffer. Note
532 * that there are substantial restrictions on the use of suspension --- see
535 * When suspending, the decompressor will back up to a convenient restart point
536 * (typically the start of the current MCU). next_input_byte & bytes_in_buffer
537 * indicate where the restart point will be if the current call returns FALSE.
538 * Data beyond this point must be rescanned after resumption, so move it to
539 * the front of the buffer rather than discarding it.
543 lfill_input_buffer (j_decompress_ptr cinfo)
545 my_src_ptr src = (my_src_ptr) cinfo->src;
547 if (src->buffer) free(src->buffer);
549 nbytes = jpeg_call_reader(src->offset, INPUT_BUF_SIZE,(char **)&(src->buffer), src->userdata);
552 WARNMS(cinfo, JWRN_JPEG_EOF);
553 src->buffer = (JOCTET *)malloc(2);
554 src->buffer[0] = (JOCTET) 0xFF;
555 src->buffer[1] = (JOCTET) JPEG_EOI;
561 src->pub.next_input_byte = src->buffer;
562 src->pub.bytes_in_buffer = nbytes;
563 src->start_of_file = FALSE;
570 * Skip data --- used to skip over a potentially large amount of
571 * uninteresting data (such as an APPn marker).
573 * Writers of suspendable-input applications must note that skip_input_data
574 * is not granted the right to give a suspension return. If the skip extends
575 * beyond the data currently in the buffer, the buffer can be marked empty so
576 * that the next read will cause a fill_input_buffer call that can suspend.
577 * Arranging for additional bytes to be discarded before reloading the input
578 * buffer is the application writer's problem.
582 lskip_input_data (j_decompress_ptr cinfo, long num_bytes)
584 my_src_ptr src = (my_src_ptr) cinfo->src;
586 /* Just a dumb implementation for now. Could use fseek() except
587 * it doesn't work on pipes. Not clear that being smart is worth
588 * any trouble anyway --- large skips are infrequent.
591 while (num_bytes > (long) src->pub.bytes_in_buffer) {
592 num_bytes -= (long) src->pub.bytes_in_buffer;
593 (void) lfill_input_buffer(cinfo);
594 /* note we assume that fill_input_buffer will never return FALSE,
595 * so suspension need not be handled.
598 src->pub.next_input_byte += (size_t) num_bytes;
599 src->pub.bytes_in_buffer -= (size_t) num_bytes;
605 * An additional method that can be provided by data source modules is the
606 * resync_to_restart method for error recovery in the presence of RST markers.
607 * For the moment, this source module just uses the default resync method
608 * provided by the JPEG library. That method assumes that no backtracking
614 * Terminate source --- called by jpeg_finish_decompress
615 * after all data has been read. Often a no-op.
617 * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
618 * application must deal with any cleanup that should happen even
623 lterm_source (j_decompress_ptr cinfo)
625 /* no work necessary here */
630 * Prepare for input from a stdio stream.
631 * The caller must have already opened the stream, and is responsible
632 * for closing it after finishing decompression.
636 jpeg_memio_src (j_decompress_ptr cinfo, void * userdata)
640 /* The source object and input buffer are made permanent so that a series
641 * of JPEG images can be read from the same file by calling jpeg_stdio_src
642 * only before the first one. (If we discarded the buffer at the end of
643 * one image, we'd likely lose the start of the next one.)
644 * This makes it unsafe to use this manager and a different source
645 * manager serially with the same JPEG object. Caveat programmer.
647 if (cinfo->src == NULL) { /* first time for this JPEG object? */
648 cinfo->src = (struct jpeg_source_mgr *)
649 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
650 SIZEOF(my_source_mgr));
651 src = (my_src_ptr) cinfo->src;
655 src = (my_src_ptr) cinfo->src;
656 src->pub.init_source = linit_source;
657 src->pub.fill_input_buffer = lfill_input_buffer;
658 src->pub.skip_input_data = lskip_input_data;
659 src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
660 src->pub.term_source = lterm_source;
661 src->userdata=userdata;
662 src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
663 src->pub.next_input_byte = NULL; /* until buffer loaded */
665 src->userdata=userdata;
671 /* cleanup to be called before cleanup of cinfo*/
673 jpeg_memio_cleanup (j_decompress_ptr cinfo) {
674 my_src_ptr src=(my_src_ptr)cinfo->src;
675 Log::getInstance()->log("BJpeg", Log::DEBUG, "cleanup src, src=%p, buf=%p",src,(src?src->buffer:0));
676 if (src && src->buffer) {