fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / vcl / source / filter / jpeg / jpegc.c
blobc05a219dbf009cd95588dda7bed51e221c3a13bd
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <setjmp.h>
23 #include <jpeglib.h>
24 #include <jerror.h>
26 #include <rtl/alloc.h>
27 #include <osl/diagnose.h>
29 #include "transupp.h"
30 #include "jpeg.h"
32 struct ErrorManagerStruct
34 struct jpeg_error_mgr pub;
35 jmp_buf setjmp_buffer;
38 void jpeg_svstream_src (j_decompress_ptr cinfo, void* infile);
39 void jpeg_svstream_dest (j_compress_ptr cinfo, void* outfile);
41 METHODDEF( void ) errorExit (j_common_ptr cinfo)
43 ErrorManagerPointer error = (ErrorManagerPointer) cinfo->err;
44 (*cinfo->err->output_message) (cinfo);
45 longjmp(error->setjmp_buffer, 1);
48 METHODDEF( void ) outputMessage (j_common_ptr cinfo)
50 char buffer[JMSG_LENGTH_MAX];
51 (*cinfo->err->format_message) (cinfo, buffer);
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 void SetJpegPreviewSizeHint( int nWidth, int nHeight )
60 nPreviewWidth = nWidth;
61 nPreviewHeight = nHeight;
64 void ReadJPEG( void* pJPEGReader, void* pInputStream, long* pLines )
66 struct jpeg_decompress_struct cinfo;
67 struct ErrorManagerStruct jerr;
68 struct JPEGCreateBitmapParam aCreateBitmapParam;
69 HPBYTE pDIB;
70 HPBYTE pTmp;
71 long nWidth;
72 long nHeight;
73 long nAlignedWidth;
74 JSAMPLE* aRangeLimit;
75 HPBYTE pScanLineBuffer = NULL;
76 long nScanLineBufferComponents = 0;
78 if ( setjmp( jerr.setjmp_buffer ) )
80 jpeg_destroy_decompress( &cinfo );
81 return;
84 cinfo.err = jpeg_std_error( &jerr.pub );
85 jerr.pub.error_exit = errorExit;
86 jerr.pub.output_message = outputMessage;
88 jpeg_create_decompress( &cinfo );
89 jpeg_svstream_src( &cinfo, pInputStream );
90 jpeg_read_header( &cinfo, TRUE );
92 cinfo.scale_num = 1;
93 cinfo.scale_denom = 1;
94 cinfo.output_gamma = 1.0;
95 cinfo.raw_data_out = FALSE;
96 cinfo.quantize_colors = FALSE;
97 if ( cinfo.jpeg_color_space == JCS_YCbCr )
98 cinfo.out_color_space = JCS_RGB;
99 else if ( cinfo.jpeg_color_space == JCS_YCCK )
100 cinfo.out_color_space = JCS_CMYK;
102 OSL_ASSERT(cinfo.out_color_space == JCS_CMYK || cinfo.out_color_space == JCS_GRAYSCALE || cinfo.out_color_space == JCS_RGB);
104 /* change scale for preview import */
105 if( nPreviewWidth || nPreviewHeight )
107 if( nPreviewWidth == 0 )
109 nPreviewWidth = ( cinfo.image_width * nPreviewHeight ) / cinfo.image_height;
110 if( nPreviewWidth <= 0 )
112 nPreviewWidth = 1;
115 else if( nPreviewHeight == 0 )
117 nPreviewHeight = ( cinfo.image_height * nPreviewWidth ) / cinfo.image_width;
118 if( nPreviewHeight <= 0 )
120 nPreviewHeight = 1;
124 for( cinfo.scale_denom = 1; cinfo.scale_denom < 8; cinfo.scale_denom *= 2 )
126 if( cinfo.image_width < nPreviewWidth * cinfo.scale_denom )
127 break;
128 if( cinfo.image_height < nPreviewHeight * cinfo.scale_denom )
129 break;
132 if( cinfo.scale_denom > 1 )
134 cinfo.dct_method = JDCT_FASTEST;
135 cinfo.do_fancy_upsampling = FALSE;
136 cinfo.do_block_smoothing = FALSE;
140 jpeg_start_decompress( &cinfo );
142 nWidth = cinfo.output_width;
143 nHeight = cinfo.output_height;
144 aCreateBitmapParam.nWidth = nWidth;
145 aCreateBitmapParam.nHeight = nHeight;
147 aCreateBitmapParam.density_unit = cinfo.density_unit;
148 aCreateBitmapParam.X_density = cinfo.X_density;
149 aCreateBitmapParam.Y_density = cinfo.Y_density;
150 aCreateBitmapParam.bGray = cinfo.output_components == 1;
151 pDIB = CreateBitmapFromJPEGReader( pJPEGReader, &aCreateBitmapParam );
152 nAlignedWidth = aCreateBitmapParam.nAlignedWidth;
153 aRangeLimit = cinfo.sample_range_limit;
155 if ( cinfo.out_color_space == JCS_CMYK )
157 nScanLineBufferComponents = cinfo.output_width * 4;
158 pScanLineBuffer = rtl_allocateMemory( nScanLineBufferComponents );
161 if( pDIB )
163 if( aCreateBitmapParam.bTopDown )
165 pTmp = pDIB;
167 else
169 pTmp = pDIB + ( nHeight - 1 ) * nAlignedWidth;
170 nAlignedWidth = -nAlignedWidth;
173 for ( *pLines = 0; *pLines < nHeight; (*pLines)++ )
175 if (pScanLineBuffer != NULL)
176 { // in other words cinfo.out_color_space == JCS_CMYK
177 int i;
178 int j;
179 jpeg_read_scanlines( &cinfo, (JSAMPARRAY) &pScanLineBuffer, 1 );
180 // convert CMYK to RGB
181 for( i=0, j=0; i < nScanLineBufferComponents; i+=4, j+=3 )
183 int color_C = 255 - pScanLineBuffer[i+0];
184 int color_M = 255 - pScanLineBuffer[i+1];
185 int color_Y = 255 - pScanLineBuffer[i+2];
186 int color_K = 255 - pScanLineBuffer[i+3];
187 pTmp[j+0] = aRangeLimit[ 255L - ( color_C + color_K ) ];
188 pTmp[j+1] = aRangeLimit[ 255L - ( color_M + color_K ) ];
189 pTmp[j+2] = aRangeLimit[ 255L - ( color_Y + color_K ) ];
192 else
194 jpeg_read_scanlines( &cinfo, (JSAMPARRAY) &pTmp, 1 );
197 /* PENDING ??? */
198 if ( cinfo.err->msg_code == 113 )
199 break;
201 pTmp += nAlignedWidth;
205 if ( pDIB )
207 jpeg_finish_decompress( &cinfo );
209 else
211 jpeg_abort_decompress( &cinfo );
214 if (pScanLineBuffer != NULL)
216 rtl_freeMemory( pScanLineBuffer );
217 pScanLineBuffer = NULL;
220 jpeg_destroy_decompress( &cinfo );
223 long WriteJPEG( void* pJPEGWriter, void* pOutputStream,
224 long nWidth, long nHeight, long bGreys,
225 long nQualityPercent, long aChromaSubsampling,
226 void* pCallbackData )
228 struct jpeg_compress_struct cinfo;
229 struct ErrorManagerStruct jerr;
230 void* pScanline;
231 long nY;
233 if ( setjmp( jerr.setjmp_buffer ) )
235 jpeg_destroy_compress( &cinfo );
236 return 0;
239 cinfo.err = jpeg_std_error( &jerr.pub );
240 jerr.pub.error_exit = errorExit;
241 jerr.pub.output_message = outputMessage;
243 jpeg_create_compress( &cinfo );
244 jpeg_svstream_dest( &cinfo, pOutputStream );
246 cinfo.image_width = (JDIMENSION) nWidth;
247 cinfo.image_height = (JDIMENSION) nHeight;
248 if ( bGreys )
250 cinfo.input_components = 1;
251 cinfo.in_color_space = JCS_GRAYSCALE;
253 else
255 cinfo.input_components = 3;
256 cinfo.in_color_space = JCS_RGB;
259 jpeg_set_defaults( &cinfo );
260 jpeg_set_quality( &cinfo, (int) nQualityPercent, FALSE );
262 if ( ( nWidth > 128 ) || ( nHeight > 128 ) )
263 jpeg_simple_progression( &cinfo );
265 if (aChromaSubsampling == 1) // YUV 4:4:4
267 cinfo.comp_info[0].h_samp_factor = 1;
268 cinfo.comp_info[0].v_samp_factor = 1;
270 else if (aChromaSubsampling == 2) // YUV 4:2:2
272 cinfo.comp_info[0].h_samp_factor = 2;
273 cinfo.comp_info[0].v_samp_factor = 1;
275 else if (aChromaSubsampling == 3) // YUV 4:2:0
277 cinfo.comp_info[0].h_samp_factor = 2;
278 cinfo.comp_info[0].v_samp_factor = 2;
281 jpeg_start_compress( &cinfo, TRUE );
283 for( nY = 0; nY < nHeight; nY++ )
285 pScanline = GetScanline( pJPEGWriter, nY );
287 if( pScanline )
289 jpeg_write_scanlines( &cinfo, (JSAMPARRAY) &pScanline, 1 );
292 if( JPEGCallback( pCallbackData, nY * 100L / nHeight ) )
294 jpeg_destroy_compress( &cinfo );
295 return 0;
299 jpeg_finish_compress(&cinfo);
300 jpeg_destroy_compress( &cinfo );
302 return 1;
305 long Transform(void* pInputStream, void* pOutputStream, long nAngle)
307 jpeg_transform_info aTransformOption;
308 JCOPY_OPTION aCopyOption = JCOPYOPT_ALL;
310 struct jpeg_decompress_struct aSourceInfo;
311 struct jpeg_compress_struct aDestinationInfo;
312 struct ErrorManagerStruct aSourceError;
313 struct ErrorManagerStruct aDestinationError;
315 jvirt_barray_ptr* aSourceCoefArrays = 0;
316 jvirt_barray_ptr* aDestinationCoefArrays = 0;
318 aTransformOption.force_grayscale = FALSE;
319 aTransformOption.trim = FALSE;
320 aTransformOption.perfect = FALSE;
321 aTransformOption.crop = FALSE;
323 // Angle to transform option
324 // 90 Clockwise = 270 Counterclockwise
325 switch (nAngle)
327 case 2700:
328 aTransformOption.transform = JXFORM_ROT_90;
329 break;
330 case 1800:
331 aTransformOption.transform = JXFORM_ROT_180;
332 break;
333 case 900:
334 aTransformOption.transform = JXFORM_ROT_270;
335 break;
336 default:
337 aTransformOption.transform = JXFORM_NONE;
340 // Decompression
341 aSourceInfo.err = jpeg_std_error(&aSourceError.pub);
342 aSourceInfo.err->error_exit = errorExit;
343 aSourceInfo.err->output_message = outputMessage;
345 // Compression
346 aDestinationInfo.err = jpeg_std_error(&aDestinationError.pub);
347 aDestinationInfo.err->error_exit = errorExit;
348 aDestinationInfo.err->output_message = outputMessage;
350 aDestinationInfo.optimize_coding = TRUE;
352 if (setjmp(aSourceError.setjmp_buffer) || setjmp(aDestinationError.setjmp_buffer))
354 jpeg_destroy_decompress(&aSourceInfo);
355 jpeg_destroy_compress(&aDestinationInfo);
356 return 0;
359 jpeg_create_decompress(&aSourceInfo);
360 jpeg_create_compress(&aDestinationInfo);
362 jpeg_svstream_src (&aSourceInfo, pInputStream);
364 jcopy_markers_setup(&aSourceInfo, aCopyOption);
365 jpeg_read_header(&aSourceInfo, 1);
366 jtransform_request_workspace(&aSourceInfo, &aTransformOption);
368 aSourceCoefArrays = jpeg_read_coefficients(&aSourceInfo);
369 jpeg_copy_critical_parameters(&aSourceInfo, &aDestinationInfo);
371 aDestinationCoefArrays = jtransform_adjust_parameters(&aSourceInfo, &aDestinationInfo, aSourceCoefArrays, &aTransformOption);
372 jpeg_svstream_dest (&aDestinationInfo, pOutputStream);
374 // Compute optimal Huffman coding tables instead of precomuted tables
375 aDestinationInfo.optimize_coding = 1;
376 jpeg_write_coefficients(&aDestinationInfo, aDestinationCoefArrays);
377 jcopy_markers_execute(&aSourceInfo, &aDestinationInfo, aCopyOption);
378 jtransform_execute_transformation(&aSourceInfo, &aDestinationInfo, aSourceCoefArrays, &aTransformOption);
380 jpeg_finish_compress(&aDestinationInfo);
381 jpeg_destroy_compress(&aDestinationInfo);
383 jpeg_finish_decompress(&aSourceInfo);
384 jpeg_destroy_decompress(&aSourceInfo);
386 return 1;
389 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */