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