Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : : #include <stdio.h>
21 : : #include <stdlib.h>
22 : : #include "setjmp.h"
23 : : #include "jpeglib.h"
24 : : #include "jerror.h"
25 : : #include "jpeg.h"
26 : : #include "rtl/alloc.h"
27 : : #include "osl/diagnose.h"
28 : :
29 : : struct my_error_mgr
30 : : {
31 : : struct jpeg_error_mgr pub;
32 : : jmp_buf setjmp_buffer;
33 : : };
34 : :
35 : : void jpeg_svstream_src (j_decompress_ptr cinfo, void* infile);
36 : : void jpeg_svstream_dest (j_compress_ptr cinfo, void* outfile);
37 : :
38 : : METHODDEF( void )
39 : 20 : my_error_exit (j_common_ptr cinfo)
40 : : {
41 : 20 : my_error_ptr myerr = (my_error_ptr) cinfo->err;
42 : 20 : (*cinfo->err->output_message) (cinfo);
43 : 20 : longjmp(myerr->setjmp_buffer, 1);
44 : : }
45 : :
46 : :
47 : : METHODDEF( void )
48 : 45 : my_output_message (j_common_ptr cinfo)
49 : : {
50 : : char buffer[JMSG_LENGTH_MAX];
51 : 45 : (*cinfo->err->format_message) (cinfo, buffer);
52 : 45 : }
53 : :
54 : : /* TODO: when incompatible changes are possible again
55 : : the preview size hint should be redone */
56 : : static int nPreviewWidth = 0;
57 : : static int nPreviewHeight = 0;
58 : 42 : void SetJpegPreviewSizeHint( int nWidth, int nHeight )
59 : : {
60 : 42 : nPreviewWidth = nWidth;
61 : 42 : nPreviewHeight = nHeight;
62 : 42 : }
63 : :
64 : 42 : void ReadJPEG( void* pJPEGReader, void* pIStm, long* pLines )
65 : : {
66 : : struct jpeg_decompress_struct cinfo;
67 : : struct my_error_mgr jerr;
68 : : struct JPEGCreateBitmapParam aCreateBitmapParam;
69 : : HPBYTE pDIB;
70 : : HPBYTE pTmp;
71 : : long nWidth;
72 : : long nHeight;
73 : : long nAlignedWidth;
74 : : JSAMPLE * range_limit;
75 : 42 : HPBYTE pScanLineBuffer = NULL;
76 : 42 : long nScanLineBufferComponents = 0;
77 : : // declare bDecompCreated volatile because of gcc
78 : : // warning: variable 'bDecompCreated' might be clobbered by `longjmp' or `vfork'
79 : 42 : volatile long bDecompCreated = 0;
80 : :
81 : : /* Falls der Stream nicht ausreicht (IO_PENDING)
82 : : wird ueber ein longjmp in der Schleife nach Exit
83 : : gesprungen, wir geben dann die Anzahl
84 : : der bisher bearbeiteten Scanlines zurueck*/
85 [ + + ]: 42 : if ( setjmp( jerr.setjmp_buffer ) )
86 : 20 : goto Exit;
87 : :
88 : 42 : cinfo.err = jpeg_std_error( &jerr.pub );
89 : 42 : jerr.pub.error_exit = my_error_exit;
90 : 42 : jerr.pub.output_message = my_output_message;
91 : :
92 : 42 : jpeg_create_decompress( &cinfo );
93 : 42 : bDecompCreated = 1;
94 : 42 : jpeg_svstream_src( &cinfo, pIStm );
95 : 42 : jpeg_read_header( &cinfo, sal_True );
96 : :
97 : 37 : cinfo.scale_num = 1;
98 : 37 : cinfo.scale_denom = 1;
99 : 37 : cinfo.output_gamma = 1.0;
100 : 37 : cinfo.raw_data_out = sal_False;
101 : 37 : cinfo.quantize_colors = sal_False;
102 [ + - ]: 37 : if ( cinfo.jpeg_color_space == JCS_YCbCr )
103 : 37 : cinfo.out_color_space = JCS_RGB;
104 [ # # ]: 0 : else if ( cinfo.jpeg_color_space == JCS_YCCK )
105 : 0 : cinfo.out_color_space = JCS_CMYK;
106 : :
107 : : OSL_ASSERT(cinfo.out_color_space == JCS_CMYK || cinfo.out_color_space == JCS_GRAYSCALE || cinfo.out_color_space == JCS_RGB);
108 : :
109 : : /* change scale for preview import */
110 [ + - ][ - + ]: 37 : if( nPreviewWidth || nPreviewHeight )
111 : : {
112 [ # # ]: 0 : if( nPreviewWidth == 0 ) {
113 : 0 : nPreviewWidth = ( cinfo.image_width*nPreviewHeight )/cinfo.image_height;
114 [ # # ]: 0 : if( nPreviewWidth <= 0 )
115 : 0 : nPreviewWidth = 1;
116 [ # # ]: 0 : } else if( nPreviewHeight == 0 ) {
117 : 0 : nPreviewHeight = ( cinfo.image_height*nPreviewWidth )/cinfo.image_width;
118 [ # # ]: 0 : if( nPreviewHeight <= 0 )
119 : 0 : nPreviewHeight = 1;
120 : : }
121 : :
122 [ # # ]: 0 : for( cinfo.scale_denom = 1; cinfo.scale_denom < 8; cinfo.scale_denom *= 2 )
123 : : {
124 [ # # ]: 0 : if( cinfo.image_width < nPreviewWidth * cinfo.scale_denom )
125 : 0 : break;
126 [ # # ]: 0 : if( cinfo.image_height < nPreviewHeight * cinfo.scale_denom )
127 : 0 : break;
128 : : }
129 : :
130 [ # # ]: 0 : if( cinfo.scale_denom > 1 )
131 : : {
132 : 0 : cinfo.dct_method = JDCT_FASTEST;
133 : 0 : cinfo.do_fancy_upsampling = sal_False;
134 : 0 : cinfo.do_block_smoothing = sal_False;
135 : : }
136 : : }
137 : :
138 : 37 : jpeg_start_decompress( &cinfo );
139 : :
140 : 27 : nWidth = cinfo.output_width;
141 : 27 : nHeight = cinfo.output_height;
142 : 27 : aCreateBitmapParam.nWidth = nWidth;
143 : 27 : aCreateBitmapParam.nHeight = nHeight;
144 : :
145 : 27 : aCreateBitmapParam.density_unit = cinfo.density_unit;
146 : 27 : aCreateBitmapParam.X_density = cinfo.X_density;
147 : 27 : aCreateBitmapParam.Y_density = cinfo.Y_density;
148 : 27 : aCreateBitmapParam.bGray = cinfo.output_components == 1;
149 : 27 : pDIB = CreateBitmap( pJPEGReader, &aCreateBitmapParam );
150 : 27 : nAlignedWidth = aCreateBitmapParam.nAlignedWidth;
151 : 27 : range_limit=cinfo.sample_range_limit;
152 : :
153 [ - + ]: 27 : if ( cinfo.out_color_space == JCS_CMYK )
154 : : {
155 : 0 : nScanLineBufferComponents = cinfo.output_width * 4;
156 : 0 : pScanLineBuffer = rtl_allocateMemory( nScanLineBufferComponents );
157 : : }
158 : :
159 [ + - ]: 27 : if( pDIB )
160 : : {
161 [ + - ]: 27 : if( aCreateBitmapParam.bTopDown )
162 : 27 : pTmp = pDIB;
163 : : else
164 : : {
165 : 0 : pTmp = pDIB + ( nHeight - 1 ) * nAlignedWidth;
166 : 0 : nAlignedWidth = -nAlignedWidth;
167 : : }
168 : :
169 [ + + ]: 1355 : for ( *pLines = 0; *pLines < nHeight; (*pLines)++ )
170 : : {
171 [ - + ]: 1328 : if (pScanLineBuffer!=NULL) { // in other words cinfo.out_color_space == JCS_CMYK
172 : : int i;
173 : : int j;
174 : 0 : jpeg_read_scanlines( &cinfo, (JSAMPARRAY) &pScanLineBuffer, 1 );
175 : : // convert CMYK to RGB
176 [ # # ]: 0 : for( i=0, j=0; i < nScanLineBufferComponents; i+=4, j+=3 )
177 : : {
178 : 0 : int c_=255-pScanLineBuffer[i+0];
179 : 0 : int m_=255-pScanLineBuffer[i+1];
180 : 0 : int y_=255-pScanLineBuffer[i+2];
181 : 0 : int k_=255-pScanLineBuffer[i+3];
182 : 0 : pTmp[j+0]=range_limit[ 255L - ( c_ + k_ ) ];
183 : 0 : pTmp[j+1]=range_limit[ 255L - ( m_ + k_ ) ];
184 : 0 : pTmp[j+2]=range_limit[ 255L - ( y_ + k_ ) ];
185 : : }
186 : : } else {
187 : 1328 : jpeg_read_scanlines( &cinfo, (JSAMPARRAY) &pTmp, 1 );
188 : : }
189 : : /* PENDING ??? */
190 [ - + ]: 1328 : if ( cinfo.err->msg_code == 113 )
191 : 0 : break;
192 : :
193 : 1328 : pTmp += nAlignedWidth;
194 : : }
195 : : }
196 : :
197 : 27 : jpeg_finish_decompress( &cinfo );
198 [ - + ]: 22 : if (pScanLineBuffer!=NULL) {
199 : 0 : rtl_freeMemory( pScanLineBuffer );
200 : 0 : pScanLineBuffer=NULL;
201 : : }
202 : :
203 : : Exit:
204 : :
205 [ + - ]: 42 : if( bDecompCreated )
206 : 42 : jpeg_destroy_decompress( &cinfo );
207 : 42 : }
208 : :
209 : 0 : long WriteJPEG( void* pJPEGWriter, void* pOStm,
210 : : long nWidth, long nHeight, long bGreys,
211 : : long nQualityPercent, void* pCallbackData )
212 : : {
213 : : struct jpeg_compress_struct cinfo;
214 : : struct my_error_mgr jerr;
215 : : void* pScanline;
216 : : long nY;
217 : : // declare bCompCreated, bRet volatile because of gcc
218 : : // warning: variable 'bCompCreated' might be clobbered by `longjmp' or `vfork'
219 : 0 : volatile long bCompCreated = 0;
220 : 0 : volatile long bRet = 0;
221 : :
222 [ # # ]: 0 : if ( setjmp( jerr.setjmp_buffer ) )
223 : 0 : goto Exit;
224 : :
225 : 0 : cinfo.err = jpeg_std_error( &jerr.pub );
226 : 0 : jerr.pub.error_exit = my_error_exit;
227 : 0 : jerr.pub.output_message = my_output_message;
228 : :
229 : 0 : jpeg_create_compress( &cinfo );
230 : 0 : bCompCreated = 1;
231 : :
232 : 0 : jpeg_svstream_dest( &cinfo, pOStm );
233 : :
234 : 0 : cinfo.image_width = (JDIMENSION) nWidth;
235 : 0 : cinfo.image_height = (JDIMENSION) nHeight;
236 [ # # ]: 0 : if ( bGreys )
237 : : {
238 : 0 : cinfo.input_components = 1;
239 : 0 : cinfo.in_color_space = JCS_GRAYSCALE;
240 : : }
241 : : else
242 : : {
243 : 0 : cinfo.input_components = 3;
244 : 0 : cinfo.in_color_space = JCS_RGB;
245 : : }
246 : :
247 : 0 : jpeg_set_defaults( &cinfo );
248 : 0 : jpeg_set_quality( &cinfo, (int) nQualityPercent, sal_False );
249 : :
250 [ # # ][ # # ]: 0 : if ( ( nWidth > 128 ) || ( nHeight > 128 ) )
251 : 0 : jpeg_simple_progression( &cinfo );
252 : :
253 : 0 : jpeg_start_compress( &cinfo, sal_True );
254 : :
255 [ # # ]: 0 : for( nY = 0; nY < nHeight; nY++ )
256 : : {
257 : 0 : pScanline = GetScanline( pJPEGWriter, nY );
258 : :
259 [ # # ]: 0 : if( pScanline )
260 : 0 : jpeg_write_scanlines( &cinfo, (JSAMPARRAY) &pScanline, 1 );
261 : :
262 [ # # ]: 0 : if( JPEGCallback( pCallbackData, nY * 100L / nHeight ) )
263 : 0 : goto Exit;
264 : : }
265 : :
266 : 0 : bRet = 1;
267 : :
268 : 0 : jpeg_finish_compress(&cinfo);
269 : :
270 : : Exit:
271 : :
272 [ # # ]: 0 : if ( bCompCreated )
273 : 0 : jpeg_destroy_compress( &cinfo );
274 : :
275 : 0 : return bRet;
276 : : }
277 : :
278 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|