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