1 /**************************************************************************/
2 /*                                                                        */
3 /* Copyright (c) 2001, 2010 NoMachine, http://www.nomachine.com/.         */
4 /*                                                                        */
5 /* NXCOMP, NX protocol compression and NX extensions to this software     */
6 /* are copyright of NoMachine. Redistribution and use of the present      */
7 /* software is allowed according to terms specified in the file LICENSE   */
8 /* which comes in the source distribution.                                */
9 /*                                                                        */
10 /* Check http://www.nomachine.com/licensing.html for applicability.       */
11 /*                                                                        */
12 /* NX and NoMachine are trademarks of Medialogic S.p.A.                   */
13 /*                                                                        */
14 /* All rights reserved.                                                   */
15 /*                                                                        */
16 /**************************************************************************/
17 
18 #include <X11/Xmd.h>
19 
20 #ifdef ANDROID
21 #include <strings.h>
22 #endif
23 #include <unistd.h>
24 #include <setjmp.h>
25 #include <zlib.h>
26 
27 #ifdef __cplusplus
28 
29 extern "C"
30 {
31   #include <stdio.h>
32   #include <jpeglib.h>
33 }
34 
35 #else
36 
37 #include <stdio.h>
38 #include <jpeglib.h>
39 
40 #endif
41 
42 #include "Misc.h"
43 #include "Jpeg.h"
44 #include "Unpack.h"
45 
46 #define PANIC
47 #define WARNING
48 #undef  TEST
49 #undef  DEBUG
50 
51 #define RGB24_TO_PIXEL(bpp,r,g,b)                               \
52    ((((CARD##bpp)(r) & 0xff) * srcRedMax + 127) / 255           \
53     << srcRedShift |                                            \
54     (((CARD##bpp)(g) & 0xff) * srcGreenMax + 127) / 255         \
55     << srcGreenShift |                                          \
56     (((CARD##bpp)(b) & 0xff) * srcBlueMax + 127) / 255          \
57     << srcBlueShift)
58 
59 #define RGB24_TO_PIXEL32(r,g,b)                                 \
60   (((CARD32)(r) & 0xff) << srcRedShift |                        \
61    ((CARD32)(g) & 0xff) << srcGreenShift |                      \
62    ((CARD32)(b) & 0xff) << srcBlueShift)
63 
64 //
65 // Functions from Unpack.cpp
66 //
67 
68 extern int Unpack32To32(const T_colormask *colormask, const unsigned int *data,
69                             unsigned int *out, unsigned int *end);
70 
71 extern int Unpack24To24(const T_colormask *colormask, const unsigned char *data,
72                             unsigned char *out, unsigned char *end);
73 
74 extern int Unpack16To16(const T_colormask *colormask, const unsigned char *data,
75                             unsigned char *out, unsigned char *end);
76 
77 //
78 // Local functions used for the jpeg decompression.
79 //
80 
81 static void JpegSetSrcManager(j_decompress_ptr cinfo, CARD8 *compressedData, int compressedLen);
82 static void JpegInitSource(j_decompress_ptr cinfo);
83 static void JpegTermSource(j_decompress_ptr cinfo);
84 static void JpegSkipInputData(j_decompress_ptr cinfo, long num_bytes);
85 
86 static boolean JpegFillInputBuffer(j_decompress_ptr cinfo);
87 
88 static int DecompressJpeg16(unsigned char *compressedData, int compressedLen,
89                                 unsigned int w, unsigned int h, unsigned char *dstBuf, int byteOrder);
90 
91 static int DecompressJpeg24(unsigned char *compressedData, int compressedLen,
92                                 unsigned int w, unsigned int h, unsigned char *dstBuf, int byteOrder);
93 
94 static int DecompressJpeg32(unsigned char *compressedData, int compressedLen,
95                                 unsigned int w, unsigned int h, unsigned char *dstBuf, int byteOrder);
96 
97 void UnpackJpegErrorHandler(j_common_ptr cinfo);
98 
99 //
100 // Colormap stuff.
101 //
102 
103 CARD16 srcRedMax, srcGreenMax, srcBlueMax;
104 CARD8  srcRedShift, srcGreenShift, srcBlueShift;
105 
106 //
107 // Error handler.
108 //
109 
110 static bool jpegError;
111 
112 jmp_buf UnpackJpegContext;
113 
UnpackJpegErrorHandler(j_common_ptr cinfo)114 void UnpackJpegErrorHandler(j_common_ptr cinfo)
115 {
116   #ifdef PANIC
117   *logofs << "UnpackJpegErrorHandler: PANIC! Detected error in JPEG decompression.\n"
118           << logofs_flush;
119 
120   *logofs << "UnpackJpegErrorHandler: PANIC! Trying to revert to the previous context.\n"
121           << logofs_flush;
122   #endif
123 
124   jpegError = 1;
125 
126   longjmp(UnpackJpegContext, 1);
127 }
128 
129 //
130 // Attributes used for the jpeg decompression.
131 //
132 
133 static struct  jpeg_source_mgr jpegSrcManager;
134 static JOCTET  *jpegBufferPtr;
135 static size_t  jpegBufferLen;
136 
137 static char    *tmpBuf;
138 static int     tmpBufSize = 0;
139 
UnpackJpeg(T_geometry * geometry,unsigned char method,unsigned char * srcData,int srcSize,int dstBpp,int dstWidth,int dstHeight,unsigned char * dstData,int dstSize)140 int UnpackJpeg(T_geometry *geometry, unsigned char method, unsigned char *srcData,
141                    int srcSize, int dstBpp, int dstWidth, int dstHeight,
142                        unsigned char *dstData, int dstSize)
143 {
144   int byteOrder = geometry -> image_byte_order;
145 
146   //
147   // Check if data is coming from a failed unsplit.
148   //
149 
150   if (srcSize < 2 || (srcData[0] == SPLIT_PATTERN &&
151           srcData[1] == SPLIT_PATTERN))
152   {
153     #ifdef WARNING
154     *logofs << "UnpackJpeg: WARNING! Skipping unpack of dummy data.\n"
155             << logofs_flush;
156     #endif
157 
158     return -1;
159   }
160 
161   #ifdef DEBUG
162   *logofs << "UnpackJpeg: Decompression. Source size "
163           << srcSize << " bits per plane " << dstBpp
164           << ".\n" << logofs_flush;
165   #endif
166 
167   srcRedShift   = ffs(geometry -> red_mask)   - 1;
168   srcGreenShift = ffs(geometry -> green_mask) - 1;
169   srcBlueShift  = ffs(geometry -> blue_mask)  - 1;
170 
171   #ifdef DEBUG
172   *logofs << "UnpackJpeg: Red shift " << (int) srcRedShift
173           << " green shift " << (int) srcGreenShift << " blue shift "
174           << (int) srcBlueShift << ".\n" << logofs_flush;
175   #endif
176 
177   srcRedMax   = geometry -> red_mask   >> srcRedShift;
178   srcGreenMax = geometry -> green_mask >> srcGreenShift;
179   srcBlueMax  = geometry -> blue_mask  >> srcBlueShift;
180 
181   #ifdef DEBUG
182   *logofs << "UnpackJpeg: Red mask " << (void *) geometry -> red_mask
183           << " green mask " << (void *) geometry -> green_mask
184           << " blue mask " << (void *) geometry -> blue_mask
185           << ".\n" << logofs_flush;
186   #endif
187 
188   #ifdef DEBUG
189   *logofs << "UnpackJpeg: Red max " << srcRedMax << " green max "
190           << srcGreenMax << " blue max " << srcBlueMax
191           << ".\n" << logofs_flush;
192   #endif
193 
194   //
195   // Make enough space in the temporary
196   // buffer to have one complete row of
197   // the image with 3 bytes for a pixel.
198   //
199 
200   tmpBufSize = dstWidth * 3;
201   tmpBuf     = new char[tmpBufSize];
202 
203   if (tmpBuf == NULL)
204   {
205     #ifdef PANIC
206     *logofs << "UnpackJpeg: PANIC! Cannot allocate "
207             << dstWidth * 3 << " bytes for Jpeg "
208             << "decompressed data.\n" << logofs_flush;
209     #endif
210 
211     delete [] tmpBuf;
212 
213     return -1;
214   }
215 
216   int result = 1;
217 
218   switch(dstBpp)
219   {
220     case 8:
221     {
222       //
223       // Simply move the data from srcData to dstData
224       // taking into consideration the correct padding.
225       //
226 
227       int row;
228 
229       unsigned char * dstBuff = dstData;
230       unsigned char * srcBuff = srcData;
231 
232       for (row = 0; row < dstHeight; row++)
233       {
234         memcpy(dstBuff, srcBuff, dstWidth);
235 
236         dstBuff += RoundUp4(dstWidth);
237         srcBuff += dstWidth;
238       }
239 
240       break;
241     }
242     case 16:
243     {
244       result = DecompressJpeg16(srcData, srcSize, dstWidth,
245                                     dstHeight, dstData, byteOrder);
246       break;
247     }
248     case 24:
249     {
250       result = DecompressJpeg24(srcData, srcSize, dstWidth,
251                                     dstHeight, dstData, byteOrder);
252       break;
253     }
254     case 32:
255     {
256       result = DecompressJpeg32(srcData, srcSize, dstWidth,
257                                     dstHeight, dstData, byteOrder);
258       break;
259     }
260     default:
261     {
262       #ifdef PANIC
263       *logofs << "UnpackJpeg: PANIC! Failed to decode Jpeg image. "
264               << " Unsupported Bpp value " << dstBpp
265               << " for the Jpeg compression"
266               << ".\n" << logofs_flush;
267       #endif
268 
269       delete [] tmpBuf;
270 
271       result = -1;
272     }
273   }
274 
275   #ifdef DEBUG
276   *logofs << "UnpackJpeg: Decompression finished with result "
277           << result << ".\n" << logofs_flush;
278   #endif
279 
280   if (result == -1)
281   {
282     delete [] tmpBuf;
283 
284     #ifdef PANIC
285     *logofs << "UnpackJpeg: PANIC! Failed to decode Jpeg image using "
286             << dstBpp << " Bpp destination.\n" << logofs_flush;
287     #endif
288 
289     return result;
290   }
291 
292   //
293   // Apply the correction for the brightness.
294   //
295 
296   int maskMethod;
297 
298   switch(method)
299   {
300     case PACK_JPEG_8_COLORS:
301     {
302       maskMethod = MASK_8_COLORS;
303 
304       break;
305     }
306     case PACK_JPEG_64_COLORS:
307     {
308       maskMethod = MASK_64_COLORS;
309 
310       break;
311     }
312     case PACK_JPEG_256_COLORS:
313     {
314       maskMethod = MASK_256_COLORS;
315 
316       break;
317     }
318     case PACK_JPEG_512_COLORS:
319     {
320       maskMethod = MASK_512_COLORS;
321 
322       break;
323     }
324     case PACK_JPEG_4K_COLORS:
325     {
326       maskMethod = MASK_4K_COLORS;
327 
328       break;
329     }
330     case PACK_JPEG_32K_COLORS:
331     {
332       maskMethod = MASK_32K_COLORS;
333 
334       break;
335     }
336     case PACK_JPEG_64K_COLORS:
337     {
338       maskMethod = MASK_64K_COLORS;
339 
340       break;
341     }
342     case PACK_JPEG_256K_COLORS:
343     {
344       maskMethod = MASK_256K_COLORS;
345 
346       break;
347     }
348     case PACK_JPEG_2M_COLORS:
349     {
350       maskMethod = MASK_2M_COLORS;
351 
352       break;
353     }
354     case PACK_JPEG_16M_COLORS:
355     {
356       maskMethod = MASK_16M_COLORS;
357 
358       break;
359     }
360     default:
361     {
362       delete [] tmpBuf;
363 
364       return -1;
365     }
366   }
367 
368   const T_colormask *colorMask = MethodColorMask(maskMethod);
369 
370   unsigned char *dstBuff = dstData;
371 
372   switch (dstBpp)
373   {
374     case 16:
375     {
376       Unpack16To16(colorMask, dstBuff, dstBuff, dstBuff + dstSize);
377 
378       break;
379     }
380     case 24:
381     {
382       break;
383     }
384     case 32:
385     {
386       Unpack32To32(colorMask, (unsigned int *) dstBuff, (unsigned int *) dstBuff,
387                        (unsigned int *) (dstBuff + dstSize));
388       break;
389     }
390     default:
391     {
392       delete [] tmpBuf;
393 
394       return -1;
395     }
396   }
397 
398   delete [] tmpBuf;
399 
400   return 1;
401 }
402 
403 //
404 // Functions that actually do the Jpeg decompression.
405 //
406 
DecompressJpeg16(unsigned char * compressedData,int compressedLen,unsigned int w,unsigned int h,unsigned char * dstBuf,int byteOrder)407 int DecompressJpeg16(unsigned char *compressedData, int compressedLen,
408                          unsigned int w, unsigned int h, unsigned char *dstBuf, int byteOrder)
409 {
410   struct jpeg_decompress_struct cinfo;
411   struct jpeg_error_mgr jerr;
412   unsigned char *data;
413   JSAMPROW rowPointer[1];
414 
415   unsigned int dx = 0;
416   unsigned int dy = 0;
417 
418   #ifdef DEBUG
419   *logofs << "DecompressJpeg16: Decompressing with length "
420           << compressedLen << " width " << w << " height "
421           << h << ".\n" << logofs_flush;
422   #endif
423 
424   jpegError = 0;
425 
426   cinfo.err = jpeg_std_error(&jerr);
427 
428   jerr.error_exit = UnpackJpegErrorHandler;
429 
430   if (setjmp(UnpackJpegContext) == 1)
431   {
432     #ifdef TEST
433     *logofs << "DecompressJpeg16: Out of the long jump with error '"
434             << jpegError << "'.\n" << logofs_flush;
435     #endif
436 
437     goto AbortDecompressJpeg16;
438   }
439 
440   jpeg_create_decompress(&cinfo);
441 
442   if (jpegError) goto AbortDecompressJpeg16;
443 
444   JpegSetSrcManager(&cinfo, compressedData, compressedLen);
445 
446   jpeg_read_header(&cinfo, TRUE);
447 
448   if (jpegError) goto AbortDecompressJpeg16;
449 
450   cinfo.out_color_space = JCS_RGB;
451 
452   jpeg_start_decompress(&cinfo);
453 
454   if (jpegError) goto AbortDecompressJpeg16;
455 
456   if (cinfo.output_width != w ||
457           cinfo.output_height != h ||
458               cinfo.output_components != 3)
459   {
460     #ifdef PANIC
461     *logofs << "DecompressJpeg16: PANIC! Wrong JPEG data received.\n"
462             << logofs_flush;
463     #endif
464 
465     jpeg_destroy_decompress(&cinfo);
466 
467     return -1;
468   }
469 
470   //
471   // PixelPtr points to dstBuf which is
472   // already padded correctly for the final
473   // image to put
474   //
475 
476   data = dstBuf;
477 
478   rowPointer[0] = (JSAMPROW) tmpBuf;
479 
480   unsigned long pixel;
481 
482   while (cinfo.output_scanline < cinfo.output_height)
483   {
484     jpeg_read_scanlines(&cinfo, rowPointer, 1);
485 
486     if (jpegError) goto AbortDecompressJpeg16;
487 
488     for (dx = 0; dx < w; dx++)
489     {
490       pixel = RGB24_TO_PIXEL(16, tmpBuf[dx * 3], tmpBuf[dx * 3 + 1],
491                                  tmpBuf[dx * 3 + 2]);
492 
493       //
494       // Follow the server byte order when arranging data.
495       //
496 
497       if (byteOrder == LSBFirst)
498       {
499         data[0] = (unsigned char) (pixel & 0xff);
500         data[1] = (unsigned char) ((pixel >> 8) & 0xff);
501       }
502       else
503       {
504         data[1] = (unsigned char) (pixel & 0xff);
505         data[0] = (unsigned char) ((pixel >> 8) & 0xff);
506       }
507 
508       data += 2;
509     }
510 
511     //
512     // Move data at the beginning of the
513     // next line.
514     //
515 
516     data = data + (RoundUp4(w * 2) - w * 2);
517 
518     dy++;
519   }
520 
521   AbortDecompressJpeg16:
522 
523   if (jpegError == 0)
524   {
525     jpeg_finish_decompress(&cinfo);
526   }
527 
528   jpeg_destroy_decompress(&cinfo);
529 
530   if (jpegError == 1)
531   {
532     #ifdef PANIC
533     *logofs << "DecompressJpeg16: Failed to decompress JPEG image.\n"
534             << logofs_flush;
535     #endif
536 
537     return -1;
538   }
539 
540   #ifdef TEST
541   *logofs << "DecompressJpeg16: Decompression finished with "
542           << dy << " lines handled.\n" << logofs_flush;
543   #endif
544 
545   return 1;
546 }
547 
DecompressJpeg24(unsigned char * compressedData,int compressedLen,unsigned int w,unsigned int h,unsigned char * dstBuf,int byteOrder)548 int DecompressJpeg24(unsigned char *compressedData, int compressedLen,
549                          unsigned int w, unsigned int h, unsigned char *dstBuf, int byteOrder)
550 {
551   struct jpeg_decompress_struct cinfo;
552   struct jpeg_error_mgr jerr;
553   CARD8 *pixelPtr = NULL;
554   JSAMPROW rowPointer[1];
555 
556   unsigned int dx = 0;
557   unsigned int dy = 0;
558 
559   #ifdef TEST
560   *logofs << "DecompressJpeg24: Decompressing with length "
561           << compressedLen << " width " << w << " height "
562           << h << ".\n" << logofs_flush;
563   #endif
564 
565   jpegError = 0;
566 
567   cinfo.err = jpeg_std_error(&jerr);
568 
569   jerr.error_exit = UnpackJpegErrorHandler;
570 
571   if (setjmp(UnpackJpegContext) == 1)
572   {
573     #ifdef TEST
574     *logofs << "DecompressJpeg24: Out of the long jump with error '"
575             << jpegError << "'.\n" << logofs_flush;
576     #endif
577 
578     goto AbortDecompressJpeg24;
579   }
580 
581   jpeg_create_decompress(&cinfo);
582 
583   if (jpegError) goto AbortDecompressJpeg24;
584 
585   JpegSetSrcManager(&cinfo, compressedData, compressedLen);
586 
587   jpeg_read_header(&cinfo, TRUE);
588 
589   if (jpegError) goto AbortDecompressJpeg24;
590 
591   cinfo.out_color_space = JCS_RGB;
592 
593   jpeg_start_decompress(&cinfo);
594 
595   if (jpegError) goto AbortDecompressJpeg24;
596 
597   if (cinfo.output_width != w ||
598           cinfo.output_height != h ||
599               cinfo.output_components != 3)
600   {
601     #ifdef PANIC
602     *logofs << "DecompressJpeg24: PANIC! Wrong JPEG data received.\n"
603             << logofs_flush;
604     #endif
605 
606     jpeg_destroy_decompress(&cinfo);
607 
608     return -1;
609   }
610 
611   //
612   // PixelPtr points to dstBuf which is
613   // already padded correctly for the final
614   // image to put.
615   //
616 
617   pixelPtr = (CARD8 *) dstBuf;
618 
619   rowPointer[0] = (JSAMPROW) tmpBuf;
620 
621   while (cinfo.output_scanline < cinfo.output_height)
622   {
623     jpeg_read_scanlines(&cinfo, rowPointer, 1);
624 
625     if (jpegError) goto AbortDecompressJpeg24;
626 
627     for (dx = 0; dx < w; dx++)
628     {
629       //
630       // Follow the server byte order when arranging data.
631       //
632 
633       if (byteOrder == LSBFirst)
634       {
635         pixelPtr[0] = tmpBuf[dx * 3];
636         pixelPtr[1] = tmpBuf[dx * 3 + 1];
637         pixelPtr[2] = tmpBuf[dx * 3 + 2];
638       }
639       else
640       {
641         pixelPtr[2] = tmpBuf[dx * 3];
642         pixelPtr[1] = tmpBuf[dx * 3 + 1];
643         pixelPtr[0] = tmpBuf[dx * 3 + 2];
644       }
645 
646       pixelPtr += 3;
647     }
648 
649     //
650     // Go to the next line.
651     //
652 
653     pixelPtr = (CARD8 *) (((char *) pixelPtr) + (RoundUp4(w * 3) - w * 3));
654 
655     dy++;
656   }
657 
658   AbortDecompressJpeg24:
659 
660   if (jpegError == 0)
661   {
662     jpeg_finish_decompress(&cinfo);
663   }
664 
665   jpeg_destroy_decompress(&cinfo);
666 
667   if (jpegError == 1)
668   {
669     #ifdef PANIC
670     *logofs << "DecompressJpeg24: Failed to decompress JPEG image.\n"
671             << logofs_flush;
672     #endif
673 
674     return -1;
675   }
676 
677   #ifdef TEST
678   *logofs << "DecompressJpeg24: Decompression finished with "
679           << dy << " lines handled.\n" << logofs_flush;
680   #endif
681 
682   return 1;
683 }
684 
DecompressJpeg32(unsigned char * compressedData,int compressedLen,unsigned int w,unsigned int h,unsigned char * dstBuf,int byteOrder)685 int DecompressJpeg32(unsigned char *compressedData, int compressedLen,
686                          unsigned int w, unsigned int h, unsigned char *dstBuf, int byteOrder)
687 {
688   struct jpeg_decompress_struct cinfo;
689   struct jpeg_error_mgr jerr;
690   unsigned char *data;
691   JSAMPROW rowPointer[1];
692 
693   unsigned int dx = 0;
694   unsigned int dy = 0;
695 
696   #ifdef TEST
697   *logofs << "DecompressJpeg32: Decompressing with length "
698           << compressedLen << " width " << w << " height "
699           << h << ".\n" << logofs_flush;
700   #endif
701 
702   jpegError = 0;
703 
704   cinfo.err = jpeg_std_error(&jerr);
705 
706   jerr.error_exit = UnpackJpegErrorHandler;
707 
708   if (setjmp(UnpackJpegContext) == 1)
709   {
710     #ifdef TEST
711     *logofs << "DecompressJpeg32: Out of the long jump with error '"
712             << jpegError << "'.\n" << logofs_flush;
713     #endif
714 
715     goto AbortDecompressJpeg32;
716   }
717 
718   jpeg_create_decompress(&cinfo);
719 
720   if (jpegError) goto AbortDecompressJpeg32;
721 
722   JpegSetSrcManager(&cinfo, compressedData, compressedLen);
723 
724   jpeg_read_header(&cinfo, TRUE);
725 
726   if (jpegError) goto AbortDecompressJpeg32;
727 
728   cinfo.out_color_space = JCS_RGB;
729 
730   jpeg_start_decompress(&cinfo);
731 
732   if (jpegError) goto AbortDecompressJpeg32;
733 
734   if (cinfo.output_width != w ||
735           cinfo.output_height != h ||
736               cinfo.output_components != 3)
737   {
738     #ifdef PANIC
739     *logofs << "DecompressJpeg32 : PANIC! Wrong JPEG data received.\n"
740             << logofs_flush;
741     #endif
742 
743     jpeg_destroy_decompress(&cinfo);
744 
745     return -1;
746   }
747 
748   //
749   // PixelPtr points to dstBuf which is
750   // already padded correctly for the final
751   // image to put
752   //
753 
754   data = dstBuf;
755 
756   rowPointer[0] = (JSAMPROW) tmpBuf;
757 
758   unsigned long pixel;
759 
760   int i;
761 
762   while (cinfo.output_scanline < cinfo.output_height)
763   {
764     jpeg_read_scanlines(&cinfo, rowPointer, 1);
765 
766     if (jpegError) goto AbortDecompressJpeg32;
767 
768     for (dx = 0; dx < w; dx++)
769     {
770       pixel = RGB24_TO_PIXEL(32, tmpBuf[dx * 3], tmpBuf[dx * 3 + 1],
771                                  tmpBuf[dx * 3 + 2]);
772 
773       //
774       // Follow the server byte order when arranging data.
775       //
776 
777       if (byteOrder == LSBFirst)
778       {
779         for (i = 0; i < 4; i++)
780         {
781           data[i] = (unsigned char)(pixel & 0xff);
782           pixel >>= 8;
783         }
784       }
785       else
786       {
787         for (i = 3; i >= 0; i--)
788         {
789           data[i] = (unsigned char) (pixel & 0xff);
790           pixel >>= 8;
791         }
792       }
793 
794       data += 4;
795     }
796 
797     dy++;
798   }
799 
800   AbortDecompressJpeg32:
801 
802   if (jpegError == 0)
803   {
804     jpeg_finish_decompress(&cinfo);
805   }
806 
807   jpeg_destroy_decompress(&cinfo);
808 
809   if (jpegError == 1)
810   {
811     #ifdef PANIC
812     *logofs << "DecompressJpeg32: Failed to decompress JPEG image.\n"
813             << logofs_flush;
814     #endif
815 
816     return -1;
817   }
818 
819   #ifdef TEST
820   *logofs << "DecompressJpeg32: Decompression finished with "
821           << dy << " lines handled.\n" << logofs_flush;
822   #endif
823 
824   return 1;
825 }
826 
JpegInitSource(j_decompress_ptr cinfo)827 static void JpegInitSource(j_decompress_ptr cinfo)
828 {
829   jpegError = 0;
830 }
831 
JpegFillInputBuffer(j_decompress_ptr cinfo)832 static boolean JpegFillInputBuffer(j_decompress_ptr cinfo)
833 {
834   jpegError = 1;
835 
836   jpegSrcManager.bytes_in_buffer = jpegBufferLen;
837   jpegSrcManager.next_input_byte = (JOCTET *)jpegBufferPtr;
838 
839   return TRUE;
840 }
841 
JpegSkipInputData(j_decompress_ptr cinfo,long num_bytes)842 static void JpegSkipInputData(j_decompress_ptr cinfo, long num_bytes)
843 {
844   if (num_bytes < 0 || (unsigned long) num_bytes > jpegSrcManager.bytes_in_buffer)
845   {
846     jpegError = 1;
847 
848     jpegSrcManager.bytes_in_buffer = jpegBufferLen;
849     jpegSrcManager.next_input_byte = (JOCTET *)jpegBufferPtr;
850   }
851   else
852   {
853     jpegSrcManager.next_input_byte += (size_t) num_bytes;
854     jpegSrcManager.bytes_in_buffer -= (size_t) num_bytes;
855   }
856 }
857 
JpegTermSource(j_decompress_ptr cinfo)858 static void JpegTermSource(j_decompress_ptr cinfo)
859 {
860 }
861 
JpegSetSrcManager(j_decompress_ptr cinfo,CARD8 * compressedData,int compressedLen)862 static void JpegSetSrcManager(j_decompress_ptr cinfo,
863                                   CARD8 *compressedData,
864                                       int compressedLen)
865 {
866   jpegBufferPtr = (JOCTET *) compressedData;
867   jpegBufferLen = (size_t) compressedLen;
868 
869   jpegSrcManager.init_source       = JpegInitSource;
870   jpegSrcManager.fill_input_buffer = JpegFillInputBuffer;
871   jpegSrcManager.skip_input_data   = JpegSkipInputData;
872   jpegSrcManager.resync_to_restart = jpeg_resync_to_restart;
873   jpegSrcManager.term_source       = JpegTermSource;
874   jpegSrcManager.next_input_byte   = jpegBufferPtr;
875   jpegSrcManager.bytes_in_buffer   = jpegBufferLen;
876 
877   cinfo->src = &jpegSrcManager;
878 }
879