1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_filter.hxx"
26 
27 #include <vcl/graph.hxx>
28 #include <vcl/bmpacc.hxx>
29 #include <svtools/fltcall.hxx>
30 
31 //============================ PSDReader ==================================
32 
33 #define	PSD_BITMAP			0
34 #define PSD_GRAYSCALE 		1
35 #define PSD_INDEXED			2
36 #define PSD_RGB				3
37 #define PSD_CMYK			4
38 #define PSD_MULTICHANNEL	7
39 #define PSD_DUOTONE			8
40 #define PSD_LAB				9
41 
42 typedef struct
43 {
44 	sal_uInt32	nSignature;
45 	sal_uInt16	nVersion;
46 	sal_uInt32	nPad1;
47 	sal_uInt16	nPad2;
48 	sal_uInt16	nChannels;
49 	sal_uInt32	nRows;
50 	sal_uInt32	nColumns;
51 	sal_uInt16	nDepth;
52 	sal_uInt16	nMode;
53 
54 } PSDFileHeader;
55 
56 class PSDReader {
57 
58 private:
59 
60 	SvStream*			mpPSD;			// Die einzulesende PSD-Datei
61 	PSDFileHeader*		mpFileHeader;
62 
63     sal_uInt32          mnXResFixed;
64     sal_uInt32          mnYResFixed;
65 
66 	sal_Bool            mbStatus;
67 	sal_Bool            mbTransparent;
68 
69 	Bitmap				maBmp;
70 	Bitmap				maMaskBmp;
71 	BitmapReadAccess*	mpReadAcc;
72 	BitmapWriteAccess*	mpWriteAcc;
73 	BitmapWriteAccess*	mpMaskWriteAcc;
74 	sal_uInt16				mnDestBitDepth;
75 	sal_Bool				mbCompression;	// RLE decoding
76 	sal_uInt8*				mpPalette;
77 
78 	sal_Bool				ImplReadBody();
79 	sal_Bool				ImplReadHeader();
80 
81 public:
82 						PSDReader();
83 						~PSDReader();
84 	sal_Bool				ReadPSD( SvStream & rPSD, Graphic & rGraphic );
85 };
86 
87 //=================== Methoden von PSDReader ==============================
88 
PSDReader()89 PSDReader::PSDReader() :
90 	mpFileHeader	( NULL ),
91     mnXResFixed     ( 0 ),
92     mnYResFixed     ( 0 ),
93 	mbStatus		( sal_True ),
94 	mbTransparent	( sal_False ),
95 	mpReadAcc		( NULL ),
96 	mpWriteAcc		( NULL ),
97 	mpMaskWriteAcc	( NULL ),
98 	mpPalette		( NULL )
99 {
100 }
101 
~PSDReader()102 PSDReader::~PSDReader()
103 {
104 	delete[] mpPalette;
105 	delete mpFileHeader;
106 }
107 
108 // ------------------------------------------------------------------------
109 
ReadPSD(SvStream & rPSD,Graphic & rGraphic)110 sal_Bool PSDReader::ReadPSD( SvStream & rPSD, Graphic & rGraphic )
111 {
112 	if ( rPSD.GetError() )
113 		return sal_False;
114 
115 	mpPSD = &rPSD;
116 	mpPSD->SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
117 
118 	// Kopf einlesen:
119 
120 	if ( ImplReadHeader() == sal_False )
121 		return sal_False;
122 
123     Size aBitmapSize( mpFileHeader->nColumns, mpFileHeader->nRows );
124 	maBmp = Bitmap( aBitmapSize, mnDestBitDepth );
125 	if ( ( mpWriteAcc = maBmp.AcquireWriteAccess() ) == NULL )
126 		mbStatus = sal_False;
127 	if ( ( mpReadAcc = maBmp.AcquireReadAccess() ) == NULL )
128 		mbStatus = sal_False;
129 	if ( mbTransparent && mbStatus )
130 	{
131 		maMaskBmp = Bitmap( aBitmapSize, 1 );
132 		if ( ( mpMaskWriteAcc = maMaskBmp.AcquireWriteAccess() ) == NULL )
133 			mbStatus = sal_False;
134 	}
135 	if ( mpPalette && mbStatus )
136 	{
137 		mpWriteAcc->SetPaletteEntryCount( 256 );
138 		for ( sal_uInt16 i = 0; i < 256; i++ )
139 		{
140 			mpWriteAcc->SetPaletteColor( i, Color( mpPalette[ i ], mpPalette[ i + 256 ], mpPalette[ i + 512 ] ) );
141 		}
142 	}
143 	// Bitmap-Daten einlesen
144 	if ( mbStatus && ImplReadBody() )
145 	{
146 		if ( mbTransparent )
147 			rGraphic = Graphic( BitmapEx( maBmp, maMaskBmp ) );
148 		else
149 			rGraphic = maBmp;
150 
151         if ( mnXResFixed && mnYResFixed )
152         {
153             Point       aEmptyPoint;
154 	        Fraction	aFractX( 1, mnXResFixed >> 16 );
155 	        Fraction	aFractY( 1, mnYResFixed >> 16 );
156 	        MapMode		aMapMode( MAP_INCH, aEmptyPoint, aFractX, aFractY );
157 	        Size		aPrefSize = OutputDevice::LogicToLogic( aBitmapSize, aMapMode, MAP_100TH_MM );
158             rGraphic.SetPrefSize( aPrefSize );
159             rGraphic.SetPrefMapMode( MapMode( MAP_100TH_MM ) );
160         }
161 	}
162 	else
163 		mbStatus = sal_False;
164 	if ( mpWriteAcc )
165 		maBmp.ReleaseAccess( mpWriteAcc );
166 	if ( mpReadAcc )
167 		maBmp.ReleaseAccess( mpReadAcc );
168 	if ( mpMaskWriteAcc )
169 		maMaskBmp.ReleaseAccess( mpMaskWriteAcc );
170 	return mbStatus;
171 }
172 
173 // ------------------------------------------------------------------------
174 
ImplReadHeader()175 sal_Bool PSDReader::ImplReadHeader()
176 {
177 	sal_uInt16	nCompression;
178 	sal_uInt32	nColorLength, nResourceLength, nLayerMaskLength;
179 
180 	mpFileHeader = new PSDFileHeader;
181 
182 	if ( !mpFileHeader )
183 		return sal_False;
184 
185 	*mpPSD >> mpFileHeader->nSignature >> mpFileHeader->nVersion >> mpFileHeader->nPad1 >>
186 		mpFileHeader->nPad2 >> mpFileHeader->nChannels >> mpFileHeader->nRows >>
187 			mpFileHeader->nColumns >> mpFileHeader->nDepth >> mpFileHeader->nMode;
188 
189 	if ( ( mpFileHeader->nSignature != 0x38425053 ) || ( mpFileHeader->nVersion != 1 ) )
190 		return sal_False;
191 
192 	if ( mpFileHeader->nRows == 0 || mpFileHeader->nColumns == 0 )
193 		return sal_False;
194 
195 	if ( ( mpFileHeader->nRows > 30000 ) || ( mpFileHeader->nColumns > 30000 ) )
196 		return sal_False;
197 
198 	sal_uInt16 nDepth = mpFileHeader->nDepth;
199 	if (!( ( nDepth == 1 ) || ( nDepth == 8 ) || ( nDepth == 16 ) ) )
200 		return sal_False;
201 
202 	mnDestBitDepth = ( nDepth == 16 ) ? 8 : nDepth;
203 
204 	*mpPSD >> nColorLength;
205 	if ( mpFileHeader->nMode == PSD_CMYK )
206 	{
207 		switch ( mpFileHeader->nChannels )
208 		{
209 			case 5 :
210 				mbTransparent = sal_True;
211 			case 4 :
212 				mnDestBitDepth = 24;
213 			break;
214 			default :
215 				return sal_False;
216 		}
217 	}
218 	else switch ( mpFileHeader->nChannels )
219 	{
220 		case 2 :
221 			mbTransparent = sal_True;
222 		case 1 :
223 			break;
224 		case 4 :
225 			mbTransparent = sal_True;
226 		case 3 :
227 			mnDestBitDepth = 24;
228 			break;
229 		default:
230 			return sal_False;
231 	}
232 
233 	switch ( mpFileHeader->nMode )
234 	{
235 		case PSD_BITMAP :
236 		{
237 			if ( nColorLength || ( nDepth != 1 ) )
238 				return sal_False;
239 		}
240 		break;
241 
242 		case PSD_INDEXED :
243 		{
244 			if ( nColorLength != 768 )		// we need the color map
245 				return sal_False;
246 			mpPalette = new sal_uInt8[ 768 ];
247 			if ( mpPalette == NULL )
248 				return sal_False;
249 			mpPSD->Read( mpPalette, 768 );
250 		}
251 		break;
252 
253 		case PSD_DUOTONE :					// we'll handle the doutone color like a normal grayscale picture
254 			mpPSD->SeekRel( nColorLength );
255 			nColorLength = 0;
256 		case PSD_GRAYSCALE :
257 		{
258 			if ( nColorLength )
259 				return sal_False;
260 			mpPalette = new sal_uInt8[ 768 ];
261 			if ( mpPalette == NULL )
262 				return sal_False;
263 			for ( sal_uInt16 i = 0; i < 256; i++ )
264 			{
265 				mpPalette[ i ] = mpPalette[ i + 256 ] = mpPalette[ i + 512 ] = (sal_uInt8)i;
266 			}
267 		}
268 		break;
269 
270 		case PSD_CMYK :
271 		case PSD_RGB :
272 		case PSD_MULTICHANNEL :
273 		case PSD_LAB :
274 		{
275 			if ( nColorLength )		// color table is not supported by the other graphic modes
276 				return sal_False;
277 		}
278 		break;
279 
280 		default:
281 			return sal_False;
282 	}
283     *mpPSD >> nResourceLength;
284     sal_uInt32 nLayerPos = mpPSD->Tell() + nResourceLength;
285 
286     // this is a loop over the resource entries to get the resolution info
287     while( mpPSD->Tell() < nLayerPos )
288     {
289         sal_uInt8 n8;
290         sal_uInt32 nType, nPStringLen, nResEntryLen;
291         sal_uInt16 nUniqueID;
292 
293         *mpPSD >> nType >> nUniqueID >> n8;
294         nPStringLen = n8;
295         if ( nType != 0x3842494d )
296             break;
297         if ( ! ( nPStringLen & 1 ) )
298             nPStringLen++;
299         mpPSD->SeekRel( nPStringLen );  // skipping the pstring
300         *mpPSD >> nResEntryLen;
301         if ( nResEntryLen & 1 )
302             nResEntryLen++;             // the resource entries are padded
303         sal_uInt32 nCurrentPos = mpPSD->Tell();
304         if ( ( nResEntryLen + nCurrentPos ) > nLayerPos )   // check if size
305             break;                                          // is possible
306         switch( nUniqueID )
307         {
308             case 0x3ed :    // UID for the resolution info
309             {
310                 sal_Int16   nUnit;
311 
312                 *mpPSD >> mnXResFixed >> nUnit >> nUnit
313                        >> mnYResFixed >> nUnit >> nUnit;
314             }
315             break;
316         }
317         mpPSD->Seek( nCurrentPos + nResEntryLen );          // set the stream to the next
318     }                                                       // resource entry
319     mpPSD->Seek( nLayerPos );
320 	*mpPSD >> nLayerMaskLength;
321 	mpPSD->SeekRel( nLayerMaskLength );
322 
323 	*mpPSD >> nCompression;
324 	if ( nCompression == 0 )
325 	{
326 		mbCompression = sal_False;
327 	}
328 	else if ( nCompression == 1 )
329 	{
330 		mpPSD->SeekRel( ( mpFileHeader->nRows * mpFileHeader->nChannels ) << 1 );
331 		mbCompression = sal_True;
332 	}
333 	else
334 		return sal_False;
335 
336 	return sal_True;
337 }
338 
339 // ------------------------------------------------------------------------
340 
ImplReadBody()341 sal_Bool PSDReader::ImplReadBody()
342 {
343 	sal_uLong		nX, nY;
344 	char		nRunCount = 0;
345 	signed char	nBitCount = -1;
346 	sal_uInt8		nDat = 0, nDummy, nRed, nGreen, nBlue;
347 	BitmapColor	aBitmapColor;
348 	nX = nY = 0;
349 
350 	switch ( mnDestBitDepth )
351 	{
352 		case 1 :
353 		{
354 			while ( nY < mpFileHeader->nRows )
355 			{
356 				if ( nBitCount == -1 )
357 				{
358 					if ( mbCompression )	// else nRunCount = 0 -> so we use only single raw packets
359 						*mpPSD >> nRunCount;
360 				}
361 				if ( nRunCount & 0x80 ) 	// a run length packet
362 				{
363 					if ( nBitCount == -1 )	// bits left in nDat ?
364 					{
365 						*mpPSD >> nDat;
366 						nDat ^= 0xff;
367 						nBitCount = 7;
368 					}
369 					for ( sal_uInt16 i = 0; i < ( -nRunCount + 1 ); i++ )
370 					{
371 						mpWriteAcc->SetPixelIndex( nY, nX, nDat >> nBitCount-- );
372 						if ( ++nX == mpFileHeader->nColumns )
373 						{
374 							nX = 0;
375 							nY++;
376 							nBitCount = -1;
377 							if ( nY == mpFileHeader->nRows )
378 								break;
379 						}
380 					}
381 				}
382 				else						// a raw packet
383 				{
384 					for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
385 					{
386 						if ( nBitCount == -1 )	// bits left in nDat ?
387 						{
388 							*mpPSD >> nDat;
389 							nDat ^= 0xff;
390 							nBitCount = 7;
391 						}
392 						mpWriteAcc->SetPixelIndex( nY, nX, nDat >> nBitCount-- );
393 						if ( ++nX == mpFileHeader->nColumns )
394 						{
395 							nX = 0;
396 							nY++;
397 							nBitCount = -1;
398 							if ( nY == mpFileHeader->nRows )
399 								break;
400 						}
401 					}
402 				}
403 			}
404 		}
405 		break;
406 
407 		case 8 :
408 		{
409 			while ( nY < mpFileHeader->nRows )
410 			{
411 				if ( mbCompression )		// else nRunCount = 0 -> so we use only single raw packets
412 					*mpPSD >> nRunCount;
413 
414 				if ( nRunCount & 0x80 ) 	// a run length packet
415 				{
416 					*mpPSD >> nDat;
417 					if ( mpFileHeader->nDepth == 16 )	// 16 bit depth is to be skipped
418 						*mpPSD >> nDummy;
419 					for ( sal_uInt16 i = 0; i < ( -nRunCount + 1 ); i++ )
420 					{
421 						mpWriteAcc->SetPixelIndex( nY, nX, nDat );
422 						if ( ++nX == mpFileHeader->nColumns )
423 						{
424 							nX = 0;
425 							nY++;
426 							if ( nY == mpFileHeader->nRows )
427 								break;
428 						}
429 					}
430 				}
431 				else						// a raw packet
432 				{
433 					for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
434 					{
435 						*mpPSD >> nDat;
436 						if ( mpFileHeader->nDepth == 16 )	// 16 bit depth is to be skipped
437 							*mpPSD >> nDummy;
438 						mpWriteAcc->SetPixelIndex( nY, nX, nDat );
439 						if ( ++nX == mpFileHeader->nColumns )
440 						{
441 							nX = 0;
442 							nY++;
443 							if ( nY == mpFileHeader->nRows )
444 								break;
445 						}
446 					}
447 				}
448 			}
449 		}
450 		break;
451 
452 		case 24 :
453 		{
454 
455 			// the psd format is in plain order (RRRR GGGG BBBB) so we have to set each pixel three times
456 			// maybe the format is CCCC MMMM YYYY KKKK
457 
458 			while ( nY < mpFileHeader->nRows )
459 			{
460 				if ( mbCompression )		// else nRunCount = 0 -> so we use only single raw packets
461 					*mpPSD >> nRunCount;
462 
463 				if ( nRunCount & 0x80 ) 	// a run length packet
464 				{
465 					*mpPSD >> nRed;
466 					if ( mpFileHeader->nDepth == 16 )	// 16 bit depth is to be skipped
467 						*mpPSD >> nDummy;
468 					for ( sal_uInt16 i = 0; i < ( -nRunCount + 1 ); i++ )
469 					{
470 						mpWriteAcc->SetPixel( nY, nX, BitmapColor( nRed, (sal_uInt8)0, (sal_uInt8)0 ) );
471 						if ( ++nX == mpFileHeader->nColumns )
472 						{
473 							nX = 0;
474 							nY++;
475 							if ( nY == mpFileHeader->nRows )
476 								break;
477 						}
478 					}
479 				}
480 				else						// a raw packet
481 				{
482 					for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
483 					{
484 						*mpPSD >> nRed;
485 						if ( mpFileHeader->nDepth == 16 )	// 16 bit depth is to be skipped
486 							*mpPSD >> nDummy;
487 						mpWriteAcc->SetPixel( nY, nX, BitmapColor( nRed, (sal_uInt8)0, (sal_uInt8)0 ) );
488 						if ( ++nX == mpFileHeader->nColumns )
489 						{
490 							nX = 0;
491 							nY++;
492 							if ( nY == mpFileHeader->nRows )
493 								break;
494 						}
495 					}
496 				}
497 			}
498 			nY = 0;
499 			while ( nY < mpFileHeader->nRows )
500 			{
501 				if ( mbCompression )
502 					*mpPSD >> nRunCount;
503 				if ( nRunCount & 0x80 ) 	// a run length packet
504 				{
505 					*mpPSD >> nGreen;
506 					if ( mpFileHeader->nDepth == 16 )	// 16 bit depth is to be skipped
507 						*mpPSD >> nDummy;
508 					for ( sal_uInt16 i = 0; i < ( -nRunCount + 1 ); i++ )
509 					{
510 						aBitmapColor = mpReadAcc->GetPixel( nY, nX );
511 						mpWriteAcc->SetPixel( nY, nX, BitmapColor( aBitmapColor.GetRed(), nGreen, aBitmapColor.GetBlue() ) );
512 						if ( ++nX == mpFileHeader->nColumns )
513 						{
514 							nX = 0;
515 							nY++;
516 							if ( nY == mpFileHeader->nRows )
517 								break;
518 						}
519 					}
520 				}
521 				else						// a raw packet
522 				{
523 					for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
524 					{
525 						*mpPSD >> nGreen;
526 						if ( mpFileHeader->nDepth == 16 )	// 16 bit depth is to be skipped
527 							*mpPSD >> nDummy;
528 						aBitmapColor = mpReadAcc->GetPixel( nY, nX );
529 						mpWriteAcc->SetPixel( nY, nX, BitmapColor( aBitmapColor.GetRed(), nGreen, aBitmapColor.GetBlue() ) );
530 						if ( ++nX == mpFileHeader->nColumns )
531 						{
532 							nX = 0;
533 							nY++;
534 							if ( nY == mpFileHeader->nRows )
535 								break;
536 						}
537 					}
538 				}
539 			}
540 			nY = 0;
541 			while ( nY < mpFileHeader->nRows )
542 			{
543 				if ( mbCompression )
544 					*mpPSD >> nRunCount;
545 				if ( nRunCount & 0x80 ) 	// a run length packet
546 				{
547 					*mpPSD >> nBlue;
548 					if ( mpFileHeader->nDepth == 16 )	// 16 bit depth is to be skipped
549 						*mpPSD >> nDummy;
550 					for ( sal_uInt16 i = 0; i < ( -nRunCount + 1 ); i++ )
551 					{
552 						aBitmapColor = mpReadAcc->GetPixel( nY, nX );
553 						mpWriteAcc->SetPixel( nY, nX, BitmapColor( aBitmapColor.GetRed(), aBitmapColor.GetGreen(), nBlue ) );
554 						if ( ++nX == mpFileHeader->nColumns )
555 						{
556 							nX = 0;
557 							nY++;
558 							if ( nY == mpFileHeader->nRows )
559 								break;
560 						}
561 					}
562 				}
563 				else						// a raw packet
564 				{
565 					for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
566 					{
567 						*mpPSD >> nBlue;
568 						if ( mpFileHeader->nDepth == 16 )	// 16 bit depth is to be skipped
569 							*mpPSD >> nDummy;
570 						aBitmapColor = mpReadAcc->GetPixel( nY, nX );
571 						mpWriteAcc->SetPixel( nY, nX, BitmapColor( aBitmapColor.GetRed(), aBitmapColor.GetGreen(), nBlue ) );
572 						if ( ++nX == mpFileHeader->nColumns )
573 						{
574 							nX = 0;
575 							nY++;
576 							if ( nY == mpFileHeader->nRows )
577 								break;
578 						}
579 					}
580 				}
581 			}
582 			if ( mpFileHeader->nMode == PSD_CMYK )
583 			{
584 				sal_uInt32	nBlack, nBlackMax = 0;
585 				sal_uInt8*	pBlack = new sal_uInt8[ mpFileHeader->nRows * mpFileHeader->nColumns ];
586 				nY = 0;
587 				while ( nY < mpFileHeader->nRows )
588 				{
589 					if ( mbCompression )		// else nRunCount = 0 -> so we use only single raw packets
590 						*mpPSD >> nRunCount;
591 
592 					if ( nRunCount & 0x80 ) 	// a run length packet
593 					{
594 						*mpPSD >> nDat;
595 
596 						if ( mpFileHeader->nDepth == 16 )	// 16 bit depth is to be skipped
597 							*mpPSD >> nDummy;
598 
599 						for ( sal_uInt16 i = 0; i < ( -nRunCount + 1 ); i++ )
600 						{
601 							nBlack = (sal_uInt8)mpReadAcc->GetPixel( nY, nX ).GetRed() + nDat;
602 							if ( nBlack > nBlackMax )
603 								nBlackMax = nBlack;
604 							nBlack = (sal_uInt8)mpReadAcc->GetPixel( nY, nX ).GetGreen() + nDat;
605 							if ( nBlack > nBlackMax )
606 								nBlackMax = nBlack;
607 							nBlack = (sal_uInt8)mpReadAcc->GetPixel( nY, nX ).GetBlue() + nDat;
608 							if ( nBlack > nBlackMax )
609 								nBlackMax = nBlack;
610 							pBlack[ nX + nY * mpFileHeader->nColumns ] = nDat ^ 0xff;
611 							if ( ++nX == mpFileHeader->nColumns )
612 							{
613 								nX = 0;
614 								nY++;
615 							if ( nY == mpFileHeader->nRows )
616 								break;
617 							}
618 						}
619 					}
620 					else						// a raw packet
621 					{
622 						for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
623 						{
624 							*mpPSD >> nDat;
625 
626 							if ( mpFileHeader->nDepth == 16 )	// 16 bit depth is to be skipped
627 								*mpPSD >> nDummy;
628 							nBlack = (sal_uInt8)mpReadAcc->GetPixel( nY, nX ).GetRed() + nDat;
629 							if ( nBlack > nBlackMax )
630 								nBlackMax = nBlack;
631 							nBlack = (sal_uInt8)mpReadAcc->GetPixel( nY, nX ).GetGreen() + nDat;
632 							if ( nBlack > nBlackMax )
633 								nBlackMax = nBlack;
634 							nBlack = (sal_uInt8)mpReadAcc->GetPixel( nY, nX ).GetBlue() + nDat;
635 							if ( nBlack > nBlackMax )
636 								nBlackMax = nBlack;
637 							pBlack[ nX + nY * mpFileHeader->nColumns ] = nDat ^ 0xff;
638 							if ( ++nX == mpFileHeader->nColumns )
639 							{
640 								nX = 0;
641 								nY++;
642 								if ( nY == mpFileHeader->nRows )
643 									break;
644 							}
645 						}
646 					}
647 				}
648 
649 				for ( nY = 0; nY < mpFileHeader->nRows; nY++ )
650 				{
651 					for ( nX = 0; nX < mpFileHeader->nColumns; nX++ )
652 					{
653 						sal_Int32 nDAT = pBlack[ nX + nY * mpFileHeader->nColumns ] * ( nBlackMax - 256 ) / 0x1ff;
654 
655 						aBitmapColor = mpReadAcc->GetPixel( nY, nX );
656 						sal_uInt8 cR = (sal_uInt8) MinMax( aBitmapColor.GetRed() - nDAT, 0L, 255L );
657 						sal_uInt8 cG = (sal_uInt8) MinMax( aBitmapColor.GetGreen() - nDAT, 0L, 255L );
658 						sal_uInt8 cB = (sal_uInt8) MinMax( aBitmapColor.GetBlue() - nDAT, 0L, 255L );
659 						mpWriteAcc->SetPixel( nY, nX, BitmapColor( cR, cG, cB ) );
660 					}
661 				}
662 				delete[] pBlack;
663 			}
664 		}
665 		break;
666 	}
667 
668 	if ( mbTransparent )
669 	{
670 		// the psd is 24 or 8 bit grafix + alphachannel
671 
672 		nY = nX = 0;
673 		while ( nY < mpFileHeader->nRows )
674 		{
675 			if ( mbCompression )		// else nRunCount = 0 -> so we use only single raw packets
676 				*mpPSD >> nRunCount;
677 
678 			if ( nRunCount & 0x80 ) 	// a run length packet
679 			{
680 				*mpPSD >> nDat;
681 				if ( nDat )
682 					nDat = 0;
683 				else
684 					nDat = 1;
685 				if ( mpFileHeader->nDepth == 16 )	// 16 bit depth is to be skipped
686 					*mpPSD >> nDummy;
687 				for ( sal_uInt16 i = 0; i < ( -nRunCount + 1 ); i++ )
688 				{
689 					mpMaskWriteAcc->SetPixelIndex( nY, nX, nDat );
690 					if ( ++nX == mpFileHeader->nColumns )
691 					{
692 						nX = 0;
693 						nY++;
694 						if ( nY == mpFileHeader->nRows )
695 							break;
696 					}
697 				}
698 			}
699 			else						// a raw packet
700 			{
701 				for ( sal_uInt16 i = 0; i < ( ( nRunCount & 0x7f ) + 1 ); i++ )
702 				{
703 					*mpPSD >> nDat;
704 					if ( nDat )
705 						nDat = 0;
706 					else
707 						nDat = 1;
708 					if ( mpFileHeader->nDepth == 16 )	// 16 bit depth is to be skipped
709 						*mpPSD >> nDummy;
710 					mpMaskWriteAcc->SetPixelIndex( nY, nX, nDat );
711 					if ( ++nX == mpFileHeader->nColumns )
712 					{
713 						nX = 0;
714 						nY++;
715 						if ( nY == mpFileHeader->nRows )
716 							break;
717 					}
718 				}
719 			}
720 		}
721 	}
722 	return sal_True;
723 }
724 
725 //================== GraphicImport - die exportierte Funktion ================
726 
GraphicImport(SvStream & rStream,Graphic & rGraphic,FilterConfigItem *,sal_Bool)727 extern "C" sal_Bool __LOADONCALLAPI GraphicImport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem*, sal_Bool )
728 {
729 	PSDReader aPSDReader;
730 
731 	return aPSDReader.ReadPSD( rStream, rGraphic );
732 }
733 
734