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.
23 #include <sys/types.h>
38 //#define EXTENDED_JPEGLIB
40 //a struct to store user data for the jpeg decompressor
43 WJpeg::JpegControl * ctl;
51 //the scale factors supported by the jpeg lib
59 struct scale jpegFactors[]={
60 #ifndef EXTENDED_JPEGLIB
61 {1,1},{1,2},{1,4},{1,8}
63 {1,1},{7,8},{3,4},{5,8},{1,2},{3,8},{1,4},{1,8}
69 #define LocalReader WindowsResourceJpegReader
70 class WindowsResourceJpegReader: public JpegReader {
72 virtual ULONG initRead(const char *filename);
73 virtual ULONG readChunk(ULONG offset,ULONG len,char **buf);
74 virtual ULONG getSize();
75 virtual ~WindowsResourceJpegReader();
82 ULONG WindowsResourceJpegReader::initRead(const char *filename)
84 HRSRC res=FindResource(NULL,filename,RT_RCDATA);
85 hres=LoadResource(NULL,res);
86 buffer=LockResource(hres);
87 size=SizeofResource(NULL,res);
92 ULONG WindowsResourceJpegReader::readChunk(ULONG offset,ULONG len,char **buf)
94 if (offset>size) return 0;
95 ULONG toread=min(size-offset,len);
96 char* buffy=(char*)malloc(toread);
97 memcpy(buffy,((char*)buffer)+offset,toread);
102 WindowsResourceJpegReader::~WindowsResourceJpegReader(){
107 ULONG WindowsResourceJpegReader::getSize(){
111 #define LocalReader LocalJpegReader
112 class LocalJpegReader: public JpegReader {
114 virtual ULONG initRead(const char *filename);
115 virtual ULONG readChunk(ULONG offset,ULONG len,char **buf);
116 virtual ~LocalJpegReader();
117 virtual ULONG getSize();
124 LocalJpegReader::LocalJpegReader(){
129 ULONG LocalJpegReader::initRead(const char *filename)
131 if (file) fclose(file);
133 file=fopen(filename,"r");
136 if (fstat(fileno(file), &st) != 0) return 0;
140 Log::getInstance()->log("WJepg", Log::ERR, "localReader unable to open File %s", filename);
144 ULONG LocalJpegReader::readChunk(ULONG offset,ULONG len,char **buf)
149 ULLONG cpos=ftell(file);
150 if (offset != cpos) {
151 fseek(file,offset-cpos,SEEK_CUR);
153 if (offset != (ULONG)ftell(file)) {
154 Log::getInstance()->log("WJepg", Log::ERR, "readChunk pos = %lu not available", offset);
157 *buf=(char *)malloc(len);
159 Log::getInstance()->log("WJepg", Log::ERR, "readChunk pos = %lu not available", offset);
162 bread=fread(*buf,1,len,file);
169 LocalJpegReader::~LocalJpegReader(){
170 if (file) fclose(file);
173 ULONG LocalJpegReader::getSize(){
178 /*----------------------------------------------------------------
179 the jpeg lib routines
180 ----------------------------------------------------------------
186 struct my_error_mgr {
187 struct jpeg_error_mgr pub; /* "public" fields */
189 jmp_buf setjmp_buffer; /* for return to caller */
192 typedef struct my_error_mgr * my_error_ptr;
195 * Here's the routine that will replace the standard error_exit method:
199 my_error_exit (j_common_ptr cinfo)
201 /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
202 my_error_ptr myerr = (my_error_ptr) cinfo->err;
204 /* Always display the message. */
205 /* We could postpone this until after returning, if we chose. */
206 (*cinfo->err->output_message) (cinfo);
207 /* Return control to the setjmp point */
208 longjmp(myerr->setjmp_buffer, 1);
211 ULONG jpeg_call_reader(ULONG offset,ULONG size,char ** buf,void *cb) {
212 jpegUserData *user=(jpegUserData *)cb;
213 return user->reader->readChunk(offset,size,buf);
215 //the memory buffer reader for the jpeg lib
216 //taken from jdatasrc.c
218 #include "jinclude.h"
224 struct jpeg_source_mgr pub; /* public fields */
226 JOCTET * buffer; /* start of buffer */
227 boolean start_of_file; /* have we gotten any data yet? */
228 void * userdata; /* used for callback */
232 typedef my_source_mgr * my_src_ptr;
234 #define INPUT_BUF_SIZE (64*4096) /* choose an efficiently fread'able size */
238 * Initialize source --- called by jpeg_read_header
239 * before any data is actually read.
243 linit_source (j_decompress_ptr cinfo)
245 my_src_ptr src = (my_src_ptr) cinfo->src;
247 /* We reset the empty-input-file flag for each image,
248 * but we don't clear the input buffer.
249 * This is correct behavior for reading a series of images from one source.
251 src->start_of_file = TRUE;
257 * Fill the input buffer --- called whenever buffer is emptied.
259 * In typical applications, this should read fresh data into the buffer
260 * (ignoring the current state of next_input_byte & bytes_in_buffer),
261 * reset the pointer & count to the start of the buffer, and return TRUE
262 * indicating that the buffer has been reloaded. It is not necessary to
263 * fill the buffer entirely, only to obtain at least one more byte.
265 * There is no such thing as an EOF return. If the end of the file has been
266 * reached, the routine has a choice of ERREXIT() or inserting fake data into
267 * the buffer. In most cases, generating a warning message and inserting a
268 * fake EOI marker is the best course of action --- this will allow the
269 * decompressor to output however much of the image is there. However,
270 * the resulting error message is misleading if the real problem is an empty
271 * input file, so we handle that case specially.
273 * In applications that need to be able to suspend compression due to input
274 * not being available yet, a FALSE return indicates that no more data can be
275 * obtained right now, but more may be forthcoming later. In this situation,
276 * the decompressor will return to its caller (with an indication of the
277 * number of scanlines it has read, if any). The application should resume
278 * decompression after it has loaded more data into the input buffer. Note
279 * that there are substantial restrictions on the use of suspension --- see
282 * When suspending, the decompressor will back up to a convenient restart point
283 * (typically the start of the current MCU). next_input_byte & bytes_in_buffer
284 * indicate where the restart point will be if the current call returns FALSE.
285 * Data beyond this point must be rescanned after resumption, so move it to
286 * the front of the buffer rather than discarding it.
290 lfill_input_buffer (j_decompress_ptr cinfo)
292 my_src_ptr src = (my_src_ptr) cinfo->src;
294 if (src->buffer) free(src->buffer);
296 nbytes = jpeg_call_reader(src->offset, INPUT_BUF_SIZE,(char **)&(src->buffer), src->userdata);
299 WARNMS(cinfo, JWRN_JPEG_EOF);
300 src->buffer = (JOCTET *)malloc(2);
301 src->buffer[0] = (JOCTET) 0xFF;
302 src->buffer[1] = (JOCTET) JPEG_EOI;
308 src->pub.next_input_byte = src->buffer;
309 src->pub.bytes_in_buffer = nbytes;
310 src->start_of_file = FALSE;
317 * Skip data --- used to skip over a potentially large amount of
318 * uninteresting data (such as an APPn marker).
320 * Writers of suspendable-input applications must note that skip_input_data
321 * is not granted the right to give a suspension return. If the skip extends
322 * beyond the data currently in the buffer, the buffer can be marked empty so
323 * that the next read will cause a fill_input_buffer call that can suspend.
324 * Arranging for additional bytes to be discarded before reloading the input
325 * buffer is the application writer's problem.
329 lskip_input_data (j_decompress_ptr cinfo, long num_bytes)
331 my_src_ptr src = (my_src_ptr) cinfo->src;
333 /* Just a dumb implementation for now. Could use fseek() except
334 * it doesn't work on pipes. Not clear that being smart is worth
335 * any trouble anyway --- large skips are infrequent.
338 while (num_bytes > (long) src->pub.bytes_in_buffer) {
339 num_bytes -= (long) src->pub.bytes_in_buffer;
340 (void) lfill_input_buffer(cinfo);
341 /* note we assume that fill_input_buffer will never return FALSE,
342 * so suspension need not be handled.
345 src->pub.next_input_byte += (size_t) num_bytes;
346 src->pub.bytes_in_buffer -= (size_t) num_bytes;
352 * An additional method that can be provided by data source modules is the
353 * resync_to_restart method for error recovery in the presence of RST markers.
354 * For the moment, this source module just uses the default resync method
355 * provided by the JPEG library. That method assumes that no backtracking
361 * Terminate source --- called by jpeg_finish_decompress
362 * after all data has been read. Often a no-op.
364 * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
365 * application must deal with any cleanup that should happen even
370 lterm_source (j_decompress_ptr cinfo)
372 /* no work necessary here */
377 * Prepare for input from a stdio stream.
378 * The caller must have already opened the stream, and is responsible
379 * for closing it after finishing decompression.
383 jpeg_memio_src (j_decompress_ptr cinfo, void * userdata)
387 /* The source object and input buffer are made permanent so that a series
388 * of JPEG images can be read from the same file by calling jpeg_stdio_src
389 * only before the first one. (If we discarded the buffer at the end of
390 * one image, we'd likely lose the start of the next one.)
391 * This makes it unsafe to use this manager and a different source
392 * manager serially with the same JPEG object. Caveat programmer.
394 if (cinfo->src == NULL) { /* first time for this JPEG object? */
395 cinfo->src = (struct jpeg_source_mgr *)
396 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
397 SIZEOF(my_source_mgr));
398 src = (my_src_ptr) cinfo->src;
402 src = (my_src_ptr) cinfo->src;
403 src->pub.init_source = linit_source;
404 src->pub.fill_input_buffer = lfill_input_buffer;
405 src->pub.skip_input_data = lskip_input_data;
406 src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
407 src->pub.term_source = lterm_source;
408 src->userdata=userdata;
409 src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
410 src->pub.next_input_byte = NULL; /* until buffer loaded */
412 src->userdata=userdata;
418 /* cleanup to be called before cleanup of cinfo*/
420 jpeg_memio_cleanup (j_decompress_ptr cinfo) {
421 my_src_ptr src=(my_src_ptr)cinfo->src;
422 Log::getInstance()->log("BJpeg", Log::DEBUG, "cleanup src, src=%p, buf=%p",src,(src?src->buffer:0));
423 if (src && src->buffer) {
430 //http://git.mvpmc.org/cgi-bin/gitweb.cgi?p=mvpmc.git;a=blob_plain;h=02d4354c0cbbed802a9aa1478918a49fcbf61d00;f=libs/libwidget/image_jpeg.c
432 #define GET2BYTES(cinfo, V, swap, offset) do { \
433 if (cinfo->src->bytes_in_buffer == 0) (*mysrc->pub.fill_input_buffer)(cinfo); \
434 cinfo->src->bytes_in_buffer--; \
435 V = (*cinfo->src->next_input_byte++) << (swap?0:8); \
436 if (cinfo->src->bytes_in_buffer == 0) (*mysrc->pub.fill_input_buffer)(cinfo); \
437 cinfo->src->bytes_in_buffer--; \
438 V += (*cinfo->src->next_input_byte++) << (swap?8:0); \
439 offset += 2; } while(0)
441 #define GET4BYTES(cinfo, V, swap, offset) do { \
442 if (cinfo->src->bytes_in_buffer == 0) (*mysrc->pub.fill_input_buffer)(cinfo); \
443 cinfo->src->bytes_in_buffer--; \
444 V = (*cinfo->src->next_input_byte++) << (swap?0:24); \
445 if (cinfo->src->bytes_in_buffer == 0) (*mysrc->pub.fill_input_buffer)(cinfo); \
446 cinfo->src->bytes_in_buffer--; \
447 V += (*cinfo->src->next_input_byte++) << (swap?8:16); \
448 if (cinfo->src->bytes_in_buffer == 0) (*mysrc->pub.fill_input_buffer)(cinfo); \
449 cinfo->src->bytes_in_buffer--; \
450 V += (*cinfo->src->next_input_byte++) << (swap?16:8); \
451 if (cinfo->src->bytes_in_buffer == 0) (*mysrc->pub.fill_input_buffer)(cinfo); \
452 cinfo->src->bytes_in_buffer--; \
453 V += (*cinfo->src->next_input_byte++) << (swap?24:0); \
454 offset += 4; } while(0)
457 get_exif_orient (j_decompress_ptr cinfo)
458 /* Get the Exif orientation info */
460 unsigned int tmp, offset, length, numtags;
465 my_src_ptr mysrc = (my_src_ptr) cinfo->src;
468 GET2BYTES(cinfo, length, 0, offset);
469 if (length<8) goto err;
471 GET4BYTES(cinfo, tmp, 0, offset);
472 if (tmp != 0x45786966) goto err;
473 GET2BYTES(cinfo, tmp, 0, offset);
474 if (tmp != 0x0000) goto err;
476 GET2BYTES(cinfo, tmp, 0, offset);
477 if (tmp == 0x4949) swap = 1;
478 else if (tmp == 0x4d4d) swap = 0;
480 GET2BYTES(cinfo, tmp, swap, offset);
481 if (tmp != 0x002A) goto err;
482 /* offset to first IFD */
483 GET4BYTES(cinfo, tmp, swap, offset);
485 (*mysrc->pub.skip_input_data)(cinfo, tmp-8);
486 /* number of tags in IFD */
487 GET2BYTES(cinfo, numtags, swap, offset);
488 if (numtags == 0) goto err;
490 /* Search for Orientation Tag in IFD0 */
492 if (offset > length-12) goto err;
493 GET2BYTES(cinfo, tmp, swap, offset);
494 if (tmp == 0x0112) break; /* found Orientation Tag */
495 if (--numtags == 0) goto err;
497 (*mysrc->pub.skip_input_data)(cinfo, 10);
500 (*mysrc->pub.skip_input_data)(cinfo, 6);
501 GET2BYTES(cinfo, orient, swap, offset);
502 if( orient==0 || orient>8 ) orient = 1;
504 Log::getInstance()->log("WJpeg", Log::DEBUG, "read exif orientation %u", orient);
505 jpegUserData * ud=(jpegUserData *)(mysrc->userdata);
508 ud->ctl->exifRotation=WJpeg::ROT_180;
511 ud->ctl->exifRotation=WJpeg::ROT_90;
514 ud->ctl->exifRotation=WJpeg::ROT_270;
519 (*mysrc->pub.skip_input_data)(cinfo, length-offset);
524 /*----------------------------------------------------------------
526 ----------------------------------------------------------------
537 if (owningReader && reader) delete reader;
540 int WJpeg::init(char* tfileName)
542 if (owningReader && reader) delete reader;
543 errbuf[0]=0; //clean error state
544 LocalReader *myreader=new LocalReader();
547 ULONG psize=myreader->initRead(tfileName);
552 snprintf(errbuf,200,"unable to open %s",tfileName);
561 bool WJpeg::hasError() {
562 return (errbuf[0] != 0);
570 Surface *sfc=getSurface(myRegion);
575 if (drawJpeg(&ctl,sfc,reader,backgroundColour) ) ok=true;
578 snprintf(errbuf,200,"jpeg reader not initialized");
581 drawTextCentre(tr("Jpeg ERROR"), 240, 170, Colour::LIGHTTEXT);
582 if (errbuf[0] != 0) drawTextCentre(errbuf,240,200, Colour::LIGHTTEXT);
583 if (ctl.error[0] != 0) drawTextCentre(ctl.error,240,230, Colour::LIGHTTEXT);
588 the main drawing function
589 this will read the pciture via the reader
590 and draw directly into the surface
591 it will compute an appropriate scale and set the infos in the
592 JpegControl structure
595 bool WJpeg::drawJpeg(JpegControl * ctl,Surface * sfc,JpegReader *rdr, Colour & backgroundColour) {
596 Log* logger = Log::getInstance();
597 if (! rdr || ! sfc) {
598 logger->log("BJpeg", Log::ERR, "JPEG error rdr=NULL or sfc=NULL");
601 logger->log("BJpeg", Log::DEBUG, "draw Jpeg Started sfc=%p, rdr=%p",sfc,rdr);
602 unsigned char* buffer =NULL;
603 struct jpeg_decompress_struct cinfo;
604 struct my_error_mgr jerr;
605 cinfo.err = jpeg_std_error(&jerr.pub);
606 jerr.pub.error_exit = my_error_exit;
607 /* Establish the setjmp return context for my_error_exit to use. */
608 if (setjmp(jerr.setjmp_buffer)) {
609 /* If we get here, the JPEG code has signaled an error.
610 * We need to clean up the JPEG object, close the input file, and return.
612 if (rdr) jpeg_memio_cleanup(&cinfo);
613 jpeg_destroy_decompress(&cinfo);
614 logger->log("BJpeg", Log::ERR, "JPEG error");
615 if (buffer) free(buffer);
618 jpegUserData userdata;
621 jpeg_create_decompress(&cinfo);
624 ctl->exifRotation=ROT_0;
627 //create the input for the jpeg lib
628 jpeg_memio_src(&cinfo,(void *)(&userdata));
629 //processor for EXIF data
630 jpeg_set_marker_processor(&cinfo, JPEG_APP0+1, get_exif_orient);
631 //read in header info
632 jpeg_read_header(&cinfo, TRUE);
633 ctl->picw=cinfo.image_width;
634 ctl->pich=cinfo.image_height;
635 ctl->compressedSize=rdr->getSize();
636 //now we have important info available in ctl (pictuerw,h, exif orientation,size)
637 //compute rotation due to the defined enum values we can simply add them
638 ctl->finalRotation=(enum Rotation)((ctl->rotation+ctl->exifRotation)%4);
639 logger->log("BJpeg", Log::DEBUG, "JPEG read header w=%i h=%i, rot=%i", ctl->picw,ctl->pich,ctl->finalRotation);
640 //now we have to compute the scale
641 //input: ctl->picw,ctl->pich,ctl->finalRotation,ctl->mode,ctl->scaleAmount, ctl->scaleafter
642 // list of available jpeg scale factors
643 //out: scalenum,scaledenom,scaleafter
645 UINT picturew=ctl->picw;
646 UINT pictureh=ctl->pich;
647 switch (ctl->finalRotation){
659 if (! ctl->enlarge) {
660 //scale - compute the factors to fit 100%
661 int scalew=1000*picturew/ctl->area.w;
662 int scaleh=1000*pictureh/ctl->area.h;
664 if (scalew > scaleh) scale=scalew;
666 //OK now find out which is the optimal setting
667 //rule: find settings being nearest to:
668 // mode=LETTER - smaller or equal screen size (i.e. scale*scalefactor <= 1000)
669 // mode=CROP - bigger or equal screen size (i.e. scale *scalefactor>= 1000)
670 // mode=CROPPERCENT - smaller or equal screensize*scaleamount (i.e. scale*scalefactor<= 1000*scaleamount)
671 // scaleamount is in % - so in reality we use scaleamount*10 instead scaleamount*1000
672 //the scalefactor computes as scalenum/(scaledenom*scaleafter)
675 logger->log("BJpeg", Log::DEBUG, "start scaling screenw=%u, screenh=%u, pw=%u,ph=%u, scale=%d, mode=%d, %%=%u, after=%u",
676 ctl->area.w,ctl->area.h,picturew,pictureh,scale,(int)ctl->mode,ctl->scaleAmount, ctl->scaleafter);
677 for (UINT j=0;j<sizeof(jpegFactors)/sizeof(jpegFactors[0]);j++) {
678 for (UINT sa=1;sa<=ctl->scaleafter;sa++) {
679 int curf=(scale*jpegFactors[j].num)/(jpegFactors[j].denom*sa);
681 logger->log("BJpeg", Log::DEBUG, "testing scale curf=%d,num=%u,denom=%u,after=%u,minDiff=%d",
682 curf,jpegFactors[j].num,jpegFactors[j].denom,sa,minDiff);
685 if (curf >= 1000 && curf < (minDiff +1000)) {
691 if (curf <= 1000 && curf > (1000-minDiff)) {
697 if (curf <= 10*(int)ctl->scaleAmount ) {
699 if (abs < 0) abs=-abs;
708 logger->log("BJpeg", Log::DEBUG, "testing scale curf=%d,take this",curf);
709 scalenum=jpegFactors[j].num;
710 scaledenom=jpegFactors[j].denom;
715 ctl->scale=100*scalenum/(scaledenom*scaleafter);
717 logger->log("BJpeg", Log::DEBUG, "JPEG scaling found scale=%i num=%i denom=%i after=%i result=%i scale=%i%% ",
718 scale,scalenum,scaledenom,scaleafter,scale*ctl->scale/100,ctl->scale);
720 cinfo.scale_denom=scaledenom;
721 cinfo.scale_num=scalenum;
725 //set drawing area according to picture
726 ctl->area.w=ctl->picw;
727 ctl->area.h=ctl->pich;
730 //now we know the scaling
731 //compute the scaled size and position
733 jpeg_start_decompress(&cinfo);
734 //picturew/h is now the output width from the decompressor and afterscaler
736 picturew=cinfo.output_width;
737 pictureh=cinfo.output_height;
738 if (scaleafter > 1) {
739 picturew=picturew/scaleafter;
740 pictureh=pictureh/scaleafter;
742 //if our image is smaller - center it
743 if (! ctl->enlarge) {
744 if (ctl->finalRotation == ROT_90 || ctl->finalRotation == ROT_270) {
746 xpos=(((int)ctl->area.w)-dim)/2;
748 ypos=(((int)ctl->area.h)-dim)/2;
751 xpos=(((int)ctl->area.w)-dim)/2;
753 ypos=(((int)ctl->area.h)-dim)/2;
760 //remember the jpeg dimensions for computing the buffer
761 UINT jpegwidth=cinfo.output_width;
762 UINT jpegheight=cinfo.output_height;
763 logger->log("BJpeg", Log::DEBUG, "JPEG startup done pw=%i ph=%i, xo=%i,yo=%i, jw=%i, jh=%i, rot=%d",
764 picturew, pictureh,xpos,ypos,jpegwidth,jpegheight,(int)ctl->finalRotation*90);
766 //fill the background
767 sfc->fillblt(ctl->area.x,ctl->area.y,ctl->area.w,ctl->area.h,backgroundColour.rgba());
769 //line len in bytes (3 bytes per Pixel) - for buffer (can be bigger then surface)
770 int linelen=jpegwidth*3;
773 buffer = (unsigned char*)malloc(jpegheight * linelen);
774 logger->log("BJpeg", Log::DEBUG, "Buffer allocated at %p, lines = %i linelen = %i", buffer, jpegheight, linelen);
775 if (buffer == NULL) {
776 if (rdr) jpeg_memio_cleanup(&cinfo);
777 jpeg_destroy_decompress(&cinfo);
778 logger->log("BJpeg", Log::ERR, "JPEG error - no room for buffer");
779 snprintf(ctl->error,100,"no room for buffer");
785 //unsigned char lbuf[linelen];
786 unsigned char *lbuf=new unsigned char[linelen*scaleafter];
787 unsigned char * ptr=lbuf;
790 unsigned char * ptr=buffer;
796 sfc->startFastDraw();//Tell the surface, that we will draw a lot of pixel,
797 //so that performance, can be optimized
798 logger->log("BJpeg", Log::DEBUG, "start drawing ");
800 //factors to base 1024
802 if (scaleafter > 1) {
803 colincr=3*scaleafter-3;
804 fac=1024/(scaleafter*scaleafter);
806 logger->log("BJpeg", Log::DEBUG, "jpeg draw scale %d image: %u %u, picture: %u %u", scaleafter,picturew,pictureh,jpegwidth,jpegheight);
807 while (cinfo.output_scanline < jpegheight)
809 // logger->log("BJpeg", Log::DEBUG, "%i", rowsread);
810 rowsread += jpeg_read_scanlines(&cinfo,&ptr,1);
814 if (scaleafter > 1) {
815 if (rowsread % scaleafter != scaleafter-1) {
816 //this simple approach wold maybe forget scaleafter -1 lines at the end...
822 drawLine(sfc,ctl->finalRotation,ptr,scaleafter,picturew,pictureh,xpos,ypos,outy,linelen,colincr,scaleafter,fac);
829 logger->log("BJpeg", Log::DEBUG, "Done all jpeg_read");
831 jpeg_finish_decompress(&cinfo);
832 jpeg_memio_cleanup(&cinfo);
833 jpeg_destroy_decompress(&cinfo);
835 logger->log("BJpeg", Log::DEBUG, "jpeg shutdown done");
840 //Tell the surface, that we will draw a lot of pixel,
841 //so that performance, can be optimized
842 sfc->startFastDraw();
843 logger->log("BJpeg", Log::DEBUG, "jpeg start buffer draw" );
844 unsigned char* p=buffer; //start of first row
845 UINT rowincr=linelen*scaleafter;
846 //for simplicity omit last line to avoid running out of buffer
847 for (y = 0; y < pictureh-1 ;y++)
849 drawLine(sfc,ctl->finalRotation,p,scaleafter,picturew,pictureh,xpos,ypos,y,linelen,colincr,scaleafter,fac);
853 logger->log("BJpeg", Log::DEBUG, "end draw");
858 logger->log("BJpeg", Log::DEBUG, "deleted buffer");
863 Surface * WJpeg::getSurface(Region & r) {
864 r.x=getRootBoxOffsetX();
865 r.y=getRootBoxOffsetY();
868 return Boxx::getSurface();