merge the formfield patch from ooo-build
[ooovba.git] / goodies / source / filter.vcl / etiff / etiff.cxx
blobe12972707cb23987a9a2ef997df5d19839aa82ad
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: etiff.cxx,v $
10 * $Revision: 1.10 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_goodies.hxx"
34 #include <vcl/graph.hxx>
35 #include <vcl/svapp.hxx>
36 #include <vcl/msgbox.hxx>
37 #include <vcl/bmpacc.hxx>
38 #include <svtools/solar.hrc>
39 #include <svtools/fltcall.hxx>
40 #include <svtools/FilterConfigItem.hxx>
42 #define NewSubfileType 254
43 #define ImageWidth 256
44 #define ImageLength 257
45 #define BitsPerSample 258
46 #define Compression 259
47 #define PhotometricInterpretation 262
48 #define StripOffsets 273
49 #define SamplesPerPixel 277
50 #define RowsPerStrip 278
51 #define StripByteCounts 279
52 #define XResolution 282
53 #define YResolution 283
54 #define PlanarConfiguration 284
55 #define ResolutionUnit 296
56 #define ColorMap 320
57 #define ReferenceBlackWhite 532
59 // -------------
60 // - TIFFWriter -
61 // -------------
63 struct TIFFLZWCTreeNode
66 TIFFLZWCTreeNode* pBrother; // naechster Knoten, der den selben Vater hat
67 TIFFLZWCTreeNode* pFirstChild; // erster Sohn
68 USHORT nCode; // Der Code fuer den String von Pixelwerten, der sich ergibt, wenn
69 USHORT nValue; // Der Pixelwert
72 class TIFFWriter
74 private:
76 SvStream* mpOStm;
77 UINT32 mnStreamOfs;
79 BOOL mbStatus;
80 BitmapReadAccess* mpAcc;
82 UINT32 mnWidth, mnHeight, mnColors;
83 UINT32 mnCurAllPictHeight;
84 UINT32 mnSumOfAllPictHeight;
85 UINT32 mnBitsPerPixel;
86 UINT32 mnLastPercent;
88 UINT32 mnLatestIfdPos;
89 UINT16 mnTagCount; // number of tags already written
90 UINT32 mnCurrentTagCountPos; // offset to the position where the current
91 // tag count is to insert
93 UINT32 mnXResPos; // if != 0 this DWORDs stores the
94 UINT32 mnYResPos; // actual streamposition of the
95 UINT32 mnPalPos; // Tag Entry
96 UINT32 mnBitmapPos;
97 UINT32 mnStripByteCountPos;
99 TIFFLZWCTreeNode* pTable;
100 TIFFLZWCTreeNode* pPrefix;
101 USHORT nDataSize;
102 USHORT nClearCode;
103 USHORT nEOICode;
104 USHORT nTableSize;
105 USHORT nCodeSize;
106 ULONG nOffset;
107 ULONG dwShift;
109 com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator > xStatusIndicator;
111 void ImplCallback( UINT32 nPercent );
112 BOOL ImplWriteHeader( BOOL bMultiPage );
113 void ImplWritePalette();
114 BOOL ImplWriteBody();
115 void ImplWriteTag( UINT16 TagID, UINT16 DataType, UINT32 NumberOfItems, UINT32 Value);
116 void ImplWriteResolution( ULONG nStreamPos, sal_uInt32 nResolutionUnit );
117 void StartCompression();
118 void Compress( BYTE nSrc );
119 void EndCompression();
120 inline void WriteBits( USHORT nCode, USHORT nCodeLen );
122 public:
124 TIFFWriter();
125 ~TIFFWriter();
127 BOOL WriteTIFF( const Graphic& rGraphic, SvStream& rTIFF, FilterConfigItem* pFilterConfigItem );
130 // ------------------------------------------------------------------------
132 TIFFWriter::TIFFWriter() :
133 mbStatus ( TRUE ),
134 mpAcc ( NULL ),
135 mnCurAllPictHeight ( 0 ),
136 mnSumOfAllPictHeight( 0 ),
137 mnLastPercent ( 0 ),
138 mnXResPos ( 0 ),
139 mnYResPos ( 0 ),
140 mnBitmapPos ( 0 ),
141 mnStripByteCountPos ( 0 )
145 // ------------------------------------------------------------------------
147 TIFFWriter::~TIFFWriter()
151 // ------------------------------------------------------------------------
153 BOOL TIFFWriter::WriteTIFF( const Graphic& rGraphic, SvStream& rTIFF, FilterConfigItem* pFilterConfigItem)
155 ULONG* pDummy = new ULONG; delete pDummy; // damit unter OS/2
156 // das richtige (Tools-)new
157 // verwendet wird, da es sonst
158 // in dieser DLL nur Vector-news
159 // gibt;
161 if ( pFilterConfigItem )
163 xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
164 if ( xStatusIndicator.is() )
166 rtl::OUString aMsg;
167 xStatusIndicator->start( aMsg, 100 );
171 // #i69169# copy stream
172 mpOStm = &rTIFF;
174 const UINT16 nOldFormat = mpOStm->GetNumberFormatInt();
175 mnStreamOfs = mpOStm->Tell();
177 // we will use the BIG Endian Mode
178 // TIFF header
179 mpOStm->SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
180 *mpOStm << (UINT32)0x4d4d002a; // TIFF identifier
181 mnLatestIfdPos = mpOStm->Tell();
182 *mpOStm << (UINT32)0;
184 Animation aAnimation;
185 Bitmap aBmp;
187 if( mbStatus )
189 if ( rGraphic.IsAnimated() )
190 aAnimation = rGraphic.GetAnimation();
191 else
193 AnimationBitmap aAnimationBitmap( rGraphic.GetBitmap(), Point(), Size() );
194 aAnimation.Insert( aAnimationBitmap );
197 USHORT i;
198 for ( i = 0; i < aAnimation.Count(); i++ )
199 mnSumOfAllPictHeight += aAnimation.Get( i ).aBmpEx.GetSizePixel().Height();
201 for ( i = 0; mbStatus && ( i < aAnimation.Count() ); i++ )
203 mnPalPos = 0;
204 const AnimationBitmap& rAnimationBitmap = aAnimation.Get( i );
205 aBmp = rAnimationBitmap.aBmpEx.GetBitmap();
206 mpAcc = aBmp.AcquireReadAccess();
207 if ( mpAcc )
209 mnBitsPerPixel = aBmp.GetBitCount();
211 // export code below only handles four discrete cases
212 mnBitsPerPixel =
213 mnBitsPerPixel <= 1 ? 1 : mnBitsPerPixel <= 4 ? 4 : mnBitsPerPixel <= 8 ? 8 : 24;
215 if ( ImplWriteHeader( ( aAnimation.Count() > 0 ) ) )
217 Size aDestMapSize( 300, 300 );
218 const MapMode aMapMode( aBmp.GetPrefMapMode() );
219 if ( aMapMode.GetMapUnit() != MAP_PIXEL )
221 const Size aPrefSize( rGraphic.GetPrefSize() );
222 aDestMapSize = OutputDevice::LogicToLogic( aPrefSize, aMapMode, MAP_INCH );
224 ImplWriteResolution( mnXResPos, aDestMapSize.Width() );
225 ImplWriteResolution( mnYResPos, aDestMapSize.Height() );
226 if ( mnPalPos )
227 ImplWritePalette();
228 ImplWriteBody();
230 UINT32 nCurPos = mpOStm->Tell();
231 mpOStm->Seek( mnCurrentTagCountPos );
232 *mpOStm << mnTagCount;
233 mpOStm->Seek( nCurPos );
235 aBmp.ReleaseAccess( mpAcc );
237 else
238 mbStatus = FALSE;
241 mpOStm->SetNumberFormatInt( nOldFormat );
243 if ( xStatusIndicator.is() )
244 xStatusIndicator->end();
246 return mbStatus;
249 // ------------------------------------------------------------------------
251 void TIFFWriter::ImplCallback( UINT32 nPercent )
253 if ( xStatusIndicator.is() )
255 if( nPercent >= mnLastPercent + 3 )
257 mnLastPercent = nPercent;
258 if ( nPercent <= 100 )
259 xStatusIndicator->setValue( nPercent );
265 // ------------------------------------------------------------------------
267 BOOL TIFFWriter::ImplWriteHeader( BOOL bMultiPage )
269 mnTagCount = 0;
270 mnWidth = mpAcc->Width();
271 mnHeight = mpAcc->Height();
273 if ( mnWidth && mnHeight && mnBitsPerPixel && mbStatus )
275 UINT32 nCurrentPos = mpOStm->Tell();
276 mpOStm->Seek( mnLatestIfdPos );
277 *mpOStm << (UINT32)( nCurrentPos - mnStreamOfs ); // offset to the IFD
278 mpOStm->Seek( nCurrentPos );
280 // (OFS8) TIFF image file directory (IFD)
281 mnCurrentTagCountPos = mpOStm->Tell();
282 *mpOStm << (UINT16)0; // the number of tagentrys is to insert later
284 UINT32 nSubFileFlags = 0;
285 if ( bMultiPage )
286 nSubFileFlags |= 2;
287 ImplWriteTag( NewSubfileType, 4, 1, nSubFileFlags );
288 ImplWriteTag( ImageWidth, 4, 1, mnWidth );
289 ImplWriteTag( ImageLength, 4, 1, mnHeight);
290 ImplWriteTag( BitsPerSample, 3, 1, ( mnBitsPerPixel == 24 ) ? 8 : mnBitsPerPixel );
291 ImplWriteTag( Compression, 3, 1, 5 );
292 BYTE nTemp;
293 switch ( mnBitsPerPixel )
295 case 1 :
296 nTemp = 1;
297 break;
298 case 4 :
299 case 8 :
300 nTemp = 3;
301 break;
302 case 24:
303 nTemp = 2;
304 break;
305 default:
306 nTemp = 0; // -Wall set a default...
307 break;
309 ImplWriteTag( PhotometricInterpretation, 3, 1, nTemp );
310 mnBitmapPos = mpOStm->Tell();
311 ImplWriteTag( StripOffsets, 4, 1, 0 );
312 ImplWriteTag( SamplesPerPixel, 3, 1, ( mnBitsPerPixel == 24 ) ? 3 : 1 );
313 ImplWriteTag( RowsPerStrip, 4, 1, mnHeight ); //0xffffffff );
314 mnStripByteCountPos = mpOStm->Tell();
315 ImplWriteTag( StripByteCounts, 4, 1, ( ( mnWidth * mnBitsPerPixel * mnHeight ) + 7 ) >> 3 );
316 mnXResPos = mpOStm->Tell();
317 ImplWriteTag( XResolution, 5, 1, 0 );
318 mnYResPos = mpOStm->Tell();
319 ImplWriteTag( YResolution, 5, 1, 0 );
320 if ( mnBitsPerPixel != 1 )
321 ImplWriteTag( PlanarConfiguration, 3, 1, 1 ); // ( RGB ORDER )
322 ImplWriteTag( ResolutionUnit, 3, 1, 2); // Resolution Unit is Inch
323 if ( ( mnBitsPerPixel == 4 ) || ( mnBitsPerPixel == 8 ) )
325 mnColors = mpAcc->GetPaletteEntryCount();
326 mnPalPos = mpOStm->Tell();
327 ImplWriteTag( ColorMap, 3, 3 * mnColors, 0 );
330 // and last we write zero to close the num dir entries list
331 mnLatestIfdPos = mpOStm->Tell();
332 *mpOStm << (UINT32)0; // there are no more IFD
334 else
335 mbStatus = FALSE;
337 return mbStatus;
340 // ------------------------------------------------------------------------
342 void TIFFWriter::ImplWritePalette()
344 USHORT i;
345 ULONG nCurrentPos = mpOStm->Tell();
346 mpOStm->Seek( mnPalPos + 8 ); // the palette tag entry needs the offset
347 *mpOStm << static_cast<sal_uInt32>(nCurrentPos - mnStreamOfs); // to the palette colors
348 mpOStm->Seek( nCurrentPos );
350 for ( i = 0; i < mnColors; i++ )
352 const BitmapColor& rColor = mpAcc->GetPaletteColor( i );
353 *mpOStm << (UINT16)( rColor.GetRed() << 8 );
355 for ( i = 0; i < mnColors; i++ )
357 const BitmapColor& rColor = mpAcc->GetPaletteColor( i );
358 *mpOStm << (UINT16)( rColor.GetGreen() << 8 );
360 for ( i = 0; i < mnColors; i++ )
362 const BitmapColor& rColor = mpAcc->GetPaletteColor( i );
363 *mpOStm << (UINT16)( rColor.GetBlue() << 8 );
367 // ------------------------------------------------------------------------
369 BOOL TIFFWriter::ImplWriteBody()
371 BYTE nTemp = 0;
372 BYTE nShift;
373 ULONG j, x, y;
375 ULONG nGfxBegin = mpOStm->Tell();
376 mpOStm->Seek( mnBitmapPos + 8 ); // the strip offset tag entry needs the offset
377 *mpOStm << static_cast<sal_uInt32>(nGfxBegin - mnStreamOfs); // to the bitmap data
378 mpOStm->Seek( nGfxBegin );
380 StartCompression();
382 switch( mnBitsPerPixel )
384 case 24 :
386 for ( y = 0; y < mnHeight; y++, mnCurAllPictHeight++ )
388 ImplCallback( 100 * mnCurAllPictHeight / mnSumOfAllPictHeight );
389 for ( x = 0; x < mnWidth; x++ )
391 const BitmapColor& rColor = mpAcc->GetPixel( y, x );
392 Compress( rColor.GetRed() );
393 Compress( rColor.GetGreen() );
394 Compress( rColor.GetBlue() );
398 break;
400 case 8 :
402 for ( y = 0; y < mnHeight; y++, mnCurAllPictHeight++ )
404 ImplCallback( 100 * mnCurAllPictHeight / mnSumOfAllPictHeight );
405 for ( x = 0; x < mnWidth; x++ )
407 Compress( mpAcc->GetPixel( y, x ) );
411 break;
413 case 4 :
415 for ( nShift = 0, y = 0; y < mnHeight; y++, mnCurAllPictHeight++ )
417 ImplCallback( 100 * mnCurAllPictHeight / mnSumOfAllPictHeight );
418 for ( x = 0; x < mnWidth; x++, nShift++ )
420 if (!( nShift & 1 ))
421 nTemp = ( (BYTE)mpAcc->GetPixel( y, x ) << 4 );
422 else
423 Compress( (BYTE)( nTemp | ( mpAcc->GetPixel( y, x ) & 0xf ) ) );
425 if ( nShift & 1 )
426 Compress( nTemp );
429 break;
431 case 1 :
433 j = 1;
434 for ( y = 0; y < mnHeight; y++, mnCurAllPictHeight++ )
436 ImplCallback( 100 * mnCurAllPictHeight / mnSumOfAllPictHeight );
437 for ( x = 0; x < mnWidth; x++)
439 j <<= 1;
440 j |= ( ( ~mpAcc->GetPixel( y, x ) ) & 1 );
441 if ( j & 0x100 )
443 Compress( (BYTE)j );
444 j = 1;
447 if ( j != 1 )
449 Compress( (BYTE)(j << ( ( ( x & 7) ^ 7 ) + 1 ) ) );
450 j = 1;
454 break;
456 default:
458 mbStatus = FALSE;
460 break;
463 EndCompression();
465 if ( mnStripByteCountPos && mbStatus )
467 ULONG nGfxEnd = mpOStm->Tell();
468 mpOStm->Seek( mnStripByteCountPos + 8 );
469 *mpOStm << static_cast<sal_uInt32>( nGfxEnd - nGfxBegin ); // mnStripByteCountPos needs the size of the compression data
470 mpOStm->Seek( nGfxEnd );
472 return mbStatus;
475 // ------------------------------------------------------------------------
477 void TIFFWriter::ImplWriteResolution( ULONG nStreamPos, sal_uInt32 nResolutionUnit )
479 ULONG nCurrentPos = mpOStm->Tell();
480 mpOStm->Seek( nStreamPos + 8 );
481 *mpOStm << (UINT32)nCurrentPos - mnStreamOfs;
482 mpOStm->Seek( nCurrentPos );
483 *mpOStm << (UINT32)1;
484 *mpOStm << nResolutionUnit;
487 // ------------------------------------------------------------------------
489 void TIFFWriter::ImplWriteTag( UINT16 nTagID, UINT16 nDataType, UINT32 nNumberOfItems, UINT32 nValue)
491 mnTagCount++;
493 *mpOStm << nTagID;
494 *mpOStm << nDataType;
495 *mpOStm << nNumberOfItems;
496 if ( nDataType == 3 )
497 nValue <<=16; // in Big Endian Mode WORDS needed to be shifted to a DWORD
498 *mpOStm << nValue;
501 // ------------------------------------------------------------------------
503 inline void TIFFWriter::WriteBits( USHORT nCode, USHORT nCodeLen )
505 dwShift |= ( nCode << ( nOffset - nCodeLen ) );
506 nOffset -= nCodeLen;
507 while ( nOffset < 24 )
509 *mpOStm << (BYTE)( dwShift >> 24 );
510 dwShift <<= 8;
511 nOffset += 8;
513 if ( nCode == 257 && nOffset != 32 )
515 *mpOStm << (BYTE)( dwShift >> 24 );
519 // ------------------------------------------------------------------------
521 void TIFFWriter::StartCompression()
523 USHORT i;
524 nDataSize = 8;
526 nClearCode = 1 << nDataSize;
527 nEOICode = nClearCode + 1;
528 nTableSize = nEOICode + 1;
529 nCodeSize = nDataSize + 1;
531 nOffset = 32; // anzahl freier bits in dwShift
532 dwShift = 0;
534 pTable = new TIFFLZWCTreeNode[ 4096 ];
536 for ( i = 0; i < 4096; i++)
538 pTable[ i ].pBrother = pTable[ i ].pFirstChild = NULL;
539 pTable[ i ].nValue = (BYTE)( pTable[ i ].nCode = i );
542 pPrefix = NULL;
543 WriteBits( nClearCode, nCodeSize );
546 // ------------------------------------------------------------------------
548 void TIFFWriter::Compress( BYTE nCompThis )
550 TIFFLZWCTreeNode* p;
551 USHORT i;
552 BYTE nV;
554 if( !pPrefix )
556 pPrefix = pTable + nCompThis;
558 else
560 nV = nCompThis;
561 for( p = pPrefix->pFirstChild; p != NULL; p = p->pBrother )
563 if ( p->nValue == nV )
564 break;
567 if( p )
568 pPrefix = p;
569 else
571 WriteBits( pPrefix->nCode, nCodeSize );
573 if ( nTableSize == 409 )
575 WriteBits( nClearCode, nCodeSize );
577 for ( i = 0; i < nClearCode; i++ )
578 pTable[ i ].pFirstChild = NULL;
580 nCodeSize = nDataSize + 1;
581 nTableSize = nEOICode + 1;
583 else
585 if( nTableSize == (USHORT)( ( 1 << nCodeSize ) - 1 ) )
586 nCodeSize++;
588 p = pTable + ( nTableSize++ );
589 p->pBrother = pPrefix->pFirstChild;
590 pPrefix->pFirstChild = p;
591 p->nValue = nV;
592 p->pFirstChild = NULL;
595 pPrefix = pTable + nV;
600 // ------------------------------------------------------------------------
602 void TIFFWriter::EndCompression()
604 if( pPrefix )
605 WriteBits( pPrefix->nCode, nCodeSize );
607 WriteBits( nEOICode, nCodeSize );
608 delete[] pTable;
611 // ------------------------------------------------------------------------
613 // ---------------------
614 // - exported function -
615 // ---------------------
617 extern "C" BOOL __LOADONCALLAPI GraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pFilterConfigItem, BOOL )
619 return TIFFWriter().WriteTIFF( rGraphic, rStream, pFilterConfigItem );
622 #ifndef GCC
623 #endif
625 // ---------------
626 // - Win16 trash -
627 // ---------------
629 #ifdef WIN
631 static HINSTANCE hDLLInst = 0;
633 extern "C" int CALLBACK LibMain( HINSTANCE hDLL, WORD, WORD nHeap, LPSTR )
635 if ( nHeap )
636 UnlockData( 0 );
638 hDLLInst = hDLL;
640 return TRUE;
643 // ------------------------------------------------------------------------
645 extern "C" int CALLBACK WEP( int )
647 return 1;
650 #endif