26#include <com/sun/star/task/XStatusIndicator.hpp>
29#define NewSubfileType 254
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
47struct TIFFLZWCTreeNode
50 TIFFLZWCTreeNode* pBrother;
51 TIFFLZWCTreeNode* pFirstChild;
62 sal_uInt32 mnStreamOfs;
68 sal_uInt32 mnCurAllPictHeight;
69 sal_uInt32 mnSumOfAllPictHeight;
70 sal_uInt32 mnBitsPerPixel;
71 sal_uInt32 mnLastPercent;
73 sal_uInt32 mnLatestIfdPos;
74 sal_uInt16 mnTagCount;
75 sal_uInt32 mnCurrentTagCountPos;
81 sal_uInt32 mnBitmapPos;
82 sal_uInt32 mnStripByteCountPos;
84 std::unique_ptr<TIFFLZWCTreeNode[]> pTable;
85 TIFFLZWCTreeNode* pPrefix;
87 sal_uInt16 nClearCode;
89 sal_uInt16 nTableSize;
94 css::uno::Reference< css::task::XStatusIndicator > xStatusIndicator;
96 void ImplCallback( sal_uInt32 nPercent );
97 bool ImplWriteHeader(
bool bMultiPage );
98 void ImplWritePalette();
100 void ImplWriteTag( sal_uInt16 TagID, sal_uInt16
DataType, sal_uInt32 NumberOfItems, sal_uInt32
Value);
101 void ImplWriteResolution( sal_uInt64 nStreamPos, sal_uInt32 nResolutionUnit );
102 void StartCompression();
104 void EndCompression();
105 inline void WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen );
109 explicit TIFFWriter(
SvStream &rStream);
116TIFFWriter::TIFFWriter(
SvStream &rStream)
124 , mnCurAllPictHeight(0)
125 , mnSumOfAllPictHeight(0)
130 , mnCurrentTagCountPos(0)
135 , mnStripByteCountPos(0)
150 if ( pFilterConfigItem )
153 if ( xStatusIndicator.is() )
155 xStatusIndicator->start( OUString(), 100 );
160 mnStreamOfs = m_rOStm.Tell();
164 m_rOStm.SetEndian( SvStreamEndian::BIG );
165 m_rOStm.WriteUInt32( 0x4d4d002a );
166 mnLatestIfdPos = m_rOStm.Tell();
167 m_rOStm.WriteUInt32( 0 );
175 for (
size_t i = 0;
i < aAnimation.
Count(); ++
i)
178 for (
size_t i = 0; mbStatus &&
i < aAnimation.
Count(); ++
i)
190 mnBitsPerPixel <= 1 ? 1 : mnBitsPerPixel <= 4 ? 4 : mnBitsPerPixel <= 8 ? 8 : 24;
192 if ( ImplWriteHeader( aAnimation.
Count() > 0 ) )
194 Size aDestMapSize( 300, 300 );
196 if ( aMapMode.GetMapUnit() != MapUnit::MapPixel )
201 ImplWriteResolution( mnXResPos, aDestMapSize.Width() );
202 ImplWriteResolution( mnYResPos, aDestMapSize.Height() );
207 sal_uInt32 nCurPos = m_rOStm.Tell();
208 m_rOStm.Seek( mnCurrentTagCountPos );
209 m_rOStm.WriteUInt16( mnTagCount );
210 m_rOStm.Seek( nCurPos );
218 m_rOStm.SetEndian( nOldFormat );
220 if ( xStatusIndicator.is() )
221 xStatusIndicator->end();
227void TIFFWriter::ImplCallback( sal_uInt32 nPercent )
229 if ( xStatusIndicator.is() )
231 if( nPercent >= mnLastPercent + 3 )
233 mnLastPercent = nPercent;
234 if ( nPercent <= 100 )
235 xStatusIndicator->setValue( nPercent );
241bool TIFFWriter::ImplWriteHeader(
bool bMultiPage )
247 if ( mnWidth && mnHeight && mnBitsPerPixel && mbStatus )
249 sal_uInt32 nCurrentPos = m_rOStm.Tell();
250 m_rOStm.Seek( mnLatestIfdPos );
251 m_rOStm.WriteUInt32( nCurrentPos - mnStreamOfs );
252 m_rOStm.Seek( nCurrentPos );
255 mnCurrentTagCountPos = m_rOStm.Tell();
256 m_rOStm.WriteUInt16( 0 );
258 sal_uInt32 nSubFileFlags = 0;
264 ImplWriteTag(
BitsPerSample, 3, 1, ( mnBitsPerPixel == 24 ) ? 8 : mnBitsPerPixel );
267 switch ( mnBitsPerPixel )
284 mnBitmapPos = m_rOStm.Tell();
286 ImplWriteTag(
SamplesPerPixel, 3, 1, ( mnBitsPerPixel == 24 ) ? 3 : 1 );
288 mnStripByteCountPos = m_rOStm.Tell();
289 ImplWriteTag(
StripByteCounts, 4, 1, ( ( mnWidth * mnBitsPerPixel * mnHeight ) + 7 ) >> 3 );
290 mnXResPos = m_rOStm.Tell();
292 mnYResPos = m_rOStm.Tell();
294 if ( mnBitsPerPixel != 1 )
297 if ( ( mnBitsPerPixel == 4 ) || ( mnBitsPerPixel == 8 ) )
299 mnColors = mpAcc->GetPaletteEntryCount();
300 mnPalPos = m_rOStm.Tell();
301 ImplWriteTag(
ColorMap, 3, 3 * mnColors, 0 );
305 mnLatestIfdPos = m_rOStm.Tell();
306 m_rOStm.WriteUInt32( 0 );
315void TIFFWriter::ImplWritePalette()
317 sal_uInt64 nCurrentPos = m_rOStm.Tell();
318 m_rOStm.Seek( mnPalPos + 8 );
319 m_rOStm.WriteUInt32( nCurrentPos - mnStreamOfs );
320 m_rOStm.Seek( nCurrentPos );
322 for ( sal_uInt32 i = 0;
i < mnColors;
i++ )
324 const BitmapColor& rColor = mpAcc->GetPaletteColor( i );
325 m_rOStm.WriteUInt16( rColor.
GetRed() << 8 );
327 for ( sal_uInt32 i = 0;
i < mnColors;
i++ )
329 const BitmapColor& rColor = mpAcc->GetPaletteColor( i );
330 m_rOStm.WriteUInt16( rColor.
GetGreen() << 8 );
332 for ( sal_uInt32 i = 0;
i < mnColors;
i++ )
334 const BitmapColor& rColor = mpAcc->GetPaletteColor( i );
335 m_rOStm.WriteUInt16( rColor.
GetBlue() << 8 );
340void TIFFWriter::ImplWriteBody()
346 sal_uInt64 nGfxBegin = m_rOStm.Tell();
347 m_rOStm.Seek( mnBitmapPos + 8 );
348 m_rOStm.WriteUInt32( nGfxBegin - mnStreamOfs );
349 m_rOStm.Seek( nGfxBegin );
353 switch( mnBitsPerPixel )
357 for ( y = 0;
y <
mnHeight;
y++, mnCurAllPictHeight++ )
359 ImplCallback( 100 * mnCurAllPictHeight / mnSumOfAllPictHeight );
360 Scanline pScanline = mpAcc->GetScanline( y );
363 const BitmapColor& rColor = mpAcc->GetPixelFromData( pScanline, x );
364 Compress( rColor.
GetRed() );
374 for ( y = 0;
y <
mnHeight;
y++, mnCurAllPictHeight++ )
376 ImplCallback( 100 * mnCurAllPictHeight / mnSumOfAllPictHeight );
377 Scanline pScanline = mpAcc->GetScanline( y );
380 Compress( mpAcc->GetIndexFromData( pScanline, x ) );
388 for ( nShift = 0, y = 0;
y <
mnHeight;
y++, mnCurAllPictHeight++ )
390 ImplCallback( 100 * mnCurAllPictHeight / mnSumOfAllPictHeight );
391 Scanline pScanline = mpAcc->GetScanline( y );
392 for ( x = 0;
x <
mnWidth;
x++, nShift++ )
395 nTemp = ( mpAcc->GetIndexFromData( pScanline, x ) << 4 );
397 Compress(
static_cast<sal_uInt8>( nTemp | ( mpAcc->GetIndexFromData( pScanline, x ) & 0xf ) ) );
408 for ( y = 0;
y <
mnHeight;
y++, mnCurAllPictHeight++ )
410 ImplCallback( 100 * mnCurAllPictHeight / mnSumOfAllPictHeight );
411 Scanline pScanline = mpAcc->GetScanline( y );
415 j |= ( ( ~mpAcc->GetIndexFromData( pScanline, x ) ) & 1 );
424 Compress(
static_cast<sal_uInt8>(j << ( ( ( x & 7) ^ 7 ) + 1 ) ) );
440 if ( mnStripByteCountPos && mbStatus )
442 sal_uInt64 nGfxEnd = m_rOStm.Tell();
443 m_rOStm.Seek( mnStripByteCountPos + 8 );
444 m_rOStm.WriteUInt32( nGfxEnd - nGfxBegin );
445 m_rOStm.Seek( nGfxEnd );
450void TIFFWriter::ImplWriteResolution( sal_uInt64 nStreamPos, sal_uInt32 nResolutionUnit )
452 sal_uInt64 nCurrentPos = m_rOStm.Tell();
453 m_rOStm.Seek( nStreamPos + 8 );
454 m_rOStm.WriteUInt32( nCurrentPos - mnStreamOfs );
455 m_rOStm.Seek( nCurrentPos );
456 m_rOStm.WriteUInt32( 1 );
457 m_rOStm.WriteUInt32( nResolutionUnit );
461void TIFFWriter::ImplWriteTag( sal_uInt16 nTagID, sal_uInt16 nDataType, sal_uInt32 nNumberOfItems, sal_uInt32 nValue)
465 m_rOStm.WriteUInt16( nTagID );
466 m_rOStm.WriteUInt16( nDataType );
467 m_rOStm.WriteUInt32( nNumberOfItems );
468 if ( nDataType == 3 )
470 m_rOStm.WriteUInt32( nValue );
474inline void TIFFWriter::WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen )
476 dwShift |= ( nCode << ( nOffset - nCodeLen ) );
478 while ( nOffset < 24 )
480 m_rOStm.WriteUChar( dwShift >> 24 );
484 if ( nCode == 257 && nOffset != 32 )
486 m_rOStm.WriteUChar( dwShift >> 24 );
491void TIFFWriter::StartCompression()
496 nClearCode = 1 << nDataSize;
497 nEOICode = nClearCode + 1;
498 nTableSize = nEOICode + 1;
499 nCodeSize = nDataSize + 1;
504 pTable.reset(
new TIFFLZWCTreeNode[ 4096 ]);
506 for ( i = 0;
i < 4096;
i++)
508 pTable[
i ].pBrother = pTable[
i ].pFirstChild =
nullptr;
509 pTable[
i ].nCode =
i;
514 WriteBits( nClearCode, nCodeSize );
518void TIFFWriter::Compress(
sal_uInt8 nCompThis )
526 pPrefix = &pTable[nCompThis];
531 for( p = pPrefix->pFirstChild; p !=
nullptr; p =
p->pBrother )
533 if (
p->nValue == nV )
541 WriteBits( pPrefix->nCode, nCodeSize );
543 if ( nTableSize == 409 )
545 WriteBits( nClearCode, nCodeSize );
547 for ( i = 0;
i < nClearCode;
i++ )
548 pTable[ i ].pFirstChild =
nullptr;
550 nCodeSize = nDataSize + 1;
551 nTableSize = nEOICode + 1;
555 if( nTableSize ==
static_cast<sal_uInt16
>( ( 1 << nCodeSize ) - 1 ) )
558 p = &pTable[ nTableSize++ ];
559 p->pBrother = pPrefix->pFirstChild;
560 pPrefix->pFirstChild =
p;
562 p->pFirstChild =
nullptr;
565 pPrefix = &pTable[nV];
571void TIFFWriter::EndCompression()
574 WriteBits( pPrefix->nCode, nCodeSize );
576 WriteBits( nEOICode, nCodeSize );
582 TIFFWriter aWriter(rStream);
583 return aWriter.WriteTIFF( rGraphic, pFilterConfigItem );
const AnimationFrame & Get(sal_uInt16 nAnimation) const
bool Insert(const AnimationFrame &rAnimationFrame)
Bitmap GetBitmap(Color aTransparentReplaceColor) const
const Size & GetSizePixel() const
const MapMode & GetPrefMapMode() const
static void ReleaseAccess(BitmapInfoAccess *pAccess)
BitmapReadAccess * AcquireReadAccess()
vcl::PixelFormat getPixelFormat() const
sal_uInt8 GetBlue() const
sal_uInt8 GetGreen() const
css::uno::Reference< css::task::XStatusIndicator > GetStatusIndicator() const
Animation GetAnimation() const
BitmapEx GetBitmapEx(const GraphicConversionParameters &rParameters=GraphicConversionParameters()) const
SAL_WARN_UNUSED_RESULT Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
constexpr tools::Long Height() const
#define PlanarConfiguration
bool ExportTiffGraphicImport(SvStream &rStream, const Graphic &rGraphic, const FilterConfigItem *pFilterConfigItem)
#define PhotometricInterpretation
constexpr sal_uInt16 pixelFormatBitCount(PixelFormat ePixelFormat)