Update ooo320-m1
[ooovba.git] / goodies / source / filter.vcl / ipsd / ipsd.cxx
blobd85b4b0309eb0bf490b9ec6120b17cdc2094edb6
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: ipsd.cxx,v $
10 * $Revision: 1.14 $
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/bmpacc.hxx>
36 #include <svtools/fltcall.hxx>
38 //============================ PSDReader ==================================
40 #define PSD_BITMAP 0
41 #define PSD_GRAYSCALE 1
42 #define PSD_INDEXED 2
43 #define PSD_RGB 3
44 #define PSD_CMYK 4
45 #define PSD_MULTICHANNEL 7
46 #define PSD_DUOTONE 8
47 #define PSD_LAB 9
49 typedef struct
51 UINT32 nSignature;
52 UINT16 nVersion;
53 UINT32 nPad1;
54 UINT16 nPad2;
55 UINT16 nChannels;
56 UINT32 nRows;
57 UINT32 nColumns;
58 UINT16 nDepth;
59 UINT16 nMode;
61 } PSDFileHeader;
63 class PSDReader {
65 private:
67 SvStream* mpPSD; // Die einzulesende PSD-Datei
68 PSDFileHeader* mpFileHeader;
70 sal_uInt32 mnXResFixed;
71 sal_uInt32 mnYResFixed;
73 sal_Bool mbStatus;
74 sal_Bool mbTransparent;
76 Bitmap maBmp;
77 Bitmap maMaskBmp;
78 BitmapReadAccess* mpReadAcc;
79 BitmapWriteAccess* mpWriteAcc;
80 BitmapWriteAccess* mpMaskWriteAcc;
81 USHORT mnDestBitDepth;
82 BOOL mbCompression; // RLE decoding
83 BYTE* mpPalette;
85 BOOL ImplReadBody();
86 BOOL ImplReadHeader();
88 public:
89 PSDReader();
90 ~PSDReader();
91 BOOL ReadPSD( SvStream & rPSD, Graphic & rGraphic );
94 //=================== Methoden von PSDReader ==============================
96 PSDReader::PSDReader() :
97 mpFileHeader ( NULL ),
98 mnXResFixed ( 0 ),
99 mnYResFixed ( 0 ),
100 mbStatus ( TRUE ),
101 mbTransparent ( FALSE ),
102 mpReadAcc ( NULL ),
103 mpWriteAcc ( NULL ),
104 mpMaskWriteAcc ( NULL ),
105 mpPalette ( NULL )
109 PSDReader::~PSDReader()
111 delete[] mpPalette;
112 delete mpFileHeader;
115 // ------------------------------------------------------------------------
117 BOOL PSDReader::ReadPSD( SvStream & rPSD, Graphic & rGraphic )
119 if ( rPSD.GetError() )
120 return FALSE;
122 mpPSD = &rPSD;
123 mpPSD->SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
125 // Kopf einlesen:
127 if ( ImplReadHeader() == FALSE )
128 return FALSE;
130 Size aBitmapSize( mpFileHeader->nColumns, mpFileHeader->nRows );
131 maBmp = Bitmap( aBitmapSize, mnDestBitDepth );
132 if ( ( mpWriteAcc = maBmp.AcquireWriteAccess() ) == NULL )
133 mbStatus = FALSE;
134 if ( ( mpReadAcc = maBmp.AcquireReadAccess() ) == NULL )
135 mbStatus = FALSE;
136 if ( mbTransparent && mbStatus )
138 maMaskBmp = Bitmap( aBitmapSize, 1 );
139 if ( ( mpMaskWriteAcc = maMaskBmp.AcquireWriteAccess() ) == NULL )
140 mbStatus = FALSE;
142 if ( mpPalette && mbStatus )
144 mpWriteAcc->SetPaletteEntryCount( 256 );
145 for ( USHORT i = 0; i < 256; i++ )
147 mpWriteAcc->SetPaletteColor( i, Color( mpPalette[ i ], mpPalette[ i + 256 ], mpPalette[ i + 512 ] ) );
150 // Bitmap-Daten einlesen
151 if ( mbStatus && ImplReadBody() )
153 if ( mbTransparent )
154 rGraphic = Graphic( BitmapEx( maBmp, maMaskBmp ) );
155 else
156 rGraphic = maBmp;
158 if ( mnXResFixed && mnYResFixed )
160 Point aEmptyPoint;
161 Fraction aFractX( 1, mnXResFixed >> 16 );
162 Fraction aFractY( 1, mnYResFixed >> 16 );
163 MapMode aMapMode( MAP_INCH, aEmptyPoint, aFractX, aFractY );
164 Size aPrefSize = OutputDevice::LogicToLogic( aBitmapSize, aMapMode, MAP_100TH_MM );
165 rGraphic.SetPrefSize( aPrefSize );
166 rGraphic.SetPrefMapMode( MapMode( MAP_100TH_MM ) );
169 else
170 mbStatus = FALSE;
171 if ( mpWriteAcc )
172 maBmp.ReleaseAccess( mpWriteAcc );
173 if ( mpReadAcc )
174 maBmp.ReleaseAccess( mpReadAcc );
175 if ( mpMaskWriteAcc )
176 maMaskBmp.ReleaseAccess( mpMaskWriteAcc );
177 return mbStatus;
180 // ------------------------------------------------------------------------
182 BOOL PSDReader::ImplReadHeader()
184 UINT16 nCompression;
185 UINT32 nColorLength, nResourceLength, nLayerMaskLength;
187 mpFileHeader = new PSDFileHeader;
189 if ( !mpFileHeader )
190 return FALSE;
192 *mpPSD >> mpFileHeader->nSignature >> mpFileHeader->nVersion >> mpFileHeader->nPad1 >>
193 mpFileHeader->nPad2 >> mpFileHeader->nChannels >> mpFileHeader->nRows >>
194 mpFileHeader->nColumns >> mpFileHeader->nDepth >> mpFileHeader->nMode;
196 if ( ( mpFileHeader->nSignature != 0x38425053 ) || ( mpFileHeader->nVersion != 1 ) )
197 return FALSE;
199 if ( mpFileHeader->nRows == 0 || mpFileHeader->nColumns == 0 )
200 return FALSE;
202 if ( ( mpFileHeader->nRows > 30000 ) || ( mpFileHeader->nColumns > 30000 ) )
203 return FALSE;
205 UINT16 nDepth = mpFileHeader->nDepth;
206 if (!( ( nDepth == 1 ) || ( nDepth == 8 ) || ( nDepth == 16 ) ) )
207 return FALSE;
209 mnDestBitDepth = ( nDepth == 16 ) ? 8 : nDepth;
211 *mpPSD >> nColorLength;
212 if ( mpFileHeader->nMode == PSD_CMYK )
214 switch ( mpFileHeader->nChannels )
216 case 5 :
217 mbTransparent = TRUE;
218 case 4 :
219 mnDestBitDepth = 24;
220 break;
221 default :
222 return FALSE;
225 else switch ( mpFileHeader->nChannels )
227 case 2 :
228 mbTransparent = TRUE;
229 case 1 :
230 break;
231 case 4 :
232 mbTransparent = TRUE;
233 case 3 :
234 mnDestBitDepth = 24;
235 break;
236 default:
237 return FALSE;
240 switch ( mpFileHeader->nMode )
242 case PSD_BITMAP :
244 if ( nColorLength || ( nDepth != 1 ) )
245 return FALSE;
247 break;
249 case PSD_INDEXED :
251 if ( nColorLength != 768 ) // we need the color map
252 return FALSE;
253 mpPalette = new BYTE[ 768 ];
254 if ( mpPalette == NULL )
255 return FALSE;
256 mpPSD->Read( mpPalette, 768 );
258 break;
260 case PSD_DUOTONE : // we'll handle the doutone color like a normal grayscale picture
261 mpPSD->SeekRel( nColorLength );
262 nColorLength = 0;
263 case PSD_GRAYSCALE :
265 if ( nColorLength )
266 return FALSE;
267 mpPalette = new BYTE[ 768 ];
268 if ( mpPalette == NULL )
269 return FALSE;
270 for ( USHORT i = 0; i < 256; i++ )
272 mpPalette[ i ] = mpPalette[ i + 256 ] = mpPalette[ i + 512 ] = (BYTE)i;
275 break;
277 case PSD_CMYK :
278 case PSD_RGB :
279 case PSD_MULTICHANNEL :
280 case PSD_LAB :
282 if ( nColorLength ) // color table is not supported by the other graphic modes
283 return FALSE;
285 break;
287 default:
288 return FALSE;
290 *mpPSD >> nResourceLength;
291 sal_uInt32 nLayerPos = mpPSD->Tell() + nResourceLength;
293 // this is a loop over the resource entries to get the resolution info
294 while( mpPSD->Tell() < nLayerPos )
296 sal_uInt8 n8;
297 sal_uInt32 nType, nPStringLen, nResEntryLen;
298 sal_uInt16 nUniqueID;
300 *mpPSD >> nType >> nUniqueID >> n8;
301 nPStringLen = n8;
302 if ( nType != 0x3842494d )
303 break;
304 if ( ! ( nPStringLen & 1 ) )
305 nPStringLen++;
306 mpPSD->SeekRel( nPStringLen ); // skipping the pstring
307 *mpPSD >> nResEntryLen;
308 if ( nResEntryLen & 1 )
309 nResEntryLen++; // the resource entries are padded
310 sal_uInt32 nCurrentPos = mpPSD->Tell();
311 if ( ( nResEntryLen + nCurrentPos ) > nLayerPos ) // check if size
312 break; // is possible
313 switch( nUniqueID )
315 case 0x3ed : // UID for the resolution info
317 sal_Int16 nUnit;
319 *mpPSD >> mnXResFixed >> nUnit >> nUnit
320 >> mnYResFixed >> nUnit >> nUnit;
322 break;
324 mpPSD->Seek( nCurrentPos + nResEntryLen ); // set the stream to the next
325 } // resource entry
326 mpPSD->Seek( nLayerPos );
327 *mpPSD >> nLayerMaskLength;
328 mpPSD->SeekRel( nLayerMaskLength );
330 *mpPSD >> nCompression;
331 if ( nCompression == 0 )
333 mbCompression = FALSE;
335 else if ( nCompression == 1 )
337 mpPSD->SeekRel( ( mpFileHeader->nRows * mpFileHeader->nChannels ) << 1 );
338 mbCompression = TRUE;
340 else
341 return FALSE;
343 return TRUE;
346 // ------------------------------------------------------------------------
348 BOOL PSDReader::ImplReadBody()
350 ULONG nX, nY;
351 char nRunCount = 0;
352 signed char nBitCount = -1;
353 BYTE nDat = 0, nDummy, nRed, nGreen, nBlue;
354 BitmapColor aBitmapColor;
355 nX = nY = 0;
357 switch ( mnDestBitDepth )
359 case 1 :
361 while ( nY < mpFileHeader->nRows )
363 if ( nBitCount == -1 )
365 if ( mbCompression ) // else nRunCount = 0 -> so we use only single raw packets
366 *mpPSD >> nRunCount;
368 if ( nRunCount & 0x80 ) // a run length packet
370 if ( nBitCount == -1 ) // bits left in nDat ?
372 *mpPSD >> nDat;
373 nDat ^= 0xff;
374 nBitCount = 7;
376 for ( USHORT i = 0; i < ( -nRunCount + 1 ); i++ )
378 mpWriteAcc->SetPixel( nY, nX, (BYTE)nDat >> nBitCount-- );
379 if ( ++nX == mpFileHeader->nColumns )
381 nX = 0;
382 nY++;
383 nBitCount = -1;
384 if ( nY == mpFileHeader->nRows )
385 break;
389 else // a raw packet
391 for ( USHORT i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
393 if ( nBitCount == -1 ) // bits left in nDat ?
395 *mpPSD >> nDat;
396 nDat ^= 0xff;
397 nBitCount = 7;
399 mpWriteAcc->SetPixel( nY, nX, (BYTE)nDat >> nBitCount-- );
400 if ( ++nX == mpFileHeader->nColumns )
402 nX = 0;
403 nY++;
404 nBitCount = -1;
405 if ( nY == mpFileHeader->nRows )
406 break;
412 break;
414 case 8 :
416 while ( nY < mpFileHeader->nRows )
418 if ( mbCompression ) // else nRunCount = 0 -> so we use only single raw packets
419 *mpPSD >> nRunCount;
421 if ( nRunCount & 0x80 ) // a run length packet
423 *mpPSD >> nDat;
424 if ( mpFileHeader->nDepth == 16 ) // 16 bit depth is to be skipped
425 *mpPSD >> nDummy;
426 for ( USHORT i = 0; i < ( -nRunCount + 1 ); i++ )
428 mpWriteAcc->SetPixel( nY, nX, (BYTE)nDat );
429 if ( ++nX == mpFileHeader->nColumns )
431 nX = 0;
432 nY++;
433 if ( nY == mpFileHeader->nRows )
434 break;
438 else // a raw packet
440 for ( USHORT i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
442 *mpPSD >> nDat;
443 if ( mpFileHeader->nDepth == 16 ) // 16 bit depth is to be skipped
444 *mpPSD >> nDummy;
445 mpWriteAcc->SetPixel( nY, nX, (BYTE)nDat );
446 if ( ++nX == mpFileHeader->nColumns )
448 nX = 0;
449 nY++;
450 if ( nY == mpFileHeader->nRows )
451 break;
457 break;
459 case 24 :
462 // the psd format is in plain order (RRRR GGGG BBBB) so we have to set each pixel three times
463 // maybe the format is CCCC MMMM YYYY KKKK
465 while ( nY < mpFileHeader->nRows )
467 if ( mbCompression ) // else nRunCount = 0 -> so we use only single raw packets
468 *mpPSD >> nRunCount;
470 if ( nRunCount & 0x80 ) // a run length packet
472 *mpPSD >> nRed;
473 if ( mpFileHeader->nDepth == 16 ) // 16 bit depth is to be skipped
474 *mpPSD >> nDummy;
475 for ( USHORT i = 0; i < ( -nRunCount + 1 ); i++ )
477 mpWriteAcc->SetPixel( nY, nX, BitmapColor( nRed, (BYTE)0, (BYTE)0 ) );
478 if ( ++nX == mpFileHeader->nColumns )
480 nX = 0;
481 nY++;
482 if ( nY == mpFileHeader->nRows )
483 break;
487 else // a raw packet
489 for ( USHORT i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
491 *mpPSD >> nRed;
492 if ( mpFileHeader->nDepth == 16 ) // 16 bit depth is to be skipped
493 *mpPSD >> nDummy;
494 mpWriteAcc->SetPixel( nY, nX, BitmapColor( nRed, (BYTE)0, (BYTE)0 ) );
495 if ( ++nX == mpFileHeader->nColumns )
497 nX = 0;
498 nY++;
499 if ( nY == mpFileHeader->nRows )
500 break;
505 nY = 0;
506 while ( nY < mpFileHeader->nRows )
508 if ( mbCompression )
509 *mpPSD >> nRunCount;
510 if ( nRunCount & 0x80 ) // a run length packet
512 *mpPSD >> nGreen;
513 if ( mpFileHeader->nDepth == 16 ) // 16 bit depth is to be skipped
514 *mpPSD >> nDummy;
515 for ( USHORT i = 0; i < ( -nRunCount + 1 ); i++ )
517 aBitmapColor = mpReadAcc->GetPixel( nY, nX );
518 mpWriteAcc->SetPixel( nY, nX, BitmapColor( aBitmapColor.GetRed(), nGreen, aBitmapColor.GetBlue() ) );
519 if ( ++nX == mpFileHeader->nColumns )
521 nX = 0;
522 nY++;
523 if ( nY == mpFileHeader->nRows )
524 break;
528 else // a raw packet
530 for ( USHORT i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
532 *mpPSD >> nGreen;
533 if ( mpFileHeader->nDepth == 16 ) // 16 bit depth is to be skipped
534 *mpPSD >> nDummy;
535 aBitmapColor = mpReadAcc->GetPixel( nY, nX );
536 mpWriteAcc->SetPixel( nY, nX, BitmapColor( aBitmapColor.GetRed(), nGreen, aBitmapColor.GetBlue() ) );
537 if ( ++nX == mpFileHeader->nColumns )
539 nX = 0;
540 nY++;
541 if ( nY == mpFileHeader->nRows )
542 break;
547 nY = 0;
548 while ( nY < mpFileHeader->nRows )
550 if ( mbCompression )
551 *mpPSD >> nRunCount;
552 if ( nRunCount & 0x80 ) // a run length packet
554 *mpPSD >> nBlue;
555 if ( mpFileHeader->nDepth == 16 ) // 16 bit depth is to be skipped
556 *mpPSD >> nDummy;
557 for ( USHORT i = 0; i < ( -nRunCount + 1 ); i++ )
559 aBitmapColor = mpReadAcc->GetPixel( nY, nX );
560 mpWriteAcc->SetPixel( nY, nX, BitmapColor( aBitmapColor.GetRed(), aBitmapColor.GetGreen(), nBlue ) );
561 if ( ++nX == mpFileHeader->nColumns )
563 nX = 0;
564 nY++;
565 if ( nY == mpFileHeader->nRows )
566 break;
570 else // a raw packet
572 for ( USHORT i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
574 *mpPSD >> nBlue;
575 if ( mpFileHeader->nDepth == 16 ) // 16 bit depth is to be skipped
576 *mpPSD >> nDummy;
577 aBitmapColor = mpReadAcc->GetPixel( nY, nX );
578 mpWriteAcc->SetPixel( nY, nX, BitmapColor( aBitmapColor.GetRed(), aBitmapColor.GetGreen(), nBlue ) );
579 if ( ++nX == mpFileHeader->nColumns )
581 nX = 0;
582 nY++;
583 if ( nY == mpFileHeader->nRows )
584 break;
589 if ( mpFileHeader->nMode == PSD_CMYK )
591 UINT32 nBlack, nBlackMax = 0;
592 BYTE* pBlack = new BYTE[ mpFileHeader->nRows * mpFileHeader->nColumns ];
593 nY = 0;
594 while ( nY < mpFileHeader->nRows )
596 if ( mbCompression ) // else nRunCount = 0 -> so we use only single raw packets
597 *mpPSD >> nRunCount;
599 if ( nRunCount & 0x80 ) // a run length packet
601 *mpPSD >> nDat;
603 if ( mpFileHeader->nDepth == 16 ) // 16 bit depth is to be skipped
604 *mpPSD >> nDummy;
606 for ( USHORT i = 0; i < ( -nRunCount + 1 ); i++ )
608 nBlack = (BYTE)mpReadAcc->GetPixel( nY, nX ).GetRed() + nDat;
609 if ( nBlack > nBlackMax )
610 nBlackMax = nBlack;
611 nBlack = (BYTE)mpReadAcc->GetPixel( nY, nX ).GetGreen() + nDat;
612 if ( nBlack > nBlackMax )
613 nBlackMax = nBlack;
614 nBlack = (BYTE)mpReadAcc->GetPixel( nY, nX ).GetBlue() + nDat;
615 if ( nBlack > nBlackMax )
616 nBlackMax = nBlack;
617 pBlack[ nX + nY * mpFileHeader->nColumns ] = nDat ^ 0xff;
618 if ( ++nX == mpFileHeader->nColumns )
620 nX = 0;
621 nY++;
622 if ( nY == mpFileHeader->nRows )
623 break;
627 else // a raw packet
629 for ( USHORT i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
631 *mpPSD >> nDat;
633 if ( mpFileHeader->nDepth == 16 ) // 16 bit depth is to be skipped
634 *mpPSD >> nDummy;
635 nBlack = (BYTE)mpReadAcc->GetPixel( nY, nX ).GetRed() + nDat;
636 if ( nBlack > nBlackMax )
637 nBlackMax = nBlack;
638 nBlack = (BYTE)mpReadAcc->GetPixel( nY, nX ).GetGreen() + nDat;
639 if ( nBlack > nBlackMax )
640 nBlackMax = nBlack;
641 nBlack = (BYTE)mpReadAcc->GetPixel( nY, nX ).GetBlue() + nDat;
642 if ( nBlack > nBlackMax )
643 nBlackMax = nBlack;
644 pBlack[ nX + nY * mpFileHeader->nColumns ] = nDat ^ 0xff;
645 if ( ++nX == mpFileHeader->nColumns )
647 nX = 0;
648 nY++;
649 if ( nY == mpFileHeader->nRows )
650 break;
656 for ( nY = 0; nY < mpFileHeader->nRows; nY++ )
658 for ( nX = 0; nX < mpFileHeader->nColumns; nX++ )
660 INT32 nDAT = pBlack[ nX + nY * mpFileHeader->nColumns ] * ( nBlackMax - 256 ) / 0x1ff;
662 aBitmapColor = mpReadAcc->GetPixel( nY, nX );
663 BYTE cR = (BYTE) MinMax( aBitmapColor.GetRed() - nDAT, 0L, 255L );
664 BYTE cG = (BYTE) MinMax( aBitmapColor.GetGreen() - nDAT, 0L, 255L );
665 BYTE cB = (BYTE) MinMax( aBitmapColor.GetBlue() - nDAT, 0L, 255L );
666 mpWriteAcc->SetPixel( nY, nX, BitmapColor( cR, cG, cB ) );
669 delete[] pBlack;
672 break;
675 if ( mbTransparent )
677 // the psd is 24 or 8 bit grafix + alphachannel
679 nY = nX = 0;
680 while ( nY < mpFileHeader->nRows )
682 if ( mbCompression ) // else nRunCount = 0 -> so we use only single raw packets
683 *mpPSD >> nRunCount;
685 if ( nRunCount & 0x80 ) // a run length packet
687 *mpPSD >> nDat;
688 if ( nDat )
689 nDat = 0;
690 else
691 nDat = 1;
692 if ( mpFileHeader->nDepth == 16 ) // 16 bit depth is to be skipped
693 *mpPSD >> nDummy;
694 for ( USHORT i = 0; i < ( -nRunCount + 1 ); i++ )
696 mpMaskWriteAcc->SetPixel( nY, nX, (BYTE)nDat );
697 if ( ++nX == mpFileHeader->nColumns )
699 nX = 0;
700 nY++;
701 if ( nY == mpFileHeader->nRows )
702 break;
706 else // a raw packet
708 for ( USHORT i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
710 *mpPSD >> nDat;
711 if ( nDat )
712 nDat = 0;
713 else
714 nDat = 1;
715 if ( mpFileHeader->nDepth == 16 ) // 16 bit depth is to be skipped
716 *mpPSD >> nDummy;
717 mpMaskWriteAcc->SetPixel( nY, nX, (BYTE)nDat );
718 if ( ++nX == mpFileHeader->nColumns )
720 nX = 0;
721 nY++;
722 if ( nY == mpFileHeader->nRows )
723 break;
729 return TRUE;
732 //================== GraphicImport - die exportierte Funktion ================
734 extern "C" BOOL __LOADONCALLAPI GraphicImport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem*, BOOL )
736 PSDReader aPSDReader;
738 return aPSDReader.ReadPSD( rStream, rGraphic );
741 //================== ein bischen Muell fuer Windows ==========================
742 #ifndef GCC
743 #endif
745 #ifdef WIN
747 static HINSTANCE hDLLInst = 0; // HANDLE der DLL
749 extern "C" int CALLBACK LibMain( HINSTANCE hDLL, WORD, WORD nHeap, LPSTR )
751 #ifndef WNT
752 if ( nHeap )
753 UnlockData( 0 );
754 #endif
756 hDLLInst = hDLL;
758 return TRUE;
761 extern "C" int CALLBACK WEP( int )
763 return 1;
766 #endif