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