1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: jpegc.c,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
37 #include "rtl/alloc.h"
38 #include "osl/diagnose.h"
42 struct jpeg_error_mgr pub
;
43 jmp_buf setjmp_buffer
;
46 void jpeg_svstream_src (j_decompress_ptr cinfo
, void* infile
);
47 void jpeg_svstream_dest (j_compress_ptr cinfo
, void* outfile
);
50 my_error_exit (j_common_ptr cinfo
)
52 my_error_ptr myerr
= (my_error_ptr
) cinfo
->err
;
53 (*cinfo
->err
->output_message
) (cinfo
);
54 longjmp(myerr
->setjmp_buffer
, 1);
59 my_output_message (j_common_ptr cinfo
)
61 char buffer
[JMSG_LENGTH_MAX
];
62 (*cinfo
->err
->format_message
) (cinfo
, buffer
);
65 /* TODO: when incompatible changes are possible again
66 the preview size hint should be redone */
67 static int nPreviewWidth
= 0;
68 static int nPreviewHeight
= 0;
69 void SetJpegPreviewSizeHint( int nWidth
, int nHeight
)
71 nPreviewWidth
= nWidth
;
72 nPreviewHeight
= nHeight
;
75 void ReadJPEG( void* pJPEGReader
, void* pIStm
, long* pLines
)
77 struct jpeg_decompress_struct cinfo
;
78 struct my_error_mgr jerr
;
79 struct JPEGCreateBitmapParam aCreateBitmapParam
;
85 JSAMPLE
* range_limit
;
86 HPBYTE pScanLineBuffer
= NULL
;
87 long nScanLineBufferComponents
= 0;
88 // declare bDecompCreated volatile because of gcc
89 // warning: variable 'bDecompCreated' might be clobbered by `longjmp' or `vfork'
90 volatile long bDecompCreated
= 0;
92 /* Falls der Stream nicht ausreicht (IO_PENDING)
93 wird ueber ein longjmp in der Schleife nach Exit
94 gesprungen, wir geben dann die Anzahl
95 der bisher bearbeiteten Scanlines zurueck*/
96 if ( setjmp( jerr
.setjmp_buffer
) )
99 cinfo
.err
= jpeg_std_error( &jerr
.pub
);
100 jerr
.pub
.error_exit
= my_error_exit
;
101 jerr
.pub
.output_message
= my_output_message
;
103 jpeg_create_decompress( &cinfo
);
105 jpeg_svstream_src( &cinfo
, pIStm
);
106 jpeg_read_header( &cinfo
, TRUE
);
109 cinfo
.scale_denom
= 1;
110 cinfo
.output_gamma
= 1.0;
111 cinfo
.raw_data_out
= FALSE
;
112 cinfo
.quantize_colors
= FALSE
;
113 if ( cinfo
.jpeg_color_space
== JCS_YCbCr
)
114 cinfo
.out_color_space
= JCS_RGB
;
115 else if ( cinfo
.jpeg_color_space
== JCS_YCCK
)
116 cinfo
.out_color_space
= JCS_CMYK
;
118 OSL_ASSERT(cinfo
.out_color_space
== JCS_CMYK
|| cinfo
.out_color_space
== JCS_GRAYSCALE
|| cinfo
.out_color_space
== JCS_RGB
);
120 /* change scale for preview import */
121 if( nPreviewWidth
|| nPreviewHeight
)
123 if( nPreviewWidth
== 0 ) {
124 nPreviewWidth
= ( cinfo
.image_width
*nPreviewHeight
)/cinfo
.image_height
;
125 if( nPreviewWidth
<= 0 )
127 } else if( nPreviewHeight
== 0 ) {
128 nPreviewHeight
= ( cinfo
.image_height
*nPreviewWidth
)/cinfo
.image_width
;
129 if( nPreviewHeight
<= 0 )
133 for( cinfo
.scale_denom
= 1; cinfo
.scale_denom
< 8; cinfo
.scale_denom
*= 2 )
135 if( cinfo
.image_width
< nPreviewWidth
* cinfo
.scale_denom
)
137 if( cinfo
.image_height
< nPreviewHeight
* cinfo
.scale_denom
)
141 if( cinfo
.scale_denom
> 1 )
143 cinfo
.dct_method
= JDCT_FASTEST
;
144 cinfo
.do_fancy_upsampling
= FALSE
;
145 cinfo
.do_block_smoothing
= FALSE
;
149 jpeg_start_decompress( &cinfo
);
151 nWidth
= cinfo
.output_width
;
152 nHeight
= cinfo
.output_height
;
153 aCreateBitmapParam
.nWidth
= nWidth
;
154 aCreateBitmapParam
.nHeight
= nHeight
;
156 aCreateBitmapParam
.density_unit
= cinfo
.density_unit
;
157 aCreateBitmapParam
.X_density
= cinfo
.X_density
;
158 aCreateBitmapParam
.Y_density
= cinfo
.Y_density
;
159 aCreateBitmapParam
.bGray
= cinfo
.output_components
== 1;
160 pDIB
= CreateBitmap( pJPEGReader
, &aCreateBitmapParam
);
161 nAlignedWidth
= aCreateBitmapParam
.nAlignedWidth
;
162 range_limit
=cinfo
.sample_range_limit
;
164 if ( cinfo
.out_color_space
== JCS_CMYK
)
166 nScanLineBufferComponents
= cinfo
.output_width
* 4;
167 pScanLineBuffer
= rtl_allocateMemory( nScanLineBufferComponents
);
172 if( aCreateBitmapParam
.bTopDown
)
176 pTmp
= pDIB
+ ( nHeight
- 1 ) * nAlignedWidth
;
177 nAlignedWidth
= -nAlignedWidth
;
180 for ( *pLines
= 0; *pLines
< nHeight
; (*pLines
)++ )
182 if (pScanLineBuffer
!=NULL
) { // in other words cinfo.out_color_space == JCS_CMYK
185 jpeg_read_scanlines( &cinfo
, (JSAMPARRAY
) &pScanLineBuffer
, 1 );
186 // convert CMYK to RGB
187 for( i
=0, j
=0; i
< nScanLineBufferComponents
; i
+=4, j
+=3 )
189 int c_
=255-pScanLineBuffer
[i
+0];
190 int m_
=255-pScanLineBuffer
[i
+1];
191 int y_
=255-pScanLineBuffer
[i
+2];
192 int k_
=255-pScanLineBuffer
[i
+3];
193 pTmp
[j
+0]=range_limit
[ 255L - ( c_
+ k_
) ];
194 pTmp
[j
+1]=range_limit
[ 255L - ( m_
+ k_
) ];
195 pTmp
[j
+2]=range_limit
[ 255L - ( y_
+ k_
) ];
198 jpeg_read_scanlines( &cinfo
, (JSAMPARRAY
) &pTmp
, 1 );
201 if ( cinfo
.err
->msg_code
== 113 )
204 pTmp
+= nAlignedWidth
;
208 jpeg_finish_decompress( &cinfo
);
209 if (pScanLineBuffer
!=NULL
) {
210 rtl_freeMemory( pScanLineBuffer
);
211 pScanLineBuffer
=NULL
;
217 jpeg_destroy_decompress( &cinfo
);
220 long WriteJPEG( void* pJPEGWriter
, void* pOStm
,
221 long nWidth
, long nHeight
,
222 long nQualityPercent
, void* pCallbackData
)
224 struct jpeg_compress_struct cinfo
;
225 struct my_error_mgr jerr
;
228 // declare bCompCreated, bRet volatile because of gcc
229 // warning: variable 'bCompCreated' might be clobbered by `longjmp' or `vfork'
230 volatile long bCompCreated
= 0;
231 volatile long bRet
= 0;
233 if ( setjmp( jerr
.setjmp_buffer
) )
236 cinfo
.err
= jpeg_std_error( &jerr
.pub
);
237 jerr
.pub
.error_exit
= my_error_exit
;
238 jerr
.pub
.output_message
= my_output_message
;
240 jpeg_create_compress( &cinfo
);
243 jpeg_svstream_dest( &cinfo
, pOStm
);
245 cinfo
.image_width
= (JDIMENSION
) nWidth
;
246 cinfo
.image_height
= (JDIMENSION
) nHeight
;
247 cinfo
.input_components
= 3;
248 cinfo
.in_color_space
= JCS_RGB
;
250 jpeg_set_defaults( &cinfo
);
251 jpeg_set_quality( &cinfo
, (int) nQualityPercent
, FALSE
);
253 if ( ( nWidth
> 128 ) || ( nHeight
> 128 ) )
254 jpeg_simple_progression( &cinfo
);
256 jpeg_start_compress( &cinfo
, TRUE
);
258 for( nY
= 0; nY
< nHeight
; nY
++ )
260 pScanline
= GetScanline( pJPEGWriter
, nY
);
263 jpeg_write_scanlines( &cinfo
, (JSAMPARRAY
) &pScanline
, 1 );
265 if( JPEGCallback( pCallbackData
, nY
* 100L / nHeight
) )
271 jpeg_finish_compress(&cinfo
);
276 jpeg_destroy_compress( &cinfo
);