~freenx-team/nx-x11/nxcomp-upstream

« back to all changes in this revision

Viewing changes to Jpeg.cpp

  • Committer: Marcelo Boveto Shima
  • Date: 2009-03-28 22:24:56 UTC
  • Revision ID: mshima@ufserv-20090328222456-rdtaq3oedfyq890c
Import nxcomp 3.3.0-3

Show diffs side-by-side

added added

removed removed

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