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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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,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);
339 // Temp disabled for boxx. what does this do anyway .. - cjt
341 if (useImageDimensions) setDimensions(picturew, pictureh);
342 fillColour(backgroundColour);
346 //line len in bytes (3 bytes per Pixel) - for buffer (can be bigger then surface)
347 int linelen=cinfo.output_width*3;
350 buffer = (unsigned char*)malloc(config.output_height * linelen);
351 logger->log("BJpeg", Log::DEBUG, "Buffer allocated at %p, width = %i height = %i", buffer, cinfo.output_height, linelen);
352 if (buffer == NULL) {
353 if (reader) jpeg_memio_cleanup(&cinfo);
354 jpeg_destroy_decompress(&cinfo);
355 if (jerr.infile) fclose(jerr.infile);
356 logger->log("BJpeg", Log::ERR, "JPEG error - no room for buffer");
361 //unsigned char* bufferPointers[area.h];
362 //for(UINT ps = 0; ps < area.h; ps++) bufferPointers[ps] = buffer + (ps * area.w * 3);
364 logger->log("BJpeg", Log::DEBUG, "header w=%d,h=%d",cinfo.output_width,cinfo.output_height);
366 //unsigned char lbuf[linelen];
367 unsigned char *lbuf=new unsigned char[linelen];
368 unsigned char * ptr=lbuf;
370 unsigned char * ptr=buffer;
376 startFastDraw();//Tell the surface, that we will draw a lot of pixel,
377 //so that performance, can be optimized
378 while (cinfo.output_scanline < cinfo.output_height)
380 // logger->log("BJpeg", Log::DEBUG, "%i", rowsread);
381 rowsread += jpeg_read_scanlines(&cinfo,&ptr,1);
386 for (unsigned char * lp=ptr;lp < (ptr+linelen);lp+=3,x++) {
390 drawPixel(x, rowsread-1,w,h,xpos,ypos, c);
397 logger->log("BJpeg", Log::DEBUG, "Done all jpeg_read");
399 jpeg_finish_decompress(&cinfo);
400 if (reader) jpeg_memio_cleanup(&cinfo);
401 jpeg_destroy_decompress(&cinfo);
403 if (jerr.infile) fclose(jerr.infile);
405 logger->log("BJpeg", Log::DEBUG, "jpeg shutdown done, x, y %u %u", area.w, area.h);
410 surface->startFastDraw();//Tell the surface, that we will draw a lot of pixel,
411 //so that performance, can be optimized
412 for (y = 0; y < numlines; y++)
414 p = bufferPointers[y];
416 for (x = 0; x < sfclen; x++)
420 // c = ( (0xFF000000 )
421 // | (p[xoff ] << 16)
422 // | (p[xoff + 1] << 8)
423 // | (p[xoff + 2] ) );
426 c.green = p[xoff + 1];
427 c.blue = p[xoff + 2];
429 drawPixel(x, y, w,h,xpos,ypos,c);
432 surface->endFastDraw();
436 logger->log("BJpeg", Log::DEBUG, "deleted buffer");
442 ((SurfaceWin*)surface)->drawJpeg(fileName+1,offsetX,offsetY,&width,&height);//This should went into the abstract base classes?
443 //Windows has a problem with the leading / fixme
446 jsize=reader->initRead(fileName);
448 if (jsize==reader->readChunk(0,jsize,&buffer))
450 ((SurfaceWin*)surface)->drawJpeg(buffer,jsize,offsetX,offsetY,&width,&height);//This should went into the abstract base classes?
456 // setDimensions(width, height);
466 ULONG jpeg_call_reader(ULONG offset,ULONG size,char ** buf,void *cb) {
467 JpegReader *rd=(JpegReader *)cb;
468 return rd->readChunk(offset,size,buf);
471 //the memory buffer reader for the jpeg lib
472 //taken from jdatasrc.c
475 /* Expanded data source object for stdio input */
476 #include "jinclude.h"
478 #include "jerror.h"/* Expanded data source object for stdio input */
481 struct jpeg_source_mgr pub; /* public fields */
483 JOCTET * buffer; /* start of buffer */
484 boolean start_of_file; /* have we gotten any data yet? */
485 void * userdata; /* used for callback */
489 typedef my_source_mgr * my_src_ptr;
491 #define INPUT_BUF_SIZE (64*4096) /* choose an efficiently fread'able size */
495 * Initialize source --- called by jpeg_read_header
496 * before any data is actually read.
500 linit_source (j_decompress_ptr cinfo)
502 my_src_ptr src = (my_src_ptr) cinfo->src;
504 /* We reset the empty-input-file flag for each image,
505 * but we don't clear the input buffer.
506 * This is correct behavior for reading a series of images from one source.
508 src->start_of_file = TRUE;
514 * Fill the input buffer --- called whenever buffer is emptied.
516 * In typical applications, this should read fresh data into the buffer
517 * (ignoring the current state of next_input_byte & bytes_in_buffer),
518 * reset the pointer & count to the start of the buffer, and return TRUE
519 * indicating that the buffer has been reloaded. It is not necessary to
520 * fill the buffer entirely, only to obtain at least one more byte.
522 * There is no such thing as an EOF return. If the end of the file has been
523 * reached, the routine has a choice of ERREXIT() or inserting fake data into
524 * the buffer. In most cases, generating a warning message and inserting a
525 * fake EOI marker is the best course of action --- this will allow the
526 * decompressor to output however much of the image is there. However,
527 * the resulting error message is misleading if the real problem is an empty
528 * input file, so we handle that case specially.
530 * In applications that need to be able to suspend compression due to input
531 * not being available yet, a FALSE return indicates that no more data can be
532 * obtained right now, but more may be forthcoming later. In this situation,
533 * the decompressor will return to its caller (with an indication of the
534 * number of scanlines it has read, if any). The application should resume
535 * decompression after it has loaded more data into the input buffer. Note
536 * that there are substantial restrictions on the use of suspension --- see
539 * When suspending, the decompressor will back up to a convenient restart point
540 * (typically the start of the current MCU). next_input_byte & bytes_in_buffer
541 * indicate where the restart point will be if the current call returns FALSE.
542 * Data beyond this point must be rescanned after resumption, so move it to
543 * the front of the buffer rather than discarding it.
547 lfill_input_buffer (j_decompress_ptr cinfo)
549 my_src_ptr src = (my_src_ptr) cinfo->src;
551 if (src->buffer) free(src->buffer);
553 nbytes = jpeg_call_reader(src->offset, INPUT_BUF_SIZE,(char **)&(src->buffer), src->userdata);
556 WARNMS(cinfo, JWRN_JPEG_EOF);
557 src->buffer = (JOCTET *)malloc(2);
558 src->buffer[0] = (JOCTET) 0xFF;
559 src->buffer[1] = (JOCTET) JPEG_EOI;
565 src->pub.next_input_byte = src->buffer;
566 src->pub.bytes_in_buffer = nbytes;
567 src->start_of_file = FALSE;
574 * Skip data --- used to skip over a potentially large amount of
575 * uninteresting data (such as an APPn marker).
577 * Writers of suspendable-input applications must note that skip_input_data
578 * is not granted the right to give a suspension return. If the skip extends
579 * beyond the data currently in the buffer, the buffer can be marked empty so
580 * that the next read will cause a fill_input_buffer call that can suspend.
581 * Arranging for additional bytes to be discarded before reloading the input
582 * buffer is the application writer's problem.
586 lskip_input_data (j_decompress_ptr cinfo, long num_bytes)
588 my_src_ptr src = (my_src_ptr) cinfo->src;
590 /* Just a dumb implementation for now. Could use fseek() except
591 * it doesn't work on pipes. Not clear that being smart is worth
592 * any trouble anyway --- large skips are infrequent.
595 while (num_bytes > (long) src->pub.bytes_in_buffer) {
596 num_bytes -= (long) src->pub.bytes_in_buffer;
597 (void) lfill_input_buffer(cinfo);
598 /* note we assume that fill_input_buffer will never return FALSE,
599 * so suspension need not be handled.
602 src->pub.next_input_byte += (size_t) num_bytes;
603 src->pub.bytes_in_buffer -= (size_t) num_bytes;
609 * An additional method that can be provided by data source modules is the
610 * resync_to_restart method for error recovery in the presence of RST markers.
611 * For the moment, this source module just uses the default resync method
612 * provided by the JPEG library. That method assumes that no backtracking
618 * Terminate source --- called by jpeg_finish_decompress
619 * after all data has been read. Often a no-op.
621 * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
622 * application must deal with any cleanup that should happen even
627 lterm_source (j_decompress_ptr cinfo)
629 /* no work necessary here */
634 * Prepare for input from a stdio stream.
635 * The caller must have already opened the stream, and is responsible
636 * for closing it after finishing decompression.
640 jpeg_memio_src (j_decompress_ptr cinfo, void * userdata)
644 /* The source object and input buffer are made permanent so that a series
645 * of JPEG images can be read from the same file by calling jpeg_stdio_src
646 * only before the first one. (If we discarded the buffer at the end of
647 * one image, we'd likely lose the start of the next one.)
648 * This makes it unsafe to use this manager and a different source
649 * manager serially with the same JPEG object. Caveat programmer.
651 if (cinfo->src == NULL) { /* first time for this JPEG object? */
652 cinfo->src = (struct jpeg_source_mgr *)
653 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
654 SIZEOF(my_source_mgr));
655 src = (my_src_ptr) cinfo->src;
659 src = (my_src_ptr) cinfo->src;
660 src->pub.init_source = linit_source;
661 src->pub.fill_input_buffer = lfill_input_buffer;
662 src->pub.skip_input_data = lskip_input_data;
663 src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
664 src->pub.term_source = lterm_source;
665 src->userdata=userdata;
666 src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
667 src->pub.next_input_byte = NULL; /* until buffer loaded */
669 src->userdata=userdata;
675 /* cleanup to be called before cleanup of cinfo*/
677 jpeg_memio_cleanup (j_decompress_ptr cinfo) {
678 my_src_ptr src=(my_src_ptr)cinfo->src;
679 Log::getInstance()->log("BJpeg", Log::DEBUG, "cleanup src, src=%p, buf=%p",src,(src?src->buffer:0));
680 if (src && src->buffer) {