15900e8ecSAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
35900e8ecSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
45900e8ecSAndrew Rist * or more contributor license agreements. See the NOTICE file
55900e8ecSAndrew Rist * distributed with this work for additional information
65900e8ecSAndrew Rist * regarding copyright ownership. The ASF licenses this file
75900e8ecSAndrew Rist * to you under the Apache License, Version 2.0 (the
85900e8ecSAndrew Rist * "License"); you may not use this file except in compliance
95900e8ecSAndrew Rist * with the License. You may obtain a copy of the License at
105900e8ecSAndrew Rist *
115900e8ecSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
125900e8ecSAndrew Rist *
135900e8ecSAndrew Rist * Unless required by applicable law or agreed to in writing,
145900e8ecSAndrew Rist * software distributed under the License is distributed on an
155900e8ecSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
165900e8ecSAndrew Rist * KIND, either express or implied. See the License for the
175900e8ecSAndrew Rist * specific language governing permissions and limitations
185900e8ecSAndrew Rist * under the License.
195900e8ecSAndrew Rist *
205900e8ecSAndrew Rist *************************************************************/
215900e8ecSAndrew Rist
225900e8ecSAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_svtools.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir #define _GIFPRIVATE
28cdf0e10cSrcweir
29cdf0e10cSrcweir #include "decode.hxx"
30cdf0e10cSrcweir #include "gifread.hxx"
31cdf0e10cSrcweir
32cdf0e10cSrcweir // -----------
33cdf0e10cSrcweir // - Defines -
34cdf0e10cSrcweir // -----------
35cdf0e10cSrcweir
36cdf0e10cSrcweir #define NO_PENDING( rStm ) ( ( rStm ).GetError() != ERRCODE_IO_PENDING )
37cdf0e10cSrcweir
38cdf0e10cSrcweir // -------------
39cdf0e10cSrcweir // - GIFReader -
40cdf0e10cSrcweir // -------------
41cdf0e10cSrcweir
GIFReader(SvStream & rStm)42cdf0e10cSrcweir GIFReader::GIFReader( SvStream& rStm ) :
43cdf0e10cSrcweir aGPalette ( 256 ),
44cdf0e10cSrcweir aLPalette ( 256 ),
45cdf0e10cSrcweir rIStm ( rStm ),
46cdf0e10cSrcweir pAcc8 ( NULL ),
47cdf0e10cSrcweir pAcc1 ( NULL ),
48cdf0e10cSrcweir nLastPos ( rStm.Tell() ),
49cdf0e10cSrcweir nLogWidth100 ( 0UL ),
50cdf0e10cSrcweir nLogHeight100 ( 0UL ),
51cdf0e10cSrcweir nLoops ( 1 ),
52cdf0e10cSrcweir eActAction ( GLOBAL_HEADER_READING ),
53cdf0e10cSrcweir bGCTransparent ( sal_False ),
54cdf0e10cSrcweir bImGraphicReady ( sal_False )
55cdf0e10cSrcweir {
56cdf0e10cSrcweir maUpperName = UniString::CreateFromAscii( "SVIGIF", 6 );
57cdf0e10cSrcweir pSrcBuf = new sal_uInt8[ 256 ];
58cdf0e10cSrcweir ClearImageExtensions();
59cdf0e10cSrcweir }
60cdf0e10cSrcweir
61cdf0e10cSrcweir // ------------------------------------------------------------------------
62cdf0e10cSrcweir
~GIFReader()63cdf0e10cSrcweir GIFReader::~GIFReader()
64cdf0e10cSrcweir {
65cdf0e10cSrcweir aImGraphic.SetContext( NULL );
66cdf0e10cSrcweir
67cdf0e10cSrcweir if( pAcc1 )
68cdf0e10cSrcweir aBmp1.ReleaseAccess( pAcc1 );
69cdf0e10cSrcweir
70cdf0e10cSrcweir if( pAcc8 )
71cdf0e10cSrcweir aBmp8.ReleaseAccess( pAcc8 );
72cdf0e10cSrcweir
73cdf0e10cSrcweir delete[] pSrcBuf;
74cdf0e10cSrcweir }
75cdf0e10cSrcweir
76cdf0e10cSrcweir // ------------------------------------------------------------------------
77cdf0e10cSrcweir
ClearImageExtensions()78cdf0e10cSrcweir void GIFReader::ClearImageExtensions()
79cdf0e10cSrcweir {
80cdf0e10cSrcweir nGCDisposalMethod = 0;
81cdf0e10cSrcweir bGCTransparent = sal_False;
82cdf0e10cSrcweir nTimer = 0;
83cdf0e10cSrcweir }
84cdf0e10cSrcweir
85cdf0e10cSrcweir // ------------------------------------------------------------------------
86cdf0e10cSrcweir
CreateBitmaps(long nWidth,long nHeight,BitmapPalette * pPal,sal_Bool bWatchForBackgroundColor)87cdf0e10cSrcweir sal_Bool GIFReader::CreateBitmaps( long nWidth, long nHeight, BitmapPalette* pPal,
88cdf0e10cSrcweir sal_Bool bWatchForBackgroundColor )
89cdf0e10cSrcweir {
90cdf0e10cSrcweir const Size aSize( nWidth, nHeight );
91cdf0e10cSrcweir
92cdf0e10cSrcweir if( bGCTransparent )
93cdf0e10cSrcweir {
94cdf0e10cSrcweir const Color aWhite( COL_WHITE );
95cdf0e10cSrcweir
96cdf0e10cSrcweir aBmp1 = Bitmap( aSize, 1 );
97cdf0e10cSrcweir
98cdf0e10cSrcweir if( !aAnimation.Count() )
99cdf0e10cSrcweir aBmp1.Erase( aWhite );
100cdf0e10cSrcweir
101cdf0e10cSrcweir pAcc1 = aBmp1.AcquireWriteAccess();
102cdf0e10cSrcweir
103cdf0e10cSrcweir if( pAcc1 )
104cdf0e10cSrcweir {
105cdf0e10cSrcweir cTransIndex1 = (sal_uInt8) pAcc1->GetBestPaletteIndex( aWhite );
106cdf0e10cSrcweir cNonTransIndex1 = cTransIndex1 ? 0 : 1;
107cdf0e10cSrcweir }
108cdf0e10cSrcweir else
109cdf0e10cSrcweir bStatus = sal_False;
110cdf0e10cSrcweir }
111cdf0e10cSrcweir
112cdf0e10cSrcweir if( bStatus )
113cdf0e10cSrcweir {
114cdf0e10cSrcweir aBmp8 = Bitmap( aSize, 8, pPal );
115cdf0e10cSrcweir
116cdf0e10cSrcweir if( !!aBmp8 && bWatchForBackgroundColor && aAnimation.Count() )
117cdf0e10cSrcweir aBmp8.Erase( (*pPal)[ nBackgroundColor ] );
118cdf0e10cSrcweir else
119cdf0e10cSrcweir aBmp8.Erase( Color( COL_WHITE ) );
120cdf0e10cSrcweir
121cdf0e10cSrcweir pAcc8 = aBmp8.AcquireWriteAccess();
122cdf0e10cSrcweir bStatus = ( pAcc8 != NULL );
123cdf0e10cSrcweir }
124cdf0e10cSrcweir
125cdf0e10cSrcweir return bStatus;
126cdf0e10cSrcweir }
127cdf0e10cSrcweir
128cdf0e10cSrcweir // ------------------------------------------------------------------------
129cdf0e10cSrcweir
ReadGlobalHeader()130cdf0e10cSrcweir sal_Bool GIFReader::ReadGlobalHeader()
131cdf0e10cSrcweir {
132cdf0e10cSrcweir char pBuf[ 7 ];
133cdf0e10cSrcweir sal_uInt8 nRF;
134cdf0e10cSrcweir sal_uInt8 nAspect;
135cdf0e10cSrcweir sal_Bool bRet = sal_False;
136cdf0e10cSrcweir
137cdf0e10cSrcweir rIStm.Read( pBuf, 6 );
138cdf0e10cSrcweir if( NO_PENDING( rIStm ) )
139cdf0e10cSrcweir {
140cdf0e10cSrcweir pBuf[ 6 ] = 0;
141cdf0e10cSrcweir if( !strcmp( pBuf, "GIF87a" ) || !strcmp( pBuf, "GIF89a" ) )
142cdf0e10cSrcweir {
143cdf0e10cSrcweir rIStm.Read( pBuf, 7 );
144cdf0e10cSrcweir if( NO_PENDING( rIStm ) )
145cdf0e10cSrcweir {
146cdf0e10cSrcweir SvMemoryStream aMemStm;
147cdf0e10cSrcweir
148cdf0e10cSrcweir aMemStm.SetBuffer( pBuf, 7, sal_False, 7 );
149cdf0e10cSrcweir aMemStm >> nGlobalWidth;
150cdf0e10cSrcweir aMemStm >> nGlobalHeight;
151cdf0e10cSrcweir aMemStm >> nRF;
152cdf0e10cSrcweir aMemStm >> nBackgroundColor;
153cdf0e10cSrcweir aMemStm >> nAspect;
154cdf0e10cSrcweir
155cdf0e10cSrcweir bGlobalPalette = (sal_Bool) ( nRF & 0x80 );
156cdf0e10cSrcweir
157cdf0e10cSrcweir if( bGlobalPalette )
158cdf0e10cSrcweir ReadPaletteEntries( &aGPalette, 1 << ( ( nRF & 7 ) + 1 ) );
159cdf0e10cSrcweir else
160cdf0e10cSrcweir nBackgroundColor = 0;
161cdf0e10cSrcweir
162cdf0e10cSrcweir if( NO_PENDING( rIStm ) )
163cdf0e10cSrcweir bRet = sal_True;
164cdf0e10cSrcweir }
165cdf0e10cSrcweir }
166cdf0e10cSrcweir else
167cdf0e10cSrcweir bStatus = sal_False;
168cdf0e10cSrcweir }
169cdf0e10cSrcweir
170cdf0e10cSrcweir return bRet;
171cdf0e10cSrcweir }
172cdf0e10cSrcweir
173cdf0e10cSrcweir // ------------------------------------------------------------------------
174cdf0e10cSrcweir
ReadPaletteEntries(BitmapPalette * pPal,sal_uLong nCount)175cdf0e10cSrcweir void GIFReader::ReadPaletteEntries( BitmapPalette* pPal, sal_uLong nCount )
176cdf0e10cSrcweir {
177cdf0e10cSrcweir const sal_uLong nLen = 3UL * nCount;
178cdf0e10cSrcweir sal_uInt8* pBuf = new sal_uInt8[ nLen ];
179cdf0e10cSrcweir
180cdf0e10cSrcweir rIStm.Read( pBuf, nLen );
181cdf0e10cSrcweir if( NO_PENDING( rIStm ) )
182cdf0e10cSrcweir {
183cdf0e10cSrcweir sal_uInt8* pTmp = pBuf;
184cdf0e10cSrcweir
185cdf0e10cSrcweir for( sal_uLong i = 0UL; i < nCount; )
186cdf0e10cSrcweir {
187cdf0e10cSrcweir BitmapColor& rColor = (*pPal)[ (sal_uInt16) i++ ];
188cdf0e10cSrcweir
189cdf0e10cSrcweir rColor.SetRed( *pTmp++ );
190cdf0e10cSrcweir rColor.SetGreen( *pTmp++ );
191cdf0e10cSrcweir rColor.SetBlue( *pTmp++ );
192cdf0e10cSrcweir }
193cdf0e10cSrcweir
194cdf0e10cSrcweir // nach Moeglichkeit noch einige Standardfarben unterbringen
195cdf0e10cSrcweir if( nCount < 256UL )
196cdf0e10cSrcweir {
197cdf0e10cSrcweir (*pPal)[ 255UL ] = Color( COL_WHITE );
198cdf0e10cSrcweir
199cdf0e10cSrcweir if( nCount < 255UL )
200cdf0e10cSrcweir (*pPal)[ 254UL ] = Color( COL_BLACK );
201cdf0e10cSrcweir }
202cdf0e10cSrcweir }
203cdf0e10cSrcweir
204cdf0e10cSrcweir delete[] pBuf;
205cdf0e10cSrcweir }
206cdf0e10cSrcweir
207cdf0e10cSrcweir // ------------------------------------------------------------------------
208cdf0e10cSrcweir
ReadExtension()209cdf0e10cSrcweir sal_Bool GIFReader::ReadExtension()
210cdf0e10cSrcweir {
211cdf0e10cSrcweir sal_uInt8 cFunction;
212cdf0e10cSrcweir sal_uInt8 cSize;
213cdf0e10cSrcweir sal_uInt8 cByte;
214cdf0e10cSrcweir sal_Bool bRet = sal_False;
215cdf0e10cSrcweir sal_Bool bOverreadDataBlocks = sal_False;
216cdf0e10cSrcweir
217cdf0e10cSrcweir // Extension-Label
218cdf0e10cSrcweir rIStm >> cFunction;
219cdf0e10cSrcweir if( NO_PENDING( rIStm ) )
220cdf0e10cSrcweir {
221cdf0e10cSrcweir // Block-Laenge
222cdf0e10cSrcweir rIStm >> cSize;
223cdf0e10cSrcweir
224cdf0e10cSrcweir switch( cFunction )
225cdf0e10cSrcweir {
226cdf0e10cSrcweir // 'Graphic Control Extension'
227cdf0e10cSrcweir case( 0xf9 ) :
228cdf0e10cSrcweir {
229cdf0e10cSrcweir sal_uInt8 cFlags;
230cdf0e10cSrcweir
231cdf0e10cSrcweir rIStm >> cFlags;
232cdf0e10cSrcweir rIStm >> nTimer;
233cdf0e10cSrcweir rIStm >> nGCTransparentIndex;
234cdf0e10cSrcweir rIStm >> cByte;
235cdf0e10cSrcweir
236cdf0e10cSrcweir if ( NO_PENDING( rIStm ) )
237cdf0e10cSrcweir {
238cdf0e10cSrcweir nGCDisposalMethod = ( cFlags >> 2) & 7;
239cdf0e10cSrcweir bGCTransparent = ( cFlags & 1 ) ? sal_True : sal_False;
240cdf0e10cSrcweir bStatus = ( cSize == 4 ) && ( cByte == 0 );
241cdf0e10cSrcweir bRet = sal_True;
242cdf0e10cSrcweir }
243cdf0e10cSrcweir }
244cdf0e10cSrcweir break;
245cdf0e10cSrcweir
246cdf0e10cSrcweir // Application-Extension
247cdf0e10cSrcweir case ( 0xff ) :
248cdf0e10cSrcweir {
249cdf0e10cSrcweir if ( NO_PENDING( rIStm ) )
250cdf0e10cSrcweir {
251cdf0e10cSrcweir // default diese Extension ueberlesen
252cdf0e10cSrcweir bOverreadDataBlocks = sal_True;
253cdf0e10cSrcweir
254cdf0e10cSrcweir // Appl.-Extension hat Laenge 11
255cdf0e10cSrcweir if ( cSize == 0x0b )
256cdf0e10cSrcweir {
257cdf0e10cSrcweir ByteString aAppId;
258cdf0e10cSrcweir ByteString aAppCode;
259cdf0e10cSrcweir
260cdf0e10cSrcweir rIStm.Read( aAppId.AllocBuffer( 8 ), 8 );
261cdf0e10cSrcweir rIStm.Read( aAppCode.AllocBuffer( 3 ), 3 );
262cdf0e10cSrcweir rIStm >> cSize;
263cdf0e10cSrcweir
264cdf0e10cSrcweir // NetScape-Extension
265cdf0e10cSrcweir if( aAppId == "NETSCAPE" && aAppCode == "2.0" && cSize == 3 )
266cdf0e10cSrcweir {
267cdf0e10cSrcweir rIStm >> cByte;
268cdf0e10cSrcweir
269cdf0e10cSrcweir // Loop-Extension
270cdf0e10cSrcweir if ( cByte == 0x01 )
271cdf0e10cSrcweir {
272cdf0e10cSrcweir rIStm >> cByte;
273cdf0e10cSrcweir nLoops = cByte;
274cdf0e10cSrcweir rIStm >> cByte;
275cdf0e10cSrcweir nLoops |= ( (sal_uInt16) cByte << 8 );
276cdf0e10cSrcweir rIStm >> cByte;
277cdf0e10cSrcweir
278cdf0e10cSrcweir bStatus = ( cByte == 0 );
279cdf0e10cSrcweir bRet = NO_PENDING( rIStm );
280cdf0e10cSrcweir bOverreadDataBlocks = sal_False;
281cdf0e10cSrcweir
282cdf0e10cSrcweir // Netscape interpretiert den LoopCount
283cdf0e10cSrcweir // als reine Anzahl der _Wiederholungen_;
284cdf0e10cSrcweir // bei uns ist es die Gesamtanzahl der
285cdf0e10cSrcweir // Durchlaeufe
286cdf0e10cSrcweir if( nLoops )
287cdf0e10cSrcweir nLoops++;
288cdf0e10cSrcweir }
289cdf0e10cSrcweir else
290cdf0e10cSrcweir rIStm.SeekRel( -1 );
291cdf0e10cSrcweir }
292cdf0e10cSrcweir else if ( aAppId == "STARDIV " && aAppCode == "5.0" && cSize == 9 )
293cdf0e10cSrcweir {
294cdf0e10cSrcweir rIStm >> cByte;
295cdf0e10cSrcweir
296cdf0e10cSrcweir // Loop-Extension
297cdf0e10cSrcweir if ( cByte == 0x01 )
298cdf0e10cSrcweir {
299cdf0e10cSrcweir rIStm >> nLogWidth100 >> nLogHeight100;
300cdf0e10cSrcweir rIStm >> cByte;
301cdf0e10cSrcweir bStatus = ( cByte == 0 );
302cdf0e10cSrcweir bRet = NO_PENDING( rIStm );
303cdf0e10cSrcweir bOverreadDataBlocks = sal_False;
304cdf0e10cSrcweir }
305cdf0e10cSrcweir else
306cdf0e10cSrcweir rIStm.SeekRel( -1 );
307cdf0e10cSrcweir }
308cdf0e10cSrcweir
309cdf0e10cSrcweir }
310cdf0e10cSrcweir }
311cdf0e10cSrcweir }
312cdf0e10cSrcweir break;
313cdf0e10cSrcweir
314cdf0e10cSrcweir // alles andere ueberlesen
315cdf0e10cSrcweir default:
316cdf0e10cSrcweir bOverreadDataBlocks = sal_True;
317cdf0e10cSrcweir break;
318cdf0e10cSrcweir }
319cdf0e10cSrcweir
320cdf0e10cSrcweir // Sub-Blocks ueberlesen
321cdf0e10cSrcweir if ( bOverreadDataBlocks )
322cdf0e10cSrcweir {
323cdf0e10cSrcweir bRet = sal_True;
324cdf0e10cSrcweir while( cSize && bStatus && !rIStm.IsEof() )
325cdf0e10cSrcweir {
326cdf0e10cSrcweir sal_uInt16 nCount = (sal_uInt16) cSize + 1;
327cdf0e10cSrcweir char* pBuffer = new char[ nCount ];
328cdf0e10cSrcweir
329cdf0e10cSrcweir bRet = sal_False;
330cdf0e10cSrcweir rIStm.Read( pBuffer, nCount );
331cdf0e10cSrcweir if( NO_PENDING( rIStm ) )
332cdf0e10cSrcweir {
333cdf0e10cSrcweir cSize = (sal_uInt8) pBuffer[ cSize ];
334cdf0e10cSrcweir bRet = sal_True;
335cdf0e10cSrcweir }
336cdf0e10cSrcweir else
337cdf0e10cSrcweir cSize = 0;
338cdf0e10cSrcweir
339cdf0e10cSrcweir delete[] pBuffer;
340cdf0e10cSrcweir }
341cdf0e10cSrcweir }
342cdf0e10cSrcweir }
343cdf0e10cSrcweir
344cdf0e10cSrcweir return bRet;
345cdf0e10cSrcweir }
346cdf0e10cSrcweir
347cdf0e10cSrcweir // ------------------------------------------------------------------------
348cdf0e10cSrcweir
ReadLocalHeader()349cdf0e10cSrcweir sal_Bool GIFReader::ReadLocalHeader()
350cdf0e10cSrcweir {
351cdf0e10cSrcweir sal_uInt8 pBuf[ 9 ];
352cdf0e10cSrcweir sal_Bool bRet = sal_False;
353cdf0e10cSrcweir
354cdf0e10cSrcweir rIStm.Read( pBuf, 9 );
355cdf0e10cSrcweir if( NO_PENDING( rIStm ) )
356cdf0e10cSrcweir {
357cdf0e10cSrcweir SvMemoryStream aMemStm;
358cdf0e10cSrcweir BitmapPalette* pPal;
359cdf0e10cSrcweir sal_uInt8 nFlags;
360cdf0e10cSrcweir
361cdf0e10cSrcweir aMemStm.SetBuffer( (char*) pBuf, 9, sal_False, 9 );
362cdf0e10cSrcweir aMemStm >> nImagePosX;
363cdf0e10cSrcweir aMemStm >> nImagePosY;
364cdf0e10cSrcweir aMemStm >> nImageWidth;
365cdf0e10cSrcweir aMemStm >> nImageHeight;
366cdf0e10cSrcweir aMemStm >> nFlags;
367cdf0e10cSrcweir
368cdf0e10cSrcweir // Falls Interlaced, ersten Startwert vorgeben
369cdf0e10cSrcweir bInterlaced = ( ( nFlags & 0x40 ) == 0x40 );
370cdf0e10cSrcweir nLastInterCount = 7;
371cdf0e10cSrcweir nLastImageY = 0;
372cdf0e10cSrcweir
373cdf0e10cSrcweir if( nFlags & 0x80 )
374cdf0e10cSrcweir {
375cdf0e10cSrcweir pPal = &aLPalette;
376cdf0e10cSrcweir ReadPaletteEntries( pPal, 1 << ( (nFlags & 7 ) + 1 ) );
377cdf0e10cSrcweir }
378cdf0e10cSrcweir else
379cdf0e10cSrcweir pPal = &aGPalette;
380cdf0e10cSrcweir
381cdf0e10cSrcweir // Falls alles soweit eingelesen werden konnte, kann
382cdf0e10cSrcweir // nun das lokale Bild angelegt werden;
383cdf0e10cSrcweir // es wird uebergeben, ob der BackgroundColorIndex evtl.
384cdf0e10cSrcweir // beruecksichtigt werden soll ( wenn Globale Farbtab. und
385cdf0e10cSrcweir // diese auch fuer dieses Bild gilt )
386cdf0e10cSrcweir if( NO_PENDING( rIStm ) )
387cdf0e10cSrcweir {
388cdf0e10cSrcweir CreateBitmaps( nImageWidth, nImageHeight, pPal, bGlobalPalette && ( pPal == &aGPalette ) );
389cdf0e10cSrcweir bRet = sal_True;
390cdf0e10cSrcweir }
391cdf0e10cSrcweir }
392cdf0e10cSrcweir
393cdf0e10cSrcweir return bRet;
394cdf0e10cSrcweir }
395cdf0e10cSrcweir
396cdf0e10cSrcweir // ------------------------------------------------------------------------
397cdf0e10cSrcweir
ReadNextBlock()398cdf0e10cSrcweir sal_uLong GIFReader::ReadNextBlock()
399cdf0e10cSrcweir {
400cdf0e10cSrcweir sal_uLong nRet = 0UL;
401cdf0e10cSrcweir sal_uLong nRead;
402cdf0e10cSrcweir sal_uInt8 cBlockSize;
403cdf0e10cSrcweir
404cdf0e10cSrcweir rIStm >> cBlockSize;
405cdf0e10cSrcweir
406cdf0e10cSrcweir if ( rIStm.IsEof() )
407cdf0e10cSrcweir nRet = 4UL;
408cdf0e10cSrcweir else if ( NO_PENDING( rIStm ) )
409cdf0e10cSrcweir {
410cdf0e10cSrcweir if ( cBlockSize == 0 )
411cdf0e10cSrcweir nRet = 2UL;
412cdf0e10cSrcweir else
413cdf0e10cSrcweir {
414cdf0e10cSrcweir rIStm.Read( pSrcBuf, cBlockSize );
415cdf0e10cSrcweir
416cdf0e10cSrcweir if( NO_PENDING( rIStm ) )
417cdf0e10cSrcweir {
418cdf0e10cSrcweir if( bOverreadBlock )
419cdf0e10cSrcweir nRet = 3UL;
420cdf0e10cSrcweir else
421cdf0e10cSrcweir {
422cdf0e10cSrcweir sal_Bool bEOI;
423cdf0e10cSrcweir HPBYTE pTarget = pDecomp->DecompressBlock( pSrcBuf, cBlockSize, nRead, bEOI );
424cdf0e10cSrcweir
425cdf0e10cSrcweir nRet = ( bEOI ? 3 : 1 );
426cdf0e10cSrcweir
427cdf0e10cSrcweir if( nRead && !bOverreadBlock )
428cdf0e10cSrcweir FillImages( pTarget, nRead );
429cdf0e10cSrcweir
430cdf0e10cSrcweir rtl_freeMemory( pTarget );
431cdf0e10cSrcweir }
432cdf0e10cSrcweir }
433cdf0e10cSrcweir }
434cdf0e10cSrcweir }
435cdf0e10cSrcweir
436cdf0e10cSrcweir return nRet;
437cdf0e10cSrcweir }
438cdf0e10cSrcweir
439cdf0e10cSrcweir // ------------------------------------------------------------------------
440cdf0e10cSrcweir
FillImages(HPBYTE pBytes,sal_uLong nCount)441cdf0e10cSrcweir void GIFReader::FillImages( HPBYTE pBytes, sal_uLong nCount )
442cdf0e10cSrcweir {
443cdf0e10cSrcweir for( sal_uLong i = 0UL; i < nCount; i++ )
444cdf0e10cSrcweir {
445cdf0e10cSrcweir if( nImageX >= nImageWidth )
446cdf0e10cSrcweir {
447cdf0e10cSrcweir if( bInterlaced )
448cdf0e10cSrcweir {
449cdf0e10cSrcweir long nT1, nT2;
450cdf0e10cSrcweir
451cdf0e10cSrcweir // falls Interlaced, werden die Zeilen kopiert
452cdf0e10cSrcweir if( nLastInterCount )
453cdf0e10cSrcweir {
454cdf0e10cSrcweir long nMinY = Min( (long) nLastImageY + 1, (long) nImageHeight - 1 );
455cdf0e10cSrcweir long nMaxY = Min( (long) nLastImageY + nLastInterCount, (long) nImageHeight - 1 );
456cdf0e10cSrcweir
457cdf0e10cSrcweir // letzte gelesene Zeile kopieren, wenn Zeilen
458cdf0e10cSrcweir // nicht zusanmmenfallen ( kommt vorm wenn wir am Ende des Bildes sind )
459cdf0e10cSrcweir if( ( nMinY > nLastImageY ) && ( nLastImageY < ( nImageHeight - 1 ) ) )
460cdf0e10cSrcweir {
461cdf0e10cSrcweir HPBYTE pScanline8 = pAcc8->GetScanline( nYAcc );
462cdf0e10cSrcweir sal_uLong nSize8 = pAcc8->GetScanlineSize();
463cdf0e10cSrcweir HPBYTE pScanline1 = 0;
464cdf0e10cSrcweir sal_uLong nSize1 = 0;
465cdf0e10cSrcweir
466cdf0e10cSrcweir if( bGCTransparent )
467cdf0e10cSrcweir {
468cdf0e10cSrcweir pScanline1 = pAcc1->GetScanline( nYAcc );
469cdf0e10cSrcweir nSize1 = pAcc1->GetScanlineSize();
470cdf0e10cSrcweir }
471cdf0e10cSrcweir
472cdf0e10cSrcweir for( long j = nMinY; j <= nMaxY; j++ )
473cdf0e10cSrcweir {
474cdf0e10cSrcweir memcpy( pAcc8->GetScanline( j ), pScanline8, nSize8 );
475cdf0e10cSrcweir
476cdf0e10cSrcweir if( bGCTransparent )
477cdf0e10cSrcweir memcpy( pAcc1->GetScanline( j ), pScanline1, nSize1 );
478cdf0e10cSrcweir }
479cdf0e10cSrcweir }
480cdf0e10cSrcweir }
481cdf0e10cSrcweir
482cdf0e10cSrcweir nT1 = ( ++nImageY ) << 3;
483cdf0e10cSrcweir nLastInterCount = 7;
484cdf0e10cSrcweir
485cdf0e10cSrcweir if( nT1 >= nImageHeight )
486cdf0e10cSrcweir {
487cdf0e10cSrcweir nT2 = nImageY - ( ( nImageHeight + 7 ) >> 3 );
488cdf0e10cSrcweir nT1 = ( nT2 << 3 ) + 4;
489cdf0e10cSrcweir nLastInterCount = 3;
490cdf0e10cSrcweir
491cdf0e10cSrcweir if( nT1 >= nImageHeight )
492cdf0e10cSrcweir {
493cdf0e10cSrcweir nT2 -= ( nImageHeight + 3 ) >> 3;
494cdf0e10cSrcweir nT1 = ( nT2 << 2 ) + 2;
495cdf0e10cSrcweir nLastInterCount = 1;
496cdf0e10cSrcweir
497cdf0e10cSrcweir if( nT1 >= nImageHeight )
498cdf0e10cSrcweir {
499cdf0e10cSrcweir nT2 -= ( nImageHeight + 1 ) >> 2;
500cdf0e10cSrcweir nT1 = ( nT2 << 1 ) + 1;
501cdf0e10cSrcweir nLastInterCount = 0;
502cdf0e10cSrcweir }
503cdf0e10cSrcweir }
504cdf0e10cSrcweir }
505cdf0e10cSrcweir
506cdf0e10cSrcweir nLastImageY = (sal_uInt16) nT1;
507cdf0e10cSrcweir nYAcc = nT1;
508cdf0e10cSrcweir }
509cdf0e10cSrcweir else
510cdf0e10cSrcweir {
511cdf0e10cSrcweir nLastImageY = ++nImageY;
512cdf0e10cSrcweir nYAcc = nImageY;
513cdf0e10cSrcweir }
514cdf0e10cSrcweir
515cdf0e10cSrcweir // Zeile faengt von vorne an
516cdf0e10cSrcweir nImageX = 0;
517cdf0e10cSrcweir }
518cdf0e10cSrcweir
519cdf0e10cSrcweir if( nImageY < nImageHeight )
520cdf0e10cSrcweir {
521cdf0e10cSrcweir const sal_uInt8 cTmp = pBytes[ i ];
522cdf0e10cSrcweir
523cdf0e10cSrcweir if( bGCTransparent )
524cdf0e10cSrcweir {
525cdf0e10cSrcweir if( cTmp == nGCTransparentIndex )
526*87bc88d3SHerbert Dürr pAcc1->SetPixelIndex( nYAcc, nImageX++, cTransIndex1 );
527cdf0e10cSrcweir else
528cdf0e10cSrcweir {
529*87bc88d3SHerbert Dürr pAcc8->SetPixelIndex( nYAcc, nImageX, cTmp );
530*87bc88d3SHerbert Dürr pAcc1->SetPixelIndex( nYAcc, nImageX++, cNonTransIndex1 );
531cdf0e10cSrcweir }
532cdf0e10cSrcweir }
533cdf0e10cSrcweir else
534*87bc88d3SHerbert Dürr pAcc8->SetPixelIndex( nYAcc, nImageX++, cTmp );
535cdf0e10cSrcweir }
536cdf0e10cSrcweir else
537cdf0e10cSrcweir {
538cdf0e10cSrcweir bOverreadBlock = sal_True;
539cdf0e10cSrcweir break;
540cdf0e10cSrcweir }
541cdf0e10cSrcweir }
542cdf0e10cSrcweir }
543cdf0e10cSrcweir
544cdf0e10cSrcweir // ------------------------------------------------------------------------
545cdf0e10cSrcweir
CreateNewBitmaps()546cdf0e10cSrcweir void GIFReader::CreateNewBitmaps()
547cdf0e10cSrcweir {
548cdf0e10cSrcweir AnimationBitmap aAnimBmp;
549cdf0e10cSrcweir
550cdf0e10cSrcweir aBmp8.ReleaseAccess( pAcc8 );
551cdf0e10cSrcweir pAcc8 = NULL;
552cdf0e10cSrcweir
553cdf0e10cSrcweir if( bGCTransparent )
554cdf0e10cSrcweir {
555cdf0e10cSrcweir aBmp1.ReleaseAccess( pAcc1 );
556cdf0e10cSrcweir pAcc1 = NULL;
557cdf0e10cSrcweir aAnimBmp.aBmpEx = BitmapEx( aBmp8, aBmp1 );
558cdf0e10cSrcweir }
559cdf0e10cSrcweir else
560cdf0e10cSrcweir aAnimBmp.aBmpEx = BitmapEx( aBmp8 );
561cdf0e10cSrcweir
562cdf0e10cSrcweir aAnimBmp.aPosPix = Point( nImagePosX, nImagePosY );
563cdf0e10cSrcweir aAnimBmp.aSizePix = Size( nImageWidth, nImageHeight );
564cdf0e10cSrcweir aAnimBmp.nWait = ( nTimer != 65535 ) ? nTimer : ANIMATION_TIMEOUT_ON_CLICK;
565cdf0e10cSrcweir aAnimBmp.bUserInput = sal_False;
566cdf0e10cSrcweir
567cdf0e10cSrcweir if( nGCDisposalMethod == 2 )
568cdf0e10cSrcweir aAnimBmp.eDisposal = DISPOSE_BACK;
569cdf0e10cSrcweir else if( nGCDisposalMethod == 3 )
570cdf0e10cSrcweir aAnimBmp.eDisposal = DISPOSE_PREVIOUS;
571cdf0e10cSrcweir else
572cdf0e10cSrcweir aAnimBmp.eDisposal = DISPOSE_NOT;
573cdf0e10cSrcweir
574cdf0e10cSrcweir aAnimation.Insert( aAnimBmp );
575cdf0e10cSrcweir
576cdf0e10cSrcweir if( aAnimation.Count() == 1 )
577cdf0e10cSrcweir {
578cdf0e10cSrcweir aAnimation.SetDisplaySizePixel( Size( nGlobalWidth, nGlobalHeight ) );
579cdf0e10cSrcweir aAnimation.SetLoopCount( nLoops );
580cdf0e10cSrcweir }
581cdf0e10cSrcweir }
582cdf0e10cSrcweir
583cdf0e10cSrcweir // ------------------------------------------------------------------------
584cdf0e10cSrcweir
GetIntermediateGraphic()585cdf0e10cSrcweir const Graphic& GIFReader::GetIntermediateGraphic()
586cdf0e10cSrcweir {
587cdf0e10cSrcweir // Intermediate-Graphic nur erzeugen, wenn schon
588cdf0e10cSrcweir // Daten vorliegen, aber die Graphic noch nicht
589cdf0e10cSrcweir // vollstaendig eingelesen wurde
590cdf0e10cSrcweir if ( bImGraphicReady && !aAnimation.Count() )
591cdf0e10cSrcweir {
592cdf0e10cSrcweir Bitmap aBmp;
593cdf0e10cSrcweir
594cdf0e10cSrcweir aBmp8.ReleaseAccess( pAcc8 );
595cdf0e10cSrcweir
596cdf0e10cSrcweir if ( bGCTransparent )
597cdf0e10cSrcweir {
598cdf0e10cSrcweir aBmp1.ReleaseAccess( pAcc1 );
599cdf0e10cSrcweir aImGraphic = BitmapEx( aBmp8, aBmp1 );
600cdf0e10cSrcweir
601cdf0e10cSrcweir pAcc1 = aBmp1.AcquireWriteAccess();
602cdf0e10cSrcweir bStatus = bStatus && ( pAcc1 != NULL );
603cdf0e10cSrcweir }
604cdf0e10cSrcweir else
605cdf0e10cSrcweir aImGraphic = aBmp8;
606cdf0e10cSrcweir
607cdf0e10cSrcweir pAcc8 = aBmp8.AcquireWriteAccess();
608cdf0e10cSrcweir bStatus = bStatus && ( pAcc8 != NULL );
609cdf0e10cSrcweir }
610cdf0e10cSrcweir
611cdf0e10cSrcweir return aImGraphic;
612cdf0e10cSrcweir }
613cdf0e10cSrcweir
614cdf0e10cSrcweir // ------------------------------------------------------------------------
615cdf0e10cSrcweir
ProcessGIF()616cdf0e10cSrcweir sal_Bool GIFReader::ProcessGIF()
617cdf0e10cSrcweir {
618cdf0e10cSrcweir sal_Bool bRead = sal_False;
619cdf0e10cSrcweir sal_Bool bEnd = sal_False;
620cdf0e10cSrcweir
621cdf0e10cSrcweir if ( !bStatus )
622cdf0e10cSrcweir eActAction = ABORT_READING;
623cdf0e10cSrcweir
624cdf0e10cSrcweir // Stream an die richtige Stelle bringen
625cdf0e10cSrcweir rIStm.Seek( nLastPos );
626cdf0e10cSrcweir
627cdf0e10cSrcweir switch( eActAction )
628cdf0e10cSrcweir {
629cdf0e10cSrcweir // naechsten Marker lesen
630cdf0e10cSrcweir case( MARKER_READING ):
631cdf0e10cSrcweir {
632cdf0e10cSrcweir sal_uInt8 cByte;
633cdf0e10cSrcweir
634cdf0e10cSrcweir rIStm >> cByte;
635cdf0e10cSrcweir
636cdf0e10cSrcweir if( rIStm.IsEof() )
637cdf0e10cSrcweir eActAction = END_READING;
638cdf0e10cSrcweir else if( NO_PENDING( rIStm ) )
639cdf0e10cSrcweir {
640cdf0e10cSrcweir bRead = sal_True;
641cdf0e10cSrcweir
642cdf0e10cSrcweir if( cByte == '!' )
643cdf0e10cSrcweir eActAction = EXTENSION_READING;
644cdf0e10cSrcweir else if( cByte == ',' )
645cdf0e10cSrcweir eActAction = LOCAL_HEADER_READING;
646cdf0e10cSrcweir else if( cByte == ';' )
647cdf0e10cSrcweir eActAction = END_READING;
648cdf0e10cSrcweir else
649cdf0e10cSrcweir eActAction = ABORT_READING;
650cdf0e10cSrcweir }
651cdf0e10cSrcweir }
652cdf0e10cSrcweir break;
653cdf0e10cSrcweir
654cdf0e10cSrcweir // ScreenDescriptor lesen
655cdf0e10cSrcweir case( GLOBAL_HEADER_READING ):
656cdf0e10cSrcweir {
657cdf0e10cSrcweir if( ( bRead = ReadGlobalHeader() ) == sal_True )
658cdf0e10cSrcweir {
659cdf0e10cSrcweir ClearImageExtensions();
660cdf0e10cSrcweir eActAction = MARKER_READING;
661cdf0e10cSrcweir }
662cdf0e10cSrcweir }
663cdf0e10cSrcweir break;
664cdf0e10cSrcweir
665cdf0e10cSrcweir
666cdf0e10cSrcweir // Extension lesen
667cdf0e10cSrcweir case( EXTENSION_READING ):
668cdf0e10cSrcweir {
669cdf0e10cSrcweir if( ( bRead = ReadExtension() ) == sal_True )
670cdf0e10cSrcweir eActAction = MARKER_READING;
671cdf0e10cSrcweir }
672cdf0e10cSrcweir break;
673cdf0e10cSrcweir
674cdf0e10cSrcweir
675cdf0e10cSrcweir // Image-Descriptor lesen
676cdf0e10cSrcweir case( LOCAL_HEADER_READING ):
677cdf0e10cSrcweir {
678cdf0e10cSrcweir if( ( bRead = ReadLocalHeader() ) == sal_True )
679cdf0e10cSrcweir {
680cdf0e10cSrcweir nYAcc = nImageX = nImageY = 0;
681cdf0e10cSrcweir eActAction = FIRST_BLOCK_READING;
682cdf0e10cSrcweir }
683cdf0e10cSrcweir }
684cdf0e10cSrcweir break;
685cdf0e10cSrcweir
686cdf0e10cSrcweir
687cdf0e10cSrcweir // ersten Datenblock lesen
688cdf0e10cSrcweir case( FIRST_BLOCK_READING ):
689cdf0e10cSrcweir {
690cdf0e10cSrcweir sal_uInt8 cDataSize;
691cdf0e10cSrcweir
692cdf0e10cSrcweir rIStm >> cDataSize;
693cdf0e10cSrcweir
694cdf0e10cSrcweir if( rIStm.IsEof() )
695cdf0e10cSrcweir eActAction = ABORT_READING;
696cdf0e10cSrcweir else if( cDataSize > 12 )
697cdf0e10cSrcweir bStatus = sal_False;
698cdf0e10cSrcweir else if( NO_PENDING( rIStm ) )
699cdf0e10cSrcweir {
700cdf0e10cSrcweir bRead = sal_True;
701cdf0e10cSrcweir pDecomp = new GIFLZWDecompressor( cDataSize );
702cdf0e10cSrcweir eActAction = NEXT_BLOCK_READING;
703cdf0e10cSrcweir bOverreadBlock = sal_False;
704cdf0e10cSrcweir }
705cdf0e10cSrcweir else
706cdf0e10cSrcweir eActAction = FIRST_BLOCK_READING;
707cdf0e10cSrcweir }
708cdf0e10cSrcweir break;
709cdf0e10cSrcweir
710cdf0e10cSrcweir // naechsten Datenblock lesen
711cdf0e10cSrcweir case( NEXT_BLOCK_READING ):
712cdf0e10cSrcweir {
713cdf0e10cSrcweir sal_uInt16 nLastX = nImageX;
714cdf0e10cSrcweir sal_uInt16 nLastY = nImageY;
715cdf0e10cSrcweir sal_uLong nRet = ReadNextBlock();
716cdf0e10cSrcweir
717cdf0e10cSrcweir // Return: 0:Pending / 1:OK; / 2:OK und letzter Block: / 3:EOI / 4:HardAbort
718cdf0e10cSrcweir if( nRet )
719cdf0e10cSrcweir {
720cdf0e10cSrcweir bRead = sal_True;
721cdf0e10cSrcweir
722cdf0e10cSrcweir if ( nRet == 1UL )
723cdf0e10cSrcweir {
724cdf0e10cSrcweir bImGraphicReady = sal_True;
725cdf0e10cSrcweir eActAction = NEXT_BLOCK_READING;
726cdf0e10cSrcweir bOverreadBlock = sal_False;
727cdf0e10cSrcweir }
728cdf0e10cSrcweir else
729cdf0e10cSrcweir {
730cdf0e10cSrcweir if( nRet == 2UL )
731cdf0e10cSrcweir {
732cdf0e10cSrcweir delete pDecomp;
733cdf0e10cSrcweir CreateNewBitmaps();
734cdf0e10cSrcweir eActAction = MARKER_READING;
735cdf0e10cSrcweir ClearImageExtensions();
736cdf0e10cSrcweir }
737cdf0e10cSrcweir else if( nRet == 3UL )
738cdf0e10cSrcweir {
739cdf0e10cSrcweir eActAction = NEXT_BLOCK_READING;
740cdf0e10cSrcweir bOverreadBlock = sal_True;
741cdf0e10cSrcweir }
742cdf0e10cSrcweir else
743cdf0e10cSrcweir {
744cdf0e10cSrcweir delete pDecomp;
745cdf0e10cSrcweir CreateNewBitmaps();
746cdf0e10cSrcweir eActAction = ABORT_READING;
747cdf0e10cSrcweir ClearImageExtensions();
748cdf0e10cSrcweir }
749cdf0e10cSrcweir }
750cdf0e10cSrcweir }
751cdf0e10cSrcweir else
752cdf0e10cSrcweir {
753cdf0e10cSrcweir nImageX = nLastX;
754cdf0e10cSrcweir nImageY = nLastY;
755cdf0e10cSrcweir }
756cdf0e10cSrcweir }
757cdf0e10cSrcweir break;
758cdf0e10cSrcweir
759cdf0e10cSrcweir // ein Fehler trat auf
760cdf0e10cSrcweir case( ABORT_READING ):
761cdf0e10cSrcweir {
762cdf0e10cSrcweir bEnd = sal_True;
763cdf0e10cSrcweir eActAction = END_READING;
764cdf0e10cSrcweir }
765cdf0e10cSrcweir break;
766cdf0e10cSrcweir
767cdf0e10cSrcweir default:
768cdf0e10cSrcweir break;
769cdf0e10cSrcweir }
770cdf0e10cSrcweir
771cdf0e10cSrcweir // Stream an die richtige Stelle bringen,
772cdf0e10cSrcweir // falls Daten gelesen werden konnten
773cdf0e10cSrcweir // entweder alte Position oder aktuelle Position
774cdf0e10cSrcweir if( bRead || bEnd )
775cdf0e10cSrcweir nLastPos = rIStm.Tell();
776cdf0e10cSrcweir
777cdf0e10cSrcweir return bRead;
778cdf0e10cSrcweir }
779cdf0e10cSrcweir
780cdf0e10cSrcweir // ------------------------------------------------------------------------
781cdf0e10cSrcweir
ReadGIF(Graphic & rGraphic)782cdf0e10cSrcweir ReadState GIFReader::ReadGIF( Graphic& rGraphic )
783cdf0e10cSrcweir {
784cdf0e10cSrcweir ReadState eReadState;
785cdf0e10cSrcweir
786cdf0e10cSrcweir bStatus = sal_True;
787cdf0e10cSrcweir
788cdf0e10cSrcweir while( ProcessGIF() && ( eActAction != END_READING ) ) {}
789cdf0e10cSrcweir
790cdf0e10cSrcweir if( !bStatus )
791cdf0e10cSrcweir eReadState = GIFREAD_ERROR;
792cdf0e10cSrcweir else if( eActAction == END_READING )
793cdf0e10cSrcweir eReadState = GIFREAD_OK;
794cdf0e10cSrcweir else
795cdf0e10cSrcweir {
796cdf0e10cSrcweir if ( rIStm.GetError() == ERRCODE_IO_PENDING )
797cdf0e10cSrcweir rIStm.ResetError();
798cdf0e10cSrcweir
799cdf0e10cSrcweir eReadState = GIFREAD_NEED_MORE;
800cdf0e10cSrcweir }
801cdf0e10cSrcweir
802cdf0e10cSrcweir if( aAnimation.Count() == 1 )
803cdf0e10cSrcweir {
804cdf0e10cSrcweir rGraphic = aAnimation.Get( 0 ).aBmpEx;
805cdf0e10cSrcweir
806cdf0e10cSrcweir if( nLogWidth100 && nLogHeight100 )
807cdf0e10cSrcweir {
808cdf0e10cSrcweir rGraphic.SetPrefSize( Size( nLogWidth100, nLogHeight100 ) );
809cdf0e10cSrcweir rGraphic.SetPrefMapMode( MAP_100TH_MM );
810cdf0e10cSrcweir }
811cdf0e10cSrcweir }
812cdf0e10cSrcweir else
813cdf0e10cSrcweir rGraphic = aAnimation;
814cdf0e10cSrcweir
815cdf0e10cSrcweir return eReadState;
816cdf0e10cSrcweir }
817cdf0e10cSrcweir
818cdf0e10cSrcweir
819cdf0e10cSrcweir // -------------
820cdf0e10cSrcweir // - ImportGIF -
821cdf0e10cSrcweir // -------------
822cdf0e10cSrcweir
ImportGIF(SvStream & rStm,Graphic & rGraphic)823cdf0e10cSrcweir sal_Bool ImportGIF( SvStream & rStm, Graphic& rGraphic )
824cdf0e10cSrcweir {
825cdf0e10cSrcweir GIFReader* pGIFReader = (GIFReader*) rGraphic.GetContext();
826cdf0e10cSrcweir sal_uInt16 nOldFormat = rStm.GetNumberFormatInt();
827cdf0e10cSrcweir ReadState eReadState;
828cdf0e10cSrcweir sal_Bool bRet = sal_True;
829cdf0e10cSrcweir
830cdf0e10cSrcweir rStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
831cdf0e10cSrcweir
832cdf0e10cSrcweir if( !pGIFReader )
833cdf0e10cSrcweir pGIFReader = new GIFReader( rStm );
834cdf0e10cSrcweir
835cdf0e10cSrcweir rGraphic.SetContext( NULL );
836cdf0e10cSrcweir eReadState = pGIFReader->ReadGIF( rGraphic );
837cdf0e10cSrcweir
838cdf0e10cSrcweir if( eReadState == GIFREAD_ERROR )
839cdf0e10cSrcweir {
840cdf0e10cSrcweir bRet = sal_False;
841cdf0e10cSrcweir delete pGIFReader;
842cdf0e10cSrcweir }
843cdf0e10cSrcweir else if( eReadState == GIFREAD_OK )
844cdf0e10cSrcweir delete pGIFReader;
845cdf0e10cSrcweir else
846cdf0e10cSrcweir {
847cdf0e10cSrcweir rGraphic = pGIFReader->GetIntermediateGraphic();
848cdf0e10cSrcweir rGraphic.SetContext( pGIFReader );
849cdf0e10cSrcweir }
850cdf0e10cSrcweir
851cdf0e10cSrcweir rStm.SetNumberFormatInt( nOldFormat );
852cdf0e10cSrcweir
853cdf0e10cSrcweir return bRet;
854cdf0e10cSrcweir }
855