Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <tools/solar.h>
31 : :
32 : : extern "C"
33 : : {
34 : : #include "stdio.h"
35 : : #include "jpeg.h"
36 : : #include "jpeglib.h"
37 : : #include "jerror.h"
38 : : }
39 : :
40 : : #define _JPEGPRIVATE
41 : : #include <vcl/bmpacc.hxx>
42 : : #include "jpeg.hxx"
43 : : #include <svtools/FilterConfigItem.hxx>
44 : : #include <svtools/filter.hxx>
45 : :
46 : : // -----------
47 : : // - Defines -
48 : : // -----------
49 : :
50 : : using namespace ::com::sun::star;
51 : :
52 : : #define JPEGMINREAD 512
53 : :
54 : : // -------------
55 : : // - (C-Calls) -
56 : : // -------------
57 : :
58 : : // ------------------------------------------------------------------------
59 : :
60 : 17 : extern "C" void* CreateBitmap( void* pJPEGReader, void* pJPEGCreateBitmapParam )
61 : : {
62 : 17 : return ( (JPEGReader*) pJPEGReader )->CreateBitmap( pJPEGCreateBitmapParam );
63 : : }
64 : :
65 : : // ------------------------------------------------------------------------
66 : :
67 : 0 : extern "C" void* GetScanline( void* pJPEGWriter, long nY )
68 : : {
69 : 0 : return ( (JPEGWriter*) pJPEGWriter )->GetScanline( nY );
70 : : }
71 : :
72 : : // ------------------------------------------------------------------------
73 : :
74 : 0 : struct JPEGCallbackStruct
75 : : {
76 : : uno::Reference< task::XStatusIndicator > xStatusIndicator;
77 : : };
78 : :
79 : 0 : extern "C" long JPEGCallback( void* pCallbackData, long nPercent )
80 : : {
81 : 0 : JPEGCallbackStruct* pS = (JPEGCallbackStruct*)pCallbackData;
82 [ # # ][ # # ]: 0 : if ( pS && pS->xStatusIndicator.is() )
[ # # ]
83 : : {
84 : 0 : pS->xStatusIndicator->setValue( nPercent );
85 : : }
86 : 0 : return 0L;
87 : : }
88 : :
89 : : #define BUF_SIZE 4096
90 : :
91 : : typedef struct
92 : : {
93 : : struct jpeg_destination_mgr pub; /* public fields */
94 : :
95 : : SvStream* outfile; /* target stream */
96 : : JOCTET * buffer; /* start of buffer */
97 : : } my_destination_mgr;
98 : :
99 : : typedef my_destination_mgr * my_dest_ptr;
100 : :
101 : 0 : extern "C" void init_destination (j_compress_ptr cinfo)
102 : : {
103 : 0 : my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
104 : :
105 : : /* Allocate the output buffer --- it will be released when done with image */
106 : : dest->buffer = (JOCTET *)
107 : : (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
108 : 0 : BUF_SIZE * sizeof(JOCTET));
109 : :
110 : 0 : dest->pub.next_output_byte = dest->buffer;
111 : 0 : dest->pub.free_in_buffer = BUF_SIZE;
112 : 0 : }
113 : :
114 : 0 : extern "C" boolean empty_output_buffer (j_compress_ptr cinfo)
115 : : {
116 : 0 : my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
117 : :
118 [ # # ]: 0 : if (dest->outfile->Write(dest->buffer, BUF_SIZE) !=
119 : : (size_t) BUF_SIZE)
120 : 0 : ERREXIT(cinfo, JERR_FILE_WRITE);
121 : :
122 : 0 : dest->pub.next_output_byte = dest->buffer;
123 : 0 : dest->pub.free_in_buffer = BUF_SIZE;
124 : :
125 : 0 : return sal_True;
126 : : }
127 : :
128 : 0 : extern "C" void term_destination (j_compress_ptr cinfo)
129 : : {
130 : 0 : my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
131 : 0 : size_t datacount = BUF_SIZE - dest->pub.free_in_buffer;
132 : :
133 : : /* Write any data remaining in the buffer */
134 [ # # ]: 0 : if (datacount > 0) {
135 [ # # ]: 0 : if (dest->outfile->Write(dest->buffer, datacount) != datacount)
136 : 0 : ERREXIT(cinfo, JERR_FILE_WRITE);
137 : : }
138 : 0 : }
139 : :
140 : 0 : extern "C" void jpeg_svstream_dest (j_compress_ptr cinfo, void* out)
141 : : {
142 : 0 : SvStream * outfile = (SvStream*)out;
143 : : my_dest_ptr dest;
144 : :
145 : : /* The destination object is made permanent so that multiple JPEG images
146 : : * can be written to the same file without re-executing jpeg_svstream_dest.
147 : : * This makes it dangerous to use this manager and a different destination
148 : : * manager serially with the same JPEG object, because their private object
149 : : * sizes may be different. Caveat programmer.
150 : : */
151 [ # # ]: 0 : if (cinfo->dest == NULL) { /* first time for this JPEG object? */
152 : : cinfo->dest = (struct jpeg_destination_mgr *)
153 : : (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
154 : 0 : sizeof(my_destination_mgr));
155 : : }
156 : :
157 : 0 : dest = (my_dest_ptr) cinfo->dest;
158 : 0 : dest->pub.init_destination = init_destination;
159 : 0 : dest->pub.empty_output_buffer = empty_output_buffer;
160 : 0 : dest->pub.term_destination = term_destination;
161 : 0 : dest->outfile = outfile;
162 : 0 : }
163 : :
164 : : /* Expanded data source object for stdio input */
165 : :
166 : : typedef struct {
167 : : struct jpeg_source_mgr pub; /* public fields */
168 : :
169 : : SvStream * infile; /* source stream */
170 : : JOCTET * buffer; /* start of buffer */
171 : : boolean start_of_file; /* have we gotten any data yet? */
172 : : } my_source_mgr;
173 : :
174 : : typedef my_source_mgr * my_src_ptr;
175 : :
176 : : /*
177 : : * Initialize source --- called by jpeg_read_header
178 : : * before any data is actually read.
179 : : */
180 : :
181 : 26 : extern "C" void init_source (j_decompress_ptr cinfo)
182 : : {
183 : 26 : my_src_ptr src = (my_src_ptr) cinfo->src;
184 : :
185 : : /* We reset the empty-input-file flag for each image,
186 : : * but we don't clear the input buffer.
187 : : * This is correct behavior for reading a series of images from one source.
188 : : */
189 : 26 : src->start_of_file = sal_True;
190 : 26 : }
191 : :
192 : 34 : long StreamRead( SvStream* pSvStm, void* pBuffer, long nBufferSize )
193 : : {
194 : 34 : long nRead = 0;
195 : :
196 [ + - ]: 34 : if( pSvStm->GetError() != ERRCODE_IO_PENDING )
197 : : {
198 : 34 : long nActPos = pSvStm->Tell();
199 : :
200 : 34 : nRead = (long) pSvStm->Read( pBuffer, nBufferSize );
201 : :
202 [ - + ]: 34 : if( pSvStm->GetError() == ERRCODE_IO_PENDING )
203 : : {
204 : : // Damit wir wieder an die alte Position
205 : : // seeken koennen, setzen wir den Error temp.zurueck
206 : 0 : pSvStm->ResetError();
207 : 0 : pSvStm->Seek( nActPos );
208 : 0 : pSvStm->SetError( ERRCODE_IO_PENDING );
209 : : }
210 : : }
211 : :
212 : 34 : return nRead;
213 : : }
214 : :
215 : 34 : extern "C" boolean fill_input_buffer (j_decompress_ptr cinfo)
216 : : {
217 : 34 : my_src_ptr src = (my_src_ptr) cinfo->src;
218 : : size_t nbytes;
219 : :
220 : 34 : nbytes = StreamRead(src->infile, src->buffer, BUF_SIZE);
221 : :
222 [ - + ]: 34 : if (!nbytes) {
223 [ # # ]: 0 : if (src->start_of_file) /* Treat empty input file as fatal error */
224 : 0 : ERREXIT(cinfo, JERR_INPUT_EMPTY);
225 : 0 : WARNMS(cinfo, JWRN_JPEG_EOF);
226 : : /* Insert a fake EOI marker */
227 : 0 : src->buffer[0] = (JOCTET) 0xFF;
228 : 0 : src->buffer[1] = (JOCTET) JPEG_EOI;
229 : 0 : nbytes = 2;
230 : : }
231 : :
232 : 34 : src->pub.next_input_byte = src->buffer;
233 : 34 : src->pub.bytes_in_buffer = nbytes;
234 : 34 : src->start_of_file = sal_False;
235 : :
236 : 34 : return sal_True;
237 : : }
238 : :
239 : 15 : extern "C" void skip_input_data (j_decompress_ptr cinfo, long num_bytes)
240 : : {
241 : 15 : my_src_ptr src = (my_src_ptr) cinfo->src;
242 : :
243 : : /* Just a dumb implementation for now. Could use fseek() except
244 : : * it doesn't work on pipes. Not clear that being smart is worth
245 : : * any trouble anyway --- large skips are infrequent.
246 : : */
247 [ + - ]: 15 : if (num_bytes > 0) {
248 [ + + ]: 21 : while (num_bytes > (long) src->pub.bytes_in_buffer) {
249 : 6 : num_bytes -= (long) src->pub.bytes_in_buffer;
250 : 6 : (void) fill_input_buffer(cinfo);
251 : : /* note we assume that fill_input_buffer will never return sal_False,
252 : : * so suspension need not be handled.
253 : : */
254 : : }
255 : 15 : src->pub.next_input_byte += (size_t) num_bytes;
256 : 15 : src->pub.bytes_in_buffer -= (size_t) num_bytes;
257 : : }
258 : 15 : }
259 : :
260 : 14 : extern "C" void term_source (j_decompress_ptr)
261 : : {
262 : : /* no work necessary here */
263 : 14 : }
264 : :
265 : 26 : extern "C" void jpeg_svstream_src (j_decompress_ptr cinfo, void * in)
266 : : {
267 : : my_src_ptr src;
268 : 26 : SvStream * infile = (SvStream*)in;
269 : :
270 : : /* The source object and input buffer are made permanent so that a series
271 : : * of JPEG images can be read from the same file by calling jpeg_stdio_src
272 : : * only before the first one. (If we discarded the buffer at the end of
273 : : * one image, we'd likely lose the start of the next one.)
274 : : * This makes it unsafe to use this manager and a different source
275 : : * manager serially with the same JPEG object. Caveat programmer.
276 : : */
277 [ + - ]: 26 : if (cinfo->src == NULL) { /* first time for this JPEG object? */
278 : : cinfo->src = (struct jpeg_source_mgr *)
279 : : (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
280 : 26 : sizeof(my_source_mgr));
281 : 26 : src = (my_src_ptr) cinfo->src;
282 : : src->buffer = (JOCTET *)
283 : : (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
284 : 26 : BUF_SIZE * sizeof(JOCTET));
285 : : }
286 : :
287 : 26 : src = (my_src_ptr) cinfo->src;
288 : 26 : src->pub.init_source = init_source;
289 : 26 : src->pub.fill_input_buffer = fill_input_buffer;
290 : 26 : src->pub.skip_input_data = skip_input_data;
291 : 26 : src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
292 : 26 : src->pub.term_source = term_source;
293 : 26 : src->infile = infile;
294 : 26 : src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
295 : 26 : src->pub.next_input_byte = NULL; /* until buffer loaded */
296 : 26 : }
297 : :
298 : : // --------------
299 : : // - JPEGReader -
300 : : // --------------
301 : :
302 : 26 : JPEGReader::JPEGReader( SvStream& rStm, void* /*pCallData*/, sal_Bool bSetLS ) :
303 : : rIStm ( rStm ),
304 : : pAcc ( NULL ),
305 : : pAcc1 ( NULL ),
306 : : pBuffer ( NULL ),
307 : 26 : nLastPos ( rStm.Tell() ),
308 : : nLastLines ( 0 ),
309 [ + - ][ + - ]: 26 : bSetLogSize ( bSetLS )
310 : : {
311 [ + - ]: 26 : maUpperName = rtl::OUString("SVIJPEG");
312 : 26 : nFormerPos = nLastPos;
313 : 26 : }
314 : :
315 : : // ------------------------------------------------------------------------
316 : :
317 [ + - ][ + - ]: 26 : JPEGReader::~JPEGReader()
318 : : {
319 [ - + ]: 26 : if( pBuffer )
320 : 0 : rtl_freeMemory( pBuffer );
321 : :
322 [ - + ]: 26 : if( pAcc )
323 [ # # ]: 0 : aBmp.ReleaseAccess( pAcc );
324 : :
325 [ - + ]: 26 : if( pAcc1 )
326 [ # # ]: 0 : aBmp1.ReleaseAccess( pAcc1 );
327 [ - + ]: 52 : }
328 : :
329 : : // ------------------------------------------------------------------------
330 : :
331 : 17 : void* JPEGReader::CreateBitmap( void* _pParam )
332 : : {
333 : 17 : JPEGCreateBitmapParam *pParam = (JPEGCreateBitmapParam *) _pParam;
334 : :
335 [ + - ][ - + ]: 17 : if (pParam->nWidth > SAL_MAX_INT32/8 || pParam->nHeight > SAL_MAX_INT32/8)
336 : 0 : return NULL; // avoid overflows later
337 : :
338 : 17 : Size aSize( pParam->nWidth, pParam->nHeight );
339 : 17 : sal_Bool bGray = pParam->bGray != 0;
340 : :
341 : 17 : void* pBmpBuf = NULL;
342 : :
343 [ - + ]: 17 : if( pAcc )
344 [ # # ]: 0 : aBmp.ReleaseAccess( pAcc );
345 : :
346 : 17 : sal_uInt64 nSize = aSize.Width();
347 : 17 : nSize *= aSize.Height();
348 [ - + ]: 17 : if (nSize > SAL_MAX_INT32 / 24)
349 : 0 : return NULL;
350 : :
351 [ - + ]: 17 : if( bGray )
352 : : {
353 [ # # ]: 0 : BitmapPalette aGrayPal( 256 );
354 : :
355 [ # # ]: 0 : for( sal_uInt16 n = 0; n < 256; n++ )
356 : : {
357 : 0 : const sal_uInt8 cGray = (sal_uInt8) n;
358 : 0 : aGrayPal[ n ] = BitmapColor( cGray, cGray, cGray );
359 : : }
360 : :
361 [ # # ][ # # ]: 0 : aBmp = Bitmap( aSize, 8, &aGrayPal );
[ # # ]
362 : : }
363 : : else
364 [ + - ][ + - ]: 17 : aBmp = Bitmap( aSize, 24 );
[ + - ]
365 : :
366 [ + - ]: 17 : if ( bSetLogSize )
367 : : {
368 : 17 : unsigned long nUnit = ((JPEGCreateBitmapParam*)pParam)->density_unit;
369 : :
370 [ + + ][ - + ]: 17 : if( ( ( 1 == nUnit ) || ( 2 == nUnit ) ) &&
[ + - ][ + - ]
371 : : pParam->X_density && pParam->Y_density )
372 : : {
373 : 11 : Point aEmptyPoint;
374 [ + - ]: 11 : Fraction aFractX( 1, pParam->X_density );
375 [ + - ]: 11 : Fraction aFractY( 1, pParam->Y_density );
376 [ + - ][ + - ]: 11 : MapMode aMapMode( nUnit == 1 ? MAP_INCH : MAP_CM, aEmptyPoint, aFractX, aFractY );
377 [ + - ][ + - ]: 11 : Size aPrefSize = OutputDevice::LogicToLogic( aSize, aMapMode, MAP_100TH_MM );
[ + - ]
378 : :
379 : 11 : aBmp.SetPrefSize( aPrefSize );
380 [ + - ][ + - ]: 11 : aBmp.SetPrefMapMode( MapMode( MAP_100TH_MM ) );
[ + - ][ + - ]
381 : : }
382 : : }
383 : :
384 [ + - ]: 17 : pAcc = aBmp.AcquireWriteAccess();
385 : :
386 [ + - ]: 17 : if( pAcc )
387 : : {
388 : 17 : const sal_uLong nFormat = pAcc->GetScanlineFormat();
389 : :
390 [ # # ][ + - ]: 17 : if(
[ - + ][ - + ]
391 : : ( bGray && ( BMP_FORMAT_8BIT_PAL == nFormat ) ) ||
392 : : ( !bGray && ( BMP_FORMAT_24BIT_TC_RGB == nFormat ) )
393 : : )
394 : : {
395 : 0 : pBmpBuf = pAcc->GetBuffer();
396 : 0 : pParam->nAlignedWidth = pAcc->GetScanlineSize();
397 [ # # ]: 0 : pParam->bTopDown = pAcc->IsTopDown();
398 : : }
399 : : else
400 : : {
401 [ - + ]: 17 : pParam->nAlignedWidth = AlignedWidth4Bytes( aSize.Width() * ( bGray ? 8 : 24 ) );
402 : 17 : pParam->bTopDown = sal_True;
403 : 17 : pBmpBuf = pBuffer = rtl_allocateMemory( pParam->nAlignedWidth * aSize.Height() );
404 : : }
405 : : }
406 : :
407 : 17 : return pBmpBuf;
408 : : }
409 : :
410 : : // ------------------------------------------------------------------------
411 : :
412 : 17 : void JPEGReader::FillBitmap()
413 : : {
414 [ + - ][ + - ]: 17 : if( pBuffer && pAcc )
415 : : {
416 : : HPBYTE pTmp;
417 : 17 : BitmapColor aColor;
418 : : long nAlignedWidth;
419 : 17 : long nWidth = pAcc->Width();
420 : 17 : long nHeight = pAcc->Height();
421 : :
422 [ - + ]: 17 : if( pAcc->GetBitCount() == 8 )
423 : : {
424 [ # # ][ # # ]: 0 : BitmapColor* pCols = new BitmapColor[ 256 ];
425 : :
426 [ # # ]: 0 : for( sal_uInt16 n = 0; n < 256; n++ )
427 : : {
428 : 0 : const sal_uInt8 cGray = (sal_uInt8) n;
429 [ # # ]: 0 : pCols[ n ] = pAcc->GetBestMatchingColor( BitmapColor( cGray, cGray, cGray ) );
430 : : }
431 : :
432 : 0 : nAlignedWidth = AlignedWidth4Bytes( pAcc->Width() * 8L );
433 : :
434 [ # # ]: 0 : for( long nY = 0L; nY < nHeight; nY++ )
435 : : {
436 : 0 : pTmp = (sal_uInt8*) pBuffer + nY * nAlignedWidth;
437 : :
438 [ # # ]: 0 : for( long nX = 0L; nX < nWidth; nX++ )
439 [ # # ]: 0 : pAcc->SetPixel( nY, nX, pCols[ *pTmp++ ] );
440 : : }
441 : :
442 [ # # ][ # # ]: 0 : delete[] pCols;
443 : : }
444 : : else
445 : : {
446 : 17 : nAlignedWidth = AlignedWidth4Bytes( pAcc->Width() * 24L );
447 : :
448 [ + + ]: 889 : for( long nY = 0L; nY < nHeight; nY++ )
449 : : {
450 : 872 : pTmp = (sal_uInt8*) pBuffer + nY * nAlignedWidth;
451 : :
452 [ + + ]: 95218 : for( long nX = 0L; nX < nWidth; nX++ )
453 : : {
454 : 94346 : aColor.SetRed( *pTmp++ );
455 : 94346 : aColor.SetGreen( *pTmp++ );
456 : 94346 : aColor.SetBlue( *pTmp++ );
457 [ + - ]: 94346 : pAcc->SetPixel( nY, nX, aColor );
458 : : }
459 : : }
460 : 17 : }
461 : : }
462 : 17 : }
463 : :
464 : : // ------------------------------------------------------------------------
465 : :
466 : 0 : Graphic JPEGReader::CreateIntermediateGraphic( const Bitmap& rBitmap, long nLines )
467 : : {
468 [ # # ]: 0 : Graphic aGraphic;
469 [ # # ]: 0 : const Size aSizePix( rBitmap.GetSizePixel() );
470 : :
471 [ # # ]: 0 : if( !nLastLines )
472 : : {
473 [ # # ]: 0 : if( pAcc1 )
474 [ # # ]: 0 : aBmp1.ReleaseAccess( pAcc1 );
475 : :
476 [ # # ][ # # ]: 0 : aBmp1 = Bitmap( rBitmap.GetSizePixel(), 1 );
[ # # ][ # # ]
477 [ # # ]: 0 : aBmp1.Erase( Color( COL_WHITE ) );
478 [ # # ]: 0 : pAcc1 = aBmp1.AcquireWriteAccess();
479 : : }
480 : :
481 [ # # ][ # # ]: 0 : if( nLines && ( nLines < aSizePix.Height() ) )
[ # # ]
482 : : {
483 [ # # ]: 0 : if( pAcc1 )
484 : : {
485 : 0 : const long nNewLines = nLines - nLastLines;
486 : :
487 [ # # ]: 0 : if( nNewLines )
488 : : {
489 [ # # ]: 0 : pAcc1->SetFillColor( Color( COL_BLACK ) );
490 : : pAcc1->FillRect( Rectangle( Point( 0, nLastLines ),
491 [ # # ][ # # ]: 0 : Size( pAcc1->Width(), nNewLines ) ) );
492 : : }
493 : :
494 [ # # ]: 0 : aBmp1.ReleaseAccess( pAcc1 );
495 [ # # ][ # # ]: 0 : aGraphic = BitmapEx( rBitmap, aBmp1 );
[ # # ][ # # ]
[ # # ]
496 [ # # ]: 0 : pAcc1 = aBmp1.AcquireWriteAccess();
497 : : }
498 : : else
499 [ # # ][ # # ]: 0 : aGraphic = rBitmap;
[ # # ]
500 : : }
501 : : else
502 [ # # ][ # # ]: 0 : aGraphic = rBitmap;
[ # # ]
503 : :
504 : 0 : nLastLines = nLines;
505 : :
506 : 0 : return aGraphic;
507 : : }
508 : :
509 : : // ------------------------------------------------------------------------
510 : :
511 : 26 : ReadState JPEGReader::Read( Graphic& rGraphic )
512 : : {
513 : : long nEndPos;
514 : : long nLines;
515 : : ReadState eReadState;
516 : 26 : sal_Bool bRet = sal_False;
517 : : sal_uInt8 cDummy;
518 : :
519 : : #if 1 // TODO: is it possible to get rid of this seek to the end?
520 : : // check if the stream's end is already available
521 [ + - ]: 26 : rIStm.Seek( STREAM_SEEK_TO_END );
522 [ + - ]: 26 : rIStm >> cDummy;
523 : 26 : nEndPos = rIStm.Tell();
524 : :
525 : : // else check if at least JPEGMINREAD bytes can be read
526 [ - + ]: 26 : if( rIStm.GetError() == ERRCODE_IO_PENDING )
527 : : {
528 [ # # ]: 0 : rIStm.ResetError();
529 [ # # ]: 0 : if( ( nEndPos - nFormerPos ) < JPEGMINREAD )
530 : : {
531 [ # # ]: 0 : rIStm.Seek( nLastPos );
532 : 0 : return JPEGREAD_NEED_MORE;
533 : : }
534 : : }
535 : :
536 : : // seek back to the original position
537 [ + - ]: 26 : rIStm.Seek( nLastPos );
538 : : #endif
539 : :
540 [ + - ]: 26 : Size aPreviewSize = GetPreviewSize();
541 [ + - ]: 26 : SetJpegPreviewSizeHint( aPreviewSize.Width(), aPreviewSize.Height() );
542 : :
543 : : // read the (partial) image
544 [ + - ]: 26 : ReadJPEG( this, &rIStm, &nLines );
545 : :
546 [ + + ]: 26 : if( pAcc )
547 : : {
548 [ + - ]: 17 : if( pBuffer )
549 : : {
550 [ + - ]: 17 : FillBitmap();
551 : 17 : rtl_freeMemory( pBuffer );
552 : 17 : pBuffer = NULL;
553 : : }
554 : :
555 [ + - ]: 17 : aBmp.ReleaseAccess( pAcc );
556 : 17 : pAcc = NULL;
557 : :
558 [ - + ]: 17 : if( rIStm.GetError() == ERRCODE_IO_PENDING )
559 [ # # ][ # # ]: 0 : rGraphic = CreateIntermediateGraphic( aBmp, nLines );
[ # # ]
560 : : else
561 [ + - ][ + - ]: 17 : rGraphic = aBmp;
[ + - ]
562 : :
563 : 17 : bRet = sal_True;
564 : : }
565 [ - + ]: 9 : else if( rIStm.GetError() == ERRCODE_IO_PENDING )
566 : 0 : bRet = sal_True;
567 : :
568 : : // Status setzen ( Pending hat immer Vorrang )
569 [ - + ]: 26 : if( rIStm.GetError() == ERRCODE_IO_PENDING )
570 : : {
571 : 0 : eReadState = JPEGREAD_NEED_MORE;
572 [ # # ]: 0 : rIStm.ResetError();
573 : 0 : nFormerPos = rIStm.Tell();
574 : : }
575 : : else
576 : : {
577 [ + + ]: 26 : if( bRet )
578 : 17 : eReadState = JPEGREAD_OK;
579 : : else
580 : 9 : eReadState = JPEGREAD_ERROR;
581 : : }
582 : :
583 : 26 : return eReadState;
584 : : }
585 : :
586 : :
587 : : // --------------
588 : : // - JPEGWriter -
589 : : // --------------
590 : :
591 : 0 : JPEGWriter::JPEGWriter( SvStream& rStm, const uno::Sequence< beans::PropertyValue >* pFilterData, bool* pExportWasGrey ) :
592 : : rOStm ( rStm ),
593 : : pAcc ( NULL ),
594 : : pBuffer ( NULL ),
595 : 0 : pExpWasGrey ( pExportWasGrey )
596 : : {
597 [ # # ]: 0 : FilterConfigItem aConfigItem( (uno::Sequence< beans::PropertyValue >*)pFilterData );
598 [ # # ][ # # ]: 0 : bGreys = aConfigItem.ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( "ColorMode" ) ), 0 ) != 0;
[ # # ][ # # ]
599 [ # # ][ # # ]: 0 : nQuality = aConfigItem.ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( "Quality" ) ), 75 );
[ # # ][ # # ]
600 : :
601 [ # # ]: 0 : if ( pFilterData )
602 : : {
603 : 0 : int nArgs = pFilterData->getLength();
604 : 0 : const beans::PropertyValue* pValues = pFilterData->getConstArray();
605 [ # # ]: 0 : while( nArgs-- )
606 : : {
607 [ # # ]: 0 : if ( pValues->Name == "StatusIndicator" )
608 : : {
609 [ # # ]: 0 : pValues->Value >>= xStatusIndicator;
610 : : }
611 : 0 : pValues++;
612 : : }
613 [ # # ]: 0 : }
614 : 0 : }
615 : :
616 : : // ------------------------------------------------------------------------
617 : :
618 : 0 : void* JPEGWriter::GetScanline( long nY )
619 : : {
620 : 0 : void* pScanline = NULL;
621 : :
622 [ # # ]: 0 : if( pAcc )
623 : : {
624 [ # # ]: 0 : if( bNative )
625 : 0 : pScanline = pAcc->GetScanline( nY );
626 [ # # ]: 0 : else if( pBuffer )
627 : : {
628 : 0 : BitmapColor aColor;
629 : 0 : long nWidth = pAcc->Width();
630 : 0 : sal_uInt8* pTmp = pBuffer;
631 : :
632 [ # # ]: 0 : if( pAcc->HasPalette() )
633 : : {
634 [ # # ]: 0 : for( long nX = 0L; nX < nWidth; nX++ )
635 : : {
636 [ # # ]: 0 : aColor = pAcc->GetPaletteColor( (sal_uInt8) pAcc->GetPixel( nY, nX ) );
637 : 0 : *pTmp++ = aColor.GetRed();
638 [ # # ]: 0 : if ( bGreys )
639 : 0 : continue;
640 : 0 : *pTmp++ = aColor.GetGreen();
641 : 0 : *pTmp++ = aColor.GetBlue();
642 : : }
643 : : }
644 : : else
645 : : {
646 [ # # ]: 0 : for( long nX = 0L; nX < nWidth; nX++ )
647 : : {
648 [ # # ]: 0 : aColor = pAcc->GetPixel( nY, nX );
649 : 0 : *pTmp++ = aColor.GetRed();
650 [ # # ]: 0 : if ( bGreys )
651 : 0 : continue;
652 : 0 : *pTmp++ = aColor.GetGreen();
653 : 0 : *pTmp++ = aColor.GetBlue();
654 : : }
655 : : }
656 : :
657 : 0 : pScanline = pBuffer;
658 : : }
659 : : }
660 : :
661 : 0 : return pScanline;
662 : : }
663 : :
664 : : // ------------------------------------------------------------------------
665 : :
666 : 0 : sal_Bool JPEGWriter::Write( const Graphic& rGraphic )
667 : : {
668 : 0 : sal_Bool bRet = sal_False;
669 : :
670 [ # # ]: 0 : if ( xStatusIndicator.is() )
671 : : {
672 : 0 : rtl::OUString aMsg;
673 [ # # ][ # # ]: 0 : xStatusIndicator->start( aMsg, 100 );
674 : : }
675 : :
676 [ # # ]: 0 : Bitmap aGraphicBmp( rGraphic.GetBitmap() );
677 : :
678 [ # # ]: 0 : if ( bGreys )
679 : : {
680 [ # # ][ # # ]: 0 : if ( !aGraphicBmp.Convert( BMP_CONVERSION_8BIT_GREYS ) )
681 [ # # ][ # # ]: 0 : aGraphicBmp = rGraphic.GetBitmap();
[ # # ]
682 : : }
683 : :
684 [ # # ]: 0 : pAcc = aGraphicBmp.AcquireReadAccess();
685 : :
686 [ # # ]: 0 : if ( !bGreys ) // bitmap was not explicitly converted into greyscale,
687 : : { // check if source is greyscale only
688 : :
689 : 0 : sal_Bool bIsGrey = sal_True;
690 : :
691 : 0 : long nWidth = pAcc->Width();
692 [ # # ][ # # ]: 0 : for ( long nY = 0; bIsGrey && ( nY < pAcc->Height() ); nY++ )
[ # # ]
693 : : {
694 : 0 : BitmapColor aColor;
695 [ # # ][ # # ]: 0 : for( long nX = 0L; bIsGrey && ( nX < nWidth ); nX++ )
[ # # ]
696 : : {
697 [ # # ][ # # ]: 0 : aColor = pAcc->HasPalette() ? pAcc->GetPaletteColor( (sal_uInt8) pAcc->GetPixel( nY, nX ) )
[ # # ]
698 [ # # ][ # # ]: 0 : : pAcc->GetPixel( nY, nX );
699 [ # # ][ # # ]: 0 : bIsGrey = ( aColor.GetRed() == aColor.GetGreen() ) && ( aColor.GetRed() == aColor.GetBlue() );
700 : : }
701 : 0 : }
702 [ # # ]: 0 : if ( bIsGrey )
703 : 0 : bGreys = sal_True;
704 : : }
705 : :
706 [ # # ]: 0 : if( pExpWasGrey )
707 : 0 : *pExpWasGrey = bGreys;
708 : :
709 [ # # ]: 0 : if( pAcc )
710 : : {
711 : 0 : bNative = ( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB );
712 : :
713 [ # # ]: 0 : if( !bNative )
714 [ # # ][ # # ]: 0 : pBuffer = new sal_uInt8[ AlignedWidth4Bytes( bGreys ? pAcc->Width() * 8L : pAcc->Width() * 24L ) ];
715 : :
716 [ # # ]: 0 : JPEGCallbackStruct aCallbackData;
717 [ # # ]: 0 : aCallbackData.xStatusIndicator = xStatusIndicator;
718 [ # # ]: 0 : bRet = (sal_Bool) WriteJPEG( this, &rOStm, pAcc->Width(), pAcc->Height(), bGreys, nQuality, &aCallbackData );
719 : :
720 [ # # ]: 0 : delete[] pBuffer;
721 : 0 : pBuffer = NULL;
722 : :
723 [ # # ]: 0 : aGraphicBmp.ReleaseAccess( pAcc );
724 [ # # ]: 0 : pAcc = NULL;
725 : : }
726 [ # # ]: 0 : if ( xStatusIndicator.is() )
727 [ # # ][ # # ]: 0 : xStatusIndicator->end();
728 : :
729 [ # # ]: 0 : return bRet;
730 : : }
731 : :
732 : : // --------------
733 : : // - ImportJPEG -
734 : : // --------------
735 : :
736 : 26 : sal_Bool ImportJPEG( SvStream& rStm, Graphic& rGraphic, void* pCallerData, sal_Int32 nImportFlags )
737 : : {
738 : 26 : JPEGReader* pJPEGReader = (JPEGReader*) rGraphic.GetContext();
739 : : ReadState eReadState;
740 : 26 : sal_Bool bRet = sal_True;
741 : :
742 [ + - ]: 26 : if( !pJPEGReader )
743 [ + - ]: 26 : pJPEGReader = new JPEGReader( rStm, pCallerData, ( nImportFlags & GRFILTER_I_FLAGS_SET_LOGSIZE_FOR_JPEG ) != 0 );
744 : :
745 [ - + ]: 26 : if( nImportFlags & GRFILTER_I_FLAGS_FOR_PREVIEW )
746 [ # # ]: 0 : pJPEGReader->SetPreviewSize( Size(128,128) );
747 : : else
748 : 26 : pJPEGReader->DisablePreviewMode();
749 : :
750 : 26 : rGraphic.SetContext( NULL );
751 : 26 : eReadState = pJPEGReader->Read( rGraphic );
752 : :
753 [ + + ]: 26 : if( eReadState == JPEGREAD_ERROR )
754 : : {
755 : 9 : bRet = sal_False;
756 [ + - ]: 9 : delete pJPEGReader;
757 : : }
758 [ + - ]: 17 : else if( eReadState == JPEGREAD_OK )
759 [ + - ]: 17 : delete pJPEGReader;
760 : : else
761 : 0 : rGraphic.SetContext( pJPEGReader );
762 : :
763 : 26 : return bRet;
764 : : }
765 : :
766 : : // --------------
767 : : // - ExportJPEG -
768 : : // --------------
769 : :
770 : 0 : sal_Bool ExportJPEG( SvStream& rOStm, const Graphic& rGraphic,
771 : : const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData,
772 : : bool* pExportWasGrey
773 : : )
774 : : {
775 [ # # ]: 0 : JPEGWriter aJPEGWriter( rOStm, pFilterData, pExportWasGrey );
776 [ # # ][ # # ]: 0 : return aJPEGWriter.Write( rGraphic );
777 : : }
778 : :
779 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|