1
/*****************************************************************************\
2
ModeJpeg.cpp : Jpeg compressor implementation
4
Copyright (c) 1996 - 2009, Hewlett-Packard Co.
7
Redistribution and use in source and binary forms, with or without
8
modification, are permitted provided that the following conditions
10
1. Redistributions of source code must retain the above copyright
11
notice, this list of conditions and the following disclaimer.
12
2. Redistributions in binary form must reproduce the above copyright
13
notice, this list of conditions and the following disclaimer in the
14
documentation and/or other materials provided with the distribution.
15
3. Neither the name of Hewlett-Packard nor the names of its
16
contributors may be used to endorse or promote products derived
17
from this software without specific prior written permission.
19
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
20
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
22
NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24
TO, PATENT INFRINGEMENT; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
\*****************************************************************************/
31
#include "CommonDefinitions.h"
37
#define MAX_JPEG_FILE_SIZE 2097152 // 2 Mgabytes
41
int (*HPLJJRCompress) (BYTE *pCompressedData,
42
uint32_t *pCompressedDataLen,
44
const uint32_t uiLogicalImageWidth,
45
const uint32_t uiLogicalImageHeight);
48
ModeJpeg::ModeJpeg(unsigned int raster_width) : Compressor (raster_width, false)
50
m_eCompressor = COMPRESSOR_JPEG_QUICKCONNECT;
52
m_max_file_size = MAX_JPEG_FILE_SIZE;;
54
m_iRowWidth = (int) raster_width * 3;
57
m_uiGrayscaleOffset = 0;
58
m_pbyInputBuffer = NULL;
59
m_hHPLibHandle = NULL;
62
// Don't need originalKData buffer allocate by Compressor, delete it
65
delete [] originalKData;
70
DRIVER_ERROR ModeJpeg::Init(int max_file_size, int page_height)
72
int buffer_size = m_iRowWidth * (page_height + 2);
73
m_pbyInputBuffer = new BYTE[buffer_size];
74
if (m_pbyInputBuffer == NULL)
76
return ALLOCMEM_ERROR;
78
if (max_file_size > 0)
80
m_max_file_size = (unsigned int) max_file_size;
82
compressBuf = new BYTE[m_max_file_size];
83
if (compressBuf == NULL)
85
return ALLOCMEM_ERROR;
87
m_iBandHeight = page_height;
91
DRIVER_ERROR ModeJpeg::Init(int color_mode, int band_height, COMPRESS_MODE *eCompressMode, QTableInfo *qtable_info)
94
m_iColorMode = color_mode;
95
m_pQTableInfo = qtable_info;
96
int buf_size = band_height * m_iRowWidth;
97
err = Init(buf_size, band_height);
103
// If plugin is not available or the plugin does not contain Taos compressor, stay with JPEG compression
104
m_eCompressor = COMPRESSOR_JPEG_JETREADY;
105
if (*eCompressMode == COMPRESS_MODE_LJ)
107
m_hHPLibHandle = LoadPlugin ("lj.so");
111
*(void **) (&HPLJJRCompress) = dlsym (m_hHPLibHandle, "HPJetReadyCompress");
112
if (HPLJJRCompress == NULL)
114
dlclose(m_hHPLibHandle);
115
m_hHPLibHandle = NULL;
116
*eCompressMode = COMPRESS_MODE_JPEG;
120
m_eCompressor = COMPRESSOR_TAOS;
127
ModeJpeg::~ModeJpeg()
131
dlclose(m_hHPLibHandle);
133
if (m_pbyInputBuffer)
135
delete [] m_pbyInputBuffer;
139
void ModeJpeg::Flush()
141
if (m_iRowNumber > 0)
147
#define RGBTOGRAY(rgb) (BYTE) ((rgb[0] * 30 + rgb[1] * 59 + rgb[2] * 11) / 100)
148
void ModeJpeg::rgbToGray(BYTE *rgbData, int iNumBytes)
150
if (m_eCompressor == COMPRESSOR_TAOS)
152
BYTE *p = m_pbyInputBuffer + (m_iRowNumber * m_iRowWidth);
153
for (int i = 0; i < iNumBytes; i += 3, rgbData += 3)
155
*p++ = RGBTOGRAY(rgbData);
161
BYTE *p = m_pbyInputBuffer + (m_iRowNumber * m_iRowWidth / 3);
162
for (int i = 0; i < iNumBytes; i += 3, rgbData += 3)
164
*p++ = 255 - RGBTOGRAY(rgbData);
168
bool ModeJpeg::Process(RASTERDATA *input)
174
if (input->rasterdata[COLORTYPE_COLOR])
176
if (m_iColorMode == 0)
178
memcpy(m_pbyInputBuffer + (m_iRowNumber * m_iRowWidth), input->rasterdata[COLORTYPE_COLOR],
179
input->rastersize[COLORTYPE_COLOR]);
183
rgbToGray(input->rasterdata[COLORTYPE_COLOR], input->rastersize[COLORTYPE_COLOR]);
187
if (m_iRowNumber == m_iBandHeight)
195
bool ModeJpeg::NextOutputRaster (RASTERDATA &next_raster)
197
if (iRastersReady == 0)
201
if (myplane == COLORTYPE_COLOR && compressedsize != 0)
203
next_raster.rastersize[COLORTYPE_COLOR] = compressedsize - m_uiGrayscaleOffset;
204
next_raster.rasterdata[COLORTYPE_COLOR] = compressBuf + m_uiGrayscaleOffset;
208
next_raster.rastersize[COLORTYPE_COLOR] = 0;
209
next_raster.rasterdata[COLORTYPE_COLOR] = NULL;
211
next_raster.rastersize[COLORTYPE_BLACK] = 0;
212
next_raster.rasterdata[COLORTYPE_BLACK] = NULL;
215
m_uiGrayscaleOffset = 0;
219
static void output_buffer_callback (JOCTET *outbuf, BYTE *buffer, int size)
221
ModeJpeg *pModeJpeg = (ModeJpeg *) outbuf;
222
pModeJpeg->StoreJpegData (buffer, size);
225
void ModeJpeg::StoreJpegData (BYTE *buffer, int iSize)
227
compressedsize += iSize;
228
if (compressedsize < m_max_file_size)
230
memcpy (compressBuf + compressedsize - iSize, buffer, iSize);
234
compressedsize = m_max_file_size + 1;
238
//----------------------------------------------------------------
239
// These are "overrides" to the JPEG library error routines
240
//----------------------------------------------------------------
242
static void HPJpeg_error (j_common_ptr cinfo)
249
void jpeg_buffer_dest (j_compress_ptr cinfo, JOCTET* outbuff, void* flush_output_buffer_callback);
250
void hp_rgb_ycc_setup (int iFlag);
253
void ModeJpeg::compress ()
255
switch(m_eCompressor)
257
case COMPRESSOR_JPEG_QUICKCONNECT:
259
jpegCompressForQuickConnect();
262
case COMPRESSOR_JPEG_JETREADY:
264
jpegCompressForJetReady();
267
case COMPRESSOR_TAOS:
269
taosCompressForJetReady();
275
memset(m_pbyInputBuffer, 0xFF, m_iRowWidth * m_iBandHeight);
278
void ModeJpeg::jpegCompressForQuickConnect()
284
* Convert the byte buffer to jpg, if converted size is greater than 2MB, delete it and
285
* convert with a higher compression factor.
288
struct jpeg_compress_struct cinfo;
289
struct jpeg_error_mgr jerr;
290
jmp_buf setjmp_buffer;
294
// Use the standard RGB to YCC table rather than the modified one for JetReady
296
hp_rgb_ycc_setup (0);
301
memset (compressBuf, 0xFF, m_max_file_size);
302
p = m_pbyInputBuffer;
304
cinfo.err = jpeg_std_error (&jerr);
305
jerr.error_exit = HPJpeg_error;
306
if (setjmp (setjmp_buffer))
308
jpeg_destroy_compress (&cinfo);
312
jpeg_create_compress (&cinfo);
313
cinfo.in_color_space = JCS_RGB;
314
jpeg_set_defaults (&cinfo);
315
cinfo.image_width = m_iRowWidth / 3;
316
cinfo.image_height = m_iRowNumber;
317
cinfo.input_components = 3;
318
cinfo.data_precision = 8;
319
jpeg_set_quality (&cinfo, iQuality, TRUE);
320
jpeg_buffer_dest (&cinfo, (JOCTET *) this, (void *) (output_buffer_callback));
321
jpeg_start_compress (&cinfo, TRUE);
322
JSAMPROW pRowArray[1];
323
for (int i = 0; i < m_iRowNumber; i++)
325
pRowArray[0] = (JSAMPROW) p;
326
jpeg_write_scanlines (&cinfo, pRowArray, 1);
328
if (compressedsize > m_max_file_size)
334
jpeg_finish_compress (&cinfo);
335
jpeg_destroy_compress (&cinfo);
346
void ModeJpeg::jpegCompressForJetReady()
348
struct jpeg_compress_struct cinfo;
349
struct jpeg_error_mgr jerr;
350
jmp_buf setjmp_buffer;
353
// Use the modified Mojave CSC table
354
hp_rgb_ycc_setup (1);
357
memset (compressBuf, 0xFF, m_max_file_size);
359
cinfo.err = jpeg_std_error (&jerr);
360
jerr.error_exit = HPJpeg_error;
361
if (setjmp (setjmp_buffer))
363
jpeg_destroy_compress (&cinfo);
367
jpeg_create_compress (&cinfo);
368
cinfo.in_color_space = (m_iColorMode == 0) ? JCS_RGB : JCS_GRAYSCALE;
369
jpeg_set_defaults (&cinfo);
370
cinfo.image_width = m_iRowWidth / 3;
371
cinfo.image_height = m_iBandHeight;
372
cinfo.input_components = (m_iColorMode == 0) ? 3 : 1;
373
cinfo.data_precision = 8;
375
// Create a static quant table here.
377
static unsigned int mojave_quant_table1[64] = {
389
// JetReady specific Q-Tables will be added here. We do the following:
390
// 1. Add three Q-Tables.
391
// 2. Scale the Q-Table elemets with the given scale factor.
392
// 3. Check to see if any of the element in the table is greater than 255
393
// reset that elemet to 255.
394
// 5. There is a specific scaling needed to be done to the first 6
395
// elements in the matrix. This is required to achieve better
396
// compression ratio.
397
// 4. Check to see if any the of the recently modified element is
398
// greater than 255, reset that to 255.
400
// Please refer to sRGBLaserHostBasedSoftwareERS.doc v9.0 section 5.2.5.3.1.1
403
// [NOTE] These loop needs to be further optimized.
405
for (int i = 0; i < 3; i++)
409
jpeg_add_quant_table(&cinfo, i, mojave_quant_table1, 0, FALSE );
411
// Scaling the Q-Table elements.
412
// Reset the element to 255, if it is greater than 255.
415
for(int j = 1; j < 64; j++)
417
cinfo.quant_tbl_ptrs[i]->quantval[j] = (UINT16)((mojave_quant_table1[j] * m_pQTableInfo->qFactor) & 0xFF);
418
} // for (int j = 1; j < 64; j++)
421
// Special scaling for first 6 elements in the table.
422
// Reset the specially scaled elements 255, if it is greater than 255.
426
// 1st component in the table. Unchanged, I need not change anything here.
428
cinfo.quant_tbl_ptrs[i]->quantval[0] = (UINT16)mojave_quant_table1[0];
431
// 2nd and 3rd components in the zig zag order
433
// The following dTemp is being used to ceil the vales: e.g 28.5 to 29
435
double dTemp = mojave_quant_table1[1] * (1 + 0.25 * (m_pQTableInfo->qFactor - 1)) + 0.5;
436
cinfo.quant_tbl_ptrs[i]->quantval[1] = (UINT16)dTemp & 0xFF;
438
dTemp = mojave_quant_table1[8] * (1 + 0.25 * (m_pQTableInfo->qFactor - 1)) + 0.5;
439
cinfo.quant_tbl_ptrs[i]->quantval[8] = (UINT16)dTemp & 0xFF;
442
// 4th, 5th and 6th components in the zig zag order
444
dTemp = mojave_quant_table1[16] * (1 + 0.50 * (m_pQTableInfo->qFactor - 1)) + 0.5;
445
cinfo.quant_tbl_ptrs[i]->quantval[16] = (UINT16)dTemp & 0xFF;
447
dTemp = mojave_quant_table1[9] * (1 + 0.50 * (m_pQTableInfo->qFactor - 1)) + 0.5;
448
cinfo.quant_tbl_ptrs[i]->quantval[9] = (UINT16)dTemp & 0xFF;
450
dTemp = mojave_quant_table1[2] * (1 + 0.50 * (m_pQTableInfo->qFactor - 1)) + 0.5;
451
cinfo.quant_tbl_ptrs[i]->quantval[2] = (UINT16)dTemp & 0xFF;
452
} // for (i = 0; i < 3; i++)
454
// Hard code to use sampling mode 4:4:4
456
cinfo.comp_info[0].h_samp_factor = 1;
457
cinfo.comp_info[0].v_samp_factor = 1;
459
jpeg_buffer_dest (&cinfo, (JOCTET *) this, (void *) (output_buffer_callback));
461
int row_width = m_iRowWidth;
462
if (m_iColorMode != 0)
464
row_width = m_iRowWidth / 3;
465
cinfo.write_JFIF_header = FALSE;
466
cinfo.write_Adobe_marker = FALSE;
467
jpeg_suppress_tables(&cinfo, TRUE);
470
jpeg_start_compress (&cinfo, TRUE);
471
JSAMPROW pRowArray[1];
472
BYTE *pScanLine = m_pbyInputBuffer;
474
for (i = 0; i < m_iBandHeight; i++)
476
pRowArray[0] = (JSAMPROW) pScanLine;
477
jpeg_write_scanlines (&cinfo, pRowArray, 1);
478
pScanLine += (row_width);
480
jpeg_finish_compress (&cinfo);
482
// Read the quantization table used for this compression
484
if (cinfo.quant_tbl_ptrs[0] != NULL)
486
// memcpy(m_pQTableInfo->qtable0, cinfo.quant_tbl_ptrs[0]->quantval, QTABLE_SIZE);
487
for (i = 0; i < QTABLE_SIZE; i++)
489
m_pQTableInfo->qtable0[i] = cinfo.quant_tbl_ptrs[0]->quantval[i];
492
if (cinfo.quant_tbl_ptrs[1] != NULL)
494
// memcpy(m_pQTableInfo->qtable1, cinfo.quant_tbl_ptrs[1]->quantval, QTABLE_SIZE);
495
for (i = 0; i < QTABLE_SIZE; i++)
497
m_pQTableInfo->qtable1[i] = cinfo.quant_tbl_ptrs[1]->quantval[i];
500
if (cinfo.quant_tbl_ptrs[2] != NULL)
502
// memcpy(m_pQTableInfo->qtable2, cinfo.quant_tbl_ptrs[2]->quantval, QTABLE_SIZE);
503
for (i = 0; i < QTABLE_SIZE; i++)
505
m_pQTableInfo->qtable2[i] = cinfo.quant_tbl_ptrs[2]->quantval[i];
508
jpeg_destroy_compress (&cinfo);
509
if (m_iColorMode != 0)
512
while (l < compressedsize)
514
if (compressBuf[l] == 0xFF && compressBuf[l+1] == 0xDA)
518
if (l != compressedsize)
520
m_uiGrayscaleOffset = l + 10;
525
void ModeJpeg::taosCompressForJetReady()
528
int bufSize = m_max_file_size;
529
iRet = HPLJJRCompress(compressBuf, (uint32_t *) &bufSize, m_pbyInputBuffer, m_iRowWidth / 3, m_iBandHeight);
530
compressedsize = (iRet < 0) ? 0 : bufSize;