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