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 :
21 : #include <vcl/graph.hxx>
22 : #include <vcl/svapp.hxx>
23 : #include <vcl/msgbox.hxx>
24 : #include <vcl/bmpacc.hxx>
25 : #include <svl/solar.hrc>
26 : #include <svtools/fltcall.hxx>
27 : #include <svtools/FilterConfigItem.hxx>
28 :
29 : #define NewSubfileType 254
30 : #define ImageWidth 256
31 : #define ImageLength 257
32 : #define BitsPerSample 258
33 : #define Compression 259
34 : #define PhotometricInterpretation 262
35 : #define StripOffsets 273
36 : #define SamplesPerPixel 277
37 : #define RowsPerStrip 278
38 : #define StripByteCounts 279
39 : #define XResolution 282
40 : #define YResolution 283
41 : #define PlanarConfiguration 284
42 : #define ResolutionUnit 296
43 : #define ColorMap 320
44 : #define ReferenceBlackWhite 532
45 :
46 : // -------------
47 : // - TIFFWriter -
48 : // -------------
49 :
50 : struct TIFFLZWCTreeNode
51 : {
52 :
53 : TIFFLZWCTreeNode* pBrother; // naechster Knoten, der den selben Vater hat
54 : TIFFLZWCTreeNode* pFirstChild; // erster Sohn
55 : sal_uInt16 nCode; // Der Code fuer den String von Pixelwerten, der sich ergibt, wenn
56 : sal_uInt16 nValue; // Der Pixelwert
57 : };
58 :
59 : class TIFFWriter
60 : {
61 : private:
62 :
63 : SvStream& m_rOStm;
64 : sal_uInt32 mnStreamOfs;
65 :
66 : sal_Bool mbStatus;
67 : BitmapReadAccess* mpAcc;
68 :
69 : sal_uInt32 mnWidth, mnHeight, mnColors;
70 : sal_uInt32 mnCurAllPictHeight;
71 : sal_uInt32 mnSumOfAllPictHeight;
72 : sal_uInt32 mnBitsPerPixel;
73 : sal_uInt32 mnLastPercent;
74 :
75 : sal_uInt32 mnLatestIfdPos;
76 : sal_uInt16 mnTagCount; // number of tags already written
77 : sal_uInt32 mnCurrentTagCountPos; // offset to the position where the current
78 : // tag count is to insert
79 :
80 : sal_uInt32 mnXResPos; // if != 0 this DWORDs stores the
81 : sal_uInt32 mnYResPos; // actual streamposition of the
82 : sal_uInt32 mnPalPos; // Tag Entry
83 : sal_uInt32 mnBitmapPos;
84 : sal_uInt32 mnStripByteCountPos;
85 :
86 : TIFFLZWCTreeNode* pTable;
87 : TIFFLZWCTreeNode* pPrefix;
88 : sal_uInt16 nDataSize;
89 : sal_uInt16 nClearCode;
90 : sal_uInt16 nEOICode;
91 : sal_uInt16 nTableSize;
92 : sal_uInt16 nCodeSize;
93 : sal_uLong nOffset;
94 : sal_uLong dwShift;
95 :
96 : com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator > xStatusIndicator;
97 :
98 : void ImplCallback( sal_uInt32 nPercent );
99 : sal_Bool ImplWriteHeader( sal_Bool bMultiPage );
100 : void ImplWritePalette();
101 : sal_Bool ImplWriteBody();
102 : void ImplWriteTag( sal_uInt16 TagID, sal_uInt16 DataType, sal_uInt32 NumberOfItems, sal_uInt32 Value);
103 : void ImplWriteResolution( sal_uLong nStreamPos, sal_uInt32 nResolutionUnit );
104 : void StartCompression();
105 : void Compress( sal_uInt8 nSrc );
106 : void EndCompression();
107 : inline void WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen );
108 :
109 : public:
110 :
111 : TIFFWriter(SvStream &rStream);
112 : ~TIFFWriter();
113 :
114 : sal_Bool WriteTIFF( const Graphic& rGraphic, FilterConfigItem* pFilterConfigItem );
115 : };
116 :
117 : // ------------------------------------------------------------------------
118 :
119 0 : TIFFWriter::TIFFWriter(SvStream &rStream)
120 : : m_rOStm(rStream)
121 : , mbStatus(sal_True)
122 : , mpAcc(NULL)
123 : , mnCurAllPictHeight(0)
124 : , mnSumOfAllPictHeight(0)
125 : , mnLastPercent(0)
126 : , mnXResPos(0)
127 : , mnYResPos(0)
128 : , mnBitmapPos(0)
129 0 : , mnStripByteCountPos(0)
130 : {
131 0 : }
132 :
133 : // ------------------------------------------------------------------------
134 :
135 0 : TIFFWriter::~TIFFWriter()
136 : {
137 0 : }
138 :
139 : // ------------------------------------------------------------------------
140 :
141 0 : sal_Bool TIFFWriter::WriteTIFF( const Graphic& rGraphic, FilterConfigItem* pFilterConfigItem)
142 : {
143 0 : sal_uLong* pDummy = new sal_uLong; delete pDummy; // damit unter OS/2
144 : // das richtige (Tools-)new
145 : // verwendet wird, da es sonst
146 : // in dieser DLL nur Vector-news
147 : // gibt;
148 :
149 0 : if ( pFilterConfigItem )
150 : {
151 0 : xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
152 0 : if ( xStatusIndicator.is() )
153 : {
154 0 : rtl::OUString aMsg;
155 0 : xStatusIndicator->start( aMsg, 100 );
156 : }
157 : }
158 :
159 0 : const sal_uInt16 nOldFormat = m_rOStm.GetNumberFormatInt();
160 0 : mnStreamOfs = m_rOStm.Tell();
161 :
162 : // we will use the BIG Endian Mode
163 : // TIFF header
164 0 : m_rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
165 0 : m_rOStm << (sal_uInt32)0x4d4d002a; // TIFF identifier
166 0 : mnLatestIfdPos = m_rOStm.Tell();
167 0 : m_rOStm << (sal_uInt32)0;
168 :
169 0 : Animation aAnimation;
170 0 : Bitmap aBmp;
171 :
172 0 : if( mbStatus )
173 : {
174 0 : if ( rGraphic.IsAnimated() )
175 0 : aAnimation = rGraphic.GetAnimation();
176 : else
177 : {
178 0 : AnimationBitmap aAnimationBitmap( rGraphic.GetBitmap(), Point(), Size() );
179 0 : aAnimation.Insert( aAnimationBitmap );
180 : }
181 :
182 : sal_uInt16 i;
183 0 : for ( i = 0; i < aAnimation.Count(); i++ )
184 0 : mnSumOfAllPictHeight += aAnimation.Get( i ).aBmpEx.GetSizePixel().Height();
185 :
186 0 : for ( i = 0; mbStatus && ( i < aAnimation.Count() ); i++ )
187 : {
188 0 : mnPalPos = 0;
189 0 : const AnimationBitmap& rAnimationBitmap = aAnimation.Get( i );
190 0 : aBmp = rAnimationBitmap.aBmpEx.GetBitmap();
191 0 : mpAcc = aBmp.AcquireReadAccess();
192 0 : if ( mpAcc )
193 : {
194 0 : mnBitsPerPixel = aBmp.GetBitCount();
195 :
196 : // export code below only handles four discrete cases
197 : mnBitsPerPixel =
198 0 : mnBitsPerPixel <= 1 ? 1 : mnBitsPerPixel <= 4 ? 4 : mnBitsPerPixel <= 8 ? 8 : 24;
199 :
200 0 : if ( ImplWriteHeader( ( aAnimation.Count() > 0 ) ) )
201 : {
202 0 : Size aDestMapSize( 300, 300 );
203 0 : const MapMode aMapMode( aBmp.GetPrefMapMode() );
204 0 : if ( aMapMode.GetMapUnit() != MAP_PIXEL )
205 : {
206 0 : const Size aPrefSize( rGraphic.GetPrefSize() );
207 0 : aDestMapSize = OutputDevice::LogicToLogic( aPrefSize, aMapMode, MAP_INCH );
208 : }
209 0 : ImplWriteResolution( mnXResPos, aDestMapSize.Width() );
210 0 : ImplWriteResolution( mnYResPos, aDestMapSize.Height() );
211 0 : if ( mnPalPos )
212 0 : ImplWritePalette();
213 0 : ImplWriteBody();
214 : }
215 0 : sal_uInt32 nCurPos = m_rOStm.Tell();
216 0 : m_rOStm.Seek( mnCurrentTagCountPos );
217 0 : m_rOStm << mnTagCount;
218 0 : m_rOStm.Seek( nCurPos );
219 :
220 0 : aBmp.ReleaseAccess( mpAcc );
221 : }
222 : else
223 0 : mbStatus = sal_False;
224 : }
225 : }
226 0 : m_rOStm.SetNumberFormatInt( nOldFormat );
227 :
228 0 : if ( xStatusIndicator.is() )
229 0 : xStatusIndicator->end();
230 :
231 0 : return mbStatus;
232 : }
233 :
234 : // ------------------------------------------------------------------------
235 :
236 0 : void TIFFWriter::ImplCallback( sal_uInt32 nPercent )
237 : {
238 0 : if ( xStatusIndicator.is() )
239 : {
240 0 : if( nPercent >= mnLastPercent + 3 )
241 : {
242 0 : mnLastPercent = nPercent;
243 0 : if ( nPercent <= 100 )
244 0 : xStatusIndicator->setValue( nPercent );
245 : }
246 : }
247 0 : }
248 :
249 :
250 : // ------------------------------------------------------------------------
251 :
252 0 : sal_Bool TIFFWriter::ImplWriteHeader( sal_Bool bMultiPage )
253 : {
254 0 : mnTagCount = 0;
255 0 : mnWidth = mpAcc->Width();
256 0 : mnHeight = mpAcc->Height();
257 :
258 0 : if ( mnWidth && mnHeight && mnBitsPerPixel && mbStatus )
259 : {
260 0 : sal_uInt32 nCurrentPos = m_rOStm.Tell();
261 0 : m_rOStm.Seek( mnLatestIfdPos );
262 0 : m_rOStm << (sal_uInt32)( nCurrentPos - mnStreamOfs ); // offset to the IFD
263 0 : m_rOStm.Seek( nCurrentPos );
264 :
265 : // (OFS8) TIFF image file directory (IFD)
266 0 : mnCurrentTagCountPos = m_rOStm.Tell();
267 0 : m_rOStm << (sal_uInt16)0; // the number of tagentrys is to insert later
268 :
269 0 : sal_uInt32 nSubFileFlags = 0;
270 0 : if ( bMultiPage )
271 0 : nSubFileFlags |= 2;
272 0 : ImplWriteTag( NewSubfileType, 4, 1, nSubFileFlags );
273 0 : ImplWriteTag( ImageWidth, 4, 1, mnWidth );
274 0 : ImplWriteTag( ImageLength, 4, 1, mnHeight);
275 0 : ImplWriteTag( BitsPerSample, 3, 1, ( mnBitsPerPixel == 24 ) ? 8 : mnBitsPerPixel );
276 0 : ImplWriteTag( Compression, 3, 1, 5 );
277 : sal_uInt8 nTemp;
278 0 : switch ( mnBitsPerPixel )
279 : {
280 : case 1 :
281 0 : nTemp = 1;
282 0 : break;
283 : case 4 :
284 : case 8 :
285 0 : nTemp = 3;
286 0 : break;
287 : case 24:
288 0 : nTemp = 2;
289 0 : break;
290 : default:
291 0 : nTemp = 0; // -Wall set a default...
292 0 : break;
293 : }
294 0 : ImplWriteTag( PhotometricInterpretation, 3, 1, nTemp );
295 0 : mnBitmapPos = m_rOStm.Tell();
296 0 : ImplWriteTag( StripOffsets, 4, 1, 0 );
297 0 : ImplWriteTag( SamplesPerPixel, 3, 1, ( mnBitsPerPixel == 24 ) ? 3 : 1 );
298 0 : ImplWriteTag( RowsPerStrip, 4, 1, mnHeight ); //0xffffffff );
299 0 : mnStripByteCountPos = m_rOStm.Tell();
300 0 : ImplWriteTag( StripByteCounts, 4, 1, ( ( mnWidth * mnBitsPerPixel * mnHeight ) + 7 ) >> 3 );
301 0 : mnXResPos = m_rOStm.Tell();
302 0 : ImplWriteTag( XResolution, 5, 1, 0 );
303 0 : mnYResPos = m_rOStm.Tell();
304 0 : ImplWriteTag( YResolution, 5, 1, 0 );
305 0 : if ( mnBitsPerPixel != 1 )
306 0 : ImplWriteTag( PlanarConfiguration, 3, 1, 1 ); // ( RGB ORDER )
307 0 : ImplWriteTag( ResolutionUnit, 3, 1, 2); // Resolution Unit is Inch
308 0 : if ( ( mnBitsPerPixel == 4 ) || ( mnBitsPerPixel == 8 ) )
309 : {
310 0 : mnColors = mpAcc->GetPaletteEntryCount();
311 0 : mnPalPos = m_rOStm.Tell();
312 0 : ImplWriteTag( ColorMap, 3, 3 * mnColors, 0 );
313 : }
314 :
315 : // and last we write zero to close the num dir entries list
316 0 : mnLatestIfdPos = m_rOStm.Tell();
317 0 : m_rOStm << (sal_uInt32)0; // there are no more IFD
318 : }
319 : else
320 0 : mbStatus = sal_False;
321 :
322 0 : return mbStatus;
323 : }
324 :
325 : // ------------------------------------------------------------------------
326 :
327 0 : void TIFFWriter::ImplWritePalette()
328 : {
329 : sal_uInt16 i;
330 0 : sal_uLong nCurrentPos = m_rOStm.Tell();
331 0 : m_rOStm.Seek( mnPalPos + 8 ); // the palette tag entry needs the offset
332 0 : m_rOStm << static_cast<sal_uInt32>(nCurrentPos - mnStreamOfs); // to the palette colors
333 0 : m_rOStm.Seek( nCurrentPos );
334 :
335 0 : for ( i = 0; i < mnColors; i++ )
336 : {
337 0 : const BitmapColor& rColor = mpAcc->GetPaletteColor( i );
338 0 : m_rOStm << (sal_uInt16)( rColor.GetRed() << 8 );
339 : }
340 0 : for ( i = 0; i < mnColors; i++ )
341 : {
342 0 : const BitmapColor& rColor = mpAcc->GetPaletteColor( i );
343 0 : m_rOStm << (sal_uInt16)( rColor.GetGreen() << 8 );
344 : }
345 0 : for ( i = 0; i < mnColors; i++ )
346 : {
347 0 : const BitmapColor& rColor = mpAcc->GetPaletteColor( i );
348 0 : m_rOStm << (sal_uInt16)( rColor.GetBlue() << 8 );
349 : }
350 0 : }
351 :
352 : // ------------------------------------------------------------------------
353 :
354 0 : sal_Bool TIFFWriter::ImplWriteBody()
355 : {
356 0 : sal_uInt8 nTemp = 0;
357 : sal_uInt8 nShift;
358 : sal_uLong j, x, y;
359 :
360 0 : sal_uLong nGfxBegin = m_rOStm.Tell();
361 0 : m_rOStm.Seek( mnBitmapPos + 8 ); // the strip offset tag entry needs the offset
362 0 : m_rOStm << static_cast<sal_uInt32>(nGfxBegin - mnStreamOfs); // to the bitmap data
363 0 : m_rOStm.Seek( nGfxBegin );
364 :
365 0 : StartCompression();
366 :
367 0 : switch( mnBitsPerPixel )
368 : {
369 : case 24 :
370 : {
371 0 : for ( y = 0; y < mnHeight; y++, mnCurAllPictHeight++ )
372 : {
373 0 : ImplCallback( 100 * mnCurAllPictHeight / mnSumOfAllPictHeight );
374 0 : for ( x = 0; x < mnWidth; x++ )
375 : {
376 0 : const BitmapColor& rColor = mpAcc->GetPixel( y, x );
377 0 : Compress( rColor.GetRed() );
378 0 : Compress( rColor.GetGreen() );
379 0 : Compress( rColor.GetBlue() );
380 0 : }
381 : }
382 : }
383 0 : break;
384 :
385 : case 8 :
386 : {
387 0 : for ( y = 0; y < mnHeight; y++, mnCurAllPictHeight++ )
388 : {
389 0 : ImplCallback( 100 * mnCurAllPictHeight / mnSumOfAllPictHeight );
390 0 : for ( x = 0; x < mnWidth; x++ )
391 : {
392 0 : Compress( mpAcc->GetPixel( y, x ) );
393 : }
394 : }
395 : }
396 0 : break;
397 :
398 : case 4 :
399 : {
400 0 : for ( nShift = 0, y = 0; y < mnHeight; y++, mnCurAllPictHeight++ )
401 : {
402 0 : ImplCallback( 100 * mnCurAllPictHeight / mnSumOfAllPictHeight );
403 0 : for ( x = 0; x < mnWidth; x++, nShift++ )
404 : {
405 0 : if (!( nShift & 1 ))
406 0 : nTemp = ( (sal_uInt8)mpAcc->GetPixel( y, x ) << 4 );
407 : else
408 0 : Compress( (sal_uInt8)( nTemp | ( mpAcc->GetPixel( y, x ) & 0xf ) ) );
409 : }
410 0 : if ( nShift & 1 )
411 0 : Compress( nTemp );
412 : }
413 : }
414 0 : break;
415 :
416 : case 1 :
417 : {
418 0 : j = 1;
419 0 : for ( y = 0; y < mnHeight; y++, mnCurAllPictHeight++ )
420 : {
421 0 : ImplCallback( 100 * mnCurAllPictHeight / mnSumOfAllPictHeight );
422 0 : for ( x = 0; x < mnWidth; x++)
423 : {
424 0 : j <<= 1;
425 0 : j |= ( ( ~mpAcc->GetPixel( y, x ) ) & 1 );
426 0 : if ( j & 0x100 )
427 : {
428 0 : Compress( (sal_uInt8)j );
429 0 : j = 1;
430 : }
431 : }
432 0 : if ( j != 1 )
433 : {
434 0 : Compress( (sal_uInt8)(j << ( ( ( x & 7) ^ 7 ) + 1 ) ) );
435 0 : j = 1;
436 : }
437 : }
438 : }
439 0 : break;
440 :
441 : default:
442 : {
443 0 : mbStatus = sal_False;
444 : }
445 0 : break;
446 : }
447 :
448 0 : EndCompression();
449 :
450 0 : if ( mnStripByteCountPos && mbStatus )
451 : {
452 0 : sal_uLong nGfxEnd = m_rOStm.Tell();
453 0 : m_rOStm.Seek( mnStripByteCountPos + 8 );
454 0 : m_rOStm << static_cast<sal_uInt32>( nGfxEnd - nGfxBegin ); // mnStripByteCountPos needs the size of the compression data
455 0 : m_rOStm.Seek( nGfxEnd );
456 : }
457 0 : return mbStatus;
458 : }
459 :
460 : // ------------------------------------------------------------------------
461 :
462 0 : void TIFFWriter::ImplWriteResolution( sal_uLong nStreamPos, sal_uInt32 nResolutionUnit )
463 : {
464 0 : sal_uLong nCurrentPos = m_rOStm.Tell();
465 0 : m_rOStm.Seek( nStreamPos + 8 );
466 0 : m_rOStm << (sal_uInt32)nCurrentPos - mnStreamOfs;
467 0 : m_rOStm.Seek( nCurrentPos );
468 0 : m_rOStm << (sal_uInt32)1;
469 0 : m_rOStm << nResolutionUnit;
470 0 : }
471 :
472 : // ------------------------------------------------------------------------
473 :
474 0 : void TIFFWriter::ImplWriteTag( sal_uInt16 nTagID, sal_uInt16 nDataType, sal_uInt32 nNumberOfItems, sal_uInt32 nValue)
475 : {
476 0 : mnTagCount++;
477 :
478 0 : m_rOStm << nTagID;
479 0 : m_rOStm << nDataType;
480 0 : m_rOStm << nNumberOfItems;
481 0 : if ( nDataType == 3 )
482 0 : nValue <<=16; // in Big Endian Mode WORDS needed to be shifted to a DWORD
483 0 : m_rOStm << nValue;
484 0 : }
485 :
486 : // ------------------------------------------------------------------------
487 :
488 0 : inline void TIFFWriter::WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen )
489 : {
490 0 : dwShift |= ( nCode << ( nOffset - nCodeLen ) );
491 0 : nOffset -= nCodeLen;
492 0 : while ( nOffset < 24 )
493 : {
494 0 : m_rOStm << (sal_uInt8)( dwShift >> 24 );
495 0 : dwShift <<= 8;
496 0 : nOffset += 8;
497 : }
498 0 : if ( nCode == 257 && nOffset != 32 )
499 : {
500 0 : m_rOStm << (sal_uInt8)( dwShift >> 24 );
501 : }
502 0 : }
503 :
504 : // ------------------------------------------------------------------------
505 :
506 0 : void TIFFWriter::StartCompression()
507 : {
508 : sal_uInt16 i;
509 0 : nDataSize = 8;
510 :
511 0 : nClearCode = 1 << nDataSize;
512 0 : nEOICode = nClearCode + 1;
513 0 : nTableSize = nEOICode + 1;
514 0 : nCodeSize = nDataSize + 1;
515 :
516 0 : nOffset = 32; // anzahl freier bits in dwShift
517 0 : dwShift = 0;
518 :
519 0 : pTable = new TIFFLZWCTreeNode[ 4096 ];
520 :
521 0 : for ( i = 0; i < 4096; i++)
522 : {
523 0 : pTable[ i ].pBrother = pTable[ i ].pFirstChild = NULL;
524 0 : pTable[ i ].nValue = (sal_uInt8)( pTable[ i ].nCode = i );
525 : }
526 :
527 0 : pPrefix = NULL;
528 0 : WriteBits( nClearCode, nCodeSize );
529 0 : }
530 :
531 : // ------------------------------------------------------------------------
532 :
533 0 : void TIFFWriter::Compress( sal_uInt8 nCompThis )
534 : {
535 : TIFFLZWCTreeNode* p;
536 : sal_uInt16 i;
537 : sal_uInt8 nV;
538 :
539 0 : if( !pPrefix )
540 : {
541 0 : pPrefix = pTable + nCompThis;
542 : }
543 : else
544 : {
545 0 : nV = nCompThis;
546 0 : for( p = pPrefix->pFirstChild; p != NULL; p = p->pBrother )
547 : {
548 0 : if ( p->nValue == nV )
549 0 : break;
550 : }
551 :
552 0 : if( p )
553 0 : pPrefix = p;
554 : else
555 : {
556 0 : WriteBits( pPrefix->nCode, nCodeSize );
557 :
558 0 : if ( nTableSize == 409 )
559 : {
560 0 : WriteBits( nClearCode, nCodeSize );
561 :
562 0 : for ( i = 0; i < nClearCode; i++ )
563 0 : pTable[ i ].pFirstChild = NULL;
564 :
565 0 : nCodeSize = nDataSize + 1;
566 0 : nTableSize = nEOICode + 1;
567 : }
568 : else
569 : {
570 0 : if( nTableSize == (sal_uInt16)( ( 1 << nCodeSize ) - 1 ) )
571 0 : nCodeSize++;
572 :
573 0 : p = pTable + ( nTableSize++ );
574 0 : p->pBrother = pPrefix->pFirstChild;
575 0 : pPrefix->pFirstChild = p;
576 0 : p->nValue = nV;
577 0 : p->pFirstChild = NULL;
578 : }
579 :
580 0 : pPrefix = pTable + nV;
581 : }
582 : }
583 0 : }
584 :
585 : // ------------------------------------------------------------------------
586 :
587 0 : void TIFFWriter::EndCompression()
588 : {
589 0 : if( pPrefix )
590 0 : WriteBits( pPrefix->nCode, nCodeSize );
591 :
592 0 : WriteBits( nEOICode, nCodeSize );
593 0 : delete[] pTable;
594 0 : }
595 :
596 : // ------------------------------------------------------------------------
597 :
598 : // ---------------------
599 : // - exported function -
600 : // ---------------------
601 :
602 : #ifdef DISABLE_DYNLOADING
603 : #define GraphicExport etiGraphicExport
604 : #endif
605 :
606 : extern "C" SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL
607 0 : GraphicExport(SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pFilterConfigItem, sal_Bool)
608 : {
609 0 : TIFFWriter aWriter(rStream);
610 0 : return aWriter.WriteTIFF( rGraphic, pFilterConfigItem );
611 : }
612 :
613 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|