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