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