• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kimgio
 

kimgio

  • kimgio
psd.cpp
1 /* This file is part of the KDE project
2  Copyright (C) 2003 Ignacio Castaņo <castano@ludicon.com>
3 
4  This program is free software; you can redistribute it and/or
5  modify it under the terms of the Lesser GNU General Public
6  License as published by the Free Software Foundation; either
7  version 2 of the License, or (at your option) any later version.
8 
9  This code is based on Thacher Ulrich PSD loading code released
10  on public domain. See: http://tulrich.com/geekstuff/
11 */
12 
13 /* this code supports:
14  * reading:
15  * rle and raw psd files
16  * writing:
17  * not supported
18  */
19 
20 #include "psd.h"
21 
22 #include <tqimage.h>
23 #include <tqdatastream.h>
24 
25 #include <kdebug.h>
26 
27 typedef TQ_UINT32 uint;
28 typedef TQ_UINT16 ushort;
29 typedef TQ_UINT8 uchar;
30 
31 namespace { // Private.
32 
33  enum ColorMode {
34  CM_BITMAP = 0,
35  CM_GRAYSCALE = 1,
36  CM_INDEXED = 2,
37  CM_RGB = 3,
38  CM_CMYK = 4,
39  CM_MULTICHANNEL = 7,
40  CM_DUOTONE = 8,
41  CM_LABCOLOR = 9
42  };
43 
44  struct PSDHeader {
45  uint signature;
46  ushort version;
47  uchar reserved[6];
48  ushort channel_count;
49  uint height;
50  uint width;
51  ushort depth;
52  ushort color_mode;
53  };
54 
55  static TQDataStream & operator>> ( TQDataStream & s, PSDHeader & header )
56  {
57  s >> header.signature;
58  s >> header.version;
59  for( int i = 0; i < 6; i++ ) {
60  s >> header.reserved[i];
61  }
62  s >> header.channel_count;
63  s >> header.height;
64  s >> header.width;
65  s >> header.depth;
66  s >> header.color_mode;
67  return s;
68  }
69  static bool seekBy(TQDataStream& s, unsigned int bytes)
70  {
71  char buf[4096];
72  while (bytes) {
73  unsigned int num= TQMIN(bytes,sizeof(buf));
74  unsigned int l = num;
75  s.readRawBytes(buf, l);
76  if(l != num)
77  return false;
78  bytes -= num;
79  }
80  return true;
81  }
82 
83  // Check that the header is a valid PSD.
84  static bool IsValid( const PSDHeader & header )
85  {
86  if( header.signature != 0x38425053 ) { // '8BPS'
87  return false;
88  }
89  return true;
90  }
91 
92  // Check that the header is supported.
93  static bool IsSupported( const PSDHeader & header )
94  {
95  if( header.version != 1 ) {
96  return false;
97  }
98  if( header.channel_count > 16 ) {
99  return false;
100  }
101  if( header.depth != 8 ) {
102  return false;
103  }
104  if( header.color_mode != CM_RGB ) {
105  return false;
106  }
107  return true;
108  }
109 
110  // Load the PSD image.
111  static bool LoadPSD( TQDataStream & s, const PSDHeader & header, TQImage & img )
112  {
113  // Create dst image.
114  if( !img.create( header.width, header.height, 32 )) {
115  return false;
116  }
117 
118  uint tmp;
119 
120  // Skip mode data.
121  s >> tmp;
122  s.device()->at( s.device()->at() + tmp );
123 
124  // Skip image resources.
125  s >> tmp;
126  s.device()->at( s.device()->at() + tmp );
127 
128  // Skip the reserved data.
129  s >> tmp;
130  s.device()->at( s.device()->at() + tmp );
131 
132  // Find out if the data is compressed.
133  // Known values:
134  // 0: no compression
135  // 1: RLE compressed
136  ushort compression;
137  s >> compression;
138 
139  if( compression > 1 ) {
140  // Unknown compression type.
141  return false;
142  }
143 
144  uint channel_num = header.channel_count;
145 
146  // Clear the image.
147  if( channel_num < 4 ) {
148  img.fill(tqRgba(0, 0, 0, 0xFF));
149  }
150  else {
151  // Enable alpha.
152  img.setAlphaBuffer( true );
153 
154  // Ignore the other channels.
155  channel_num = 4;
156  }
157 
158  const uint pixel_count = header.height * header.width;
159 
160  static const uint components[4] = {2, 1, 0, 3}; // @@ Is this endian dependant?
161 
162  if( compression ) {
163 
164  // Skip row lengths.
165  if(!seekBy(s, header.height*header.channel_count*sizeof(ushort)))
166  return false;
167 
168  // Read RLE data.
169  for(uint channel = 0; channel < channel_num; channel++) {
170 
171  uchar * ptr = img.bits() + components[channel];
172 
173  uint count = 0;
174  while( count < pixel_count ) {
175  uchar c;
176  if(s.atEnd())
177  return false;
178  s >> c;
179  uint len = c;
180 
181  if( len < 128 ) {
182  // Copy next len+1 bytes literally.
183  len++;
184  count += len;
185  if ( count > pixel_count )
186  return false;
187 
188  while( len != 0 ) {
189  s >> *ptr;
190  ptr += 4;
191  len--;
192  }
193  }
194  else if( len > 128 ) {
195  // Next -len+1 bytes in the dest are replicated from next source byte.
196  // (Interpret len as a negative 8-bit int.)
197  len ^= 0xFF;
198  len += 2;
199  count += len;
200  if(s.atEnd() || count > pixel_count)
201  return false;
202  uchar val;
203  s >> val;
204  while( len != 0 ) {
205  *ptr = val;
206  ptr += 4;
207  len--;
208  }
209  }
210  else if( len == 128 ) {
211  // No-op.
212  }
213  }
214  }
215  }
216  else {
217  // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...)
218  // where each channel consists of an 8-bit value for each pixel in the image.
219 
220  // Read the data by channel.
221  for(uint channel = 0; channel < channel_num; channel++) {
222 
223  uchar * ptr = img.bits() + components[channel];
224 
225  // Read the data.
226  uint count = pixel_count;
227  while( count != 0 ) {
228  s >> *ptr;
229  ptr += 4;
230  count--;
231  }
232  }
233  }
234 
235  return true;
236  }
237 
238 } // Private
239 
240 
241 void kimgio_psd_read( TQImageIO *io )
242 {
243  TQDataStream s( io->ioDevice() );
244  s.setByteOrder( TQDataStream::BigEndian );
245 
246  PSDHeader header;
247  s >> header;
248 
249  // Check image file format.
250  if( s.atEnd() || !IsValid( header ) ) {
251  kdDebug(399) << "This PSD file is not valid." << endl;
252  io->setImage( TQImage() );
253  io->setStatus( -1 );
254  return;
255  }
256 
257  // Check if it's a supported format.
258  if( !IsSupported( header ) ) {
259  kdDebug(399) << "This PSD file is not supported." << endl;
260  io->setImage( TQImage() );
261  io->setStatus( -1 );
262  return;
263  }
264 
265  TQImage img;
266  if( !LoadPSD(s, header, img) ) {
267  kdDebug(399) << "Error loading PSD file." << endl;
268  io->setImage( TQImage() );
269  io->setStatus( -1 );
270  return;
271  }
272 
273  io->setImage( img );
274  io->setStatus( 0 );
275 }
276 
277 
278 void kimgio_psd_write( TQImageIO * )
279 {
280  // TODO Stub!
281 }
282 

kimgio

Skip menu "kimgio"
  • Main Page
  • File List
  • Related Pages

kimgio

Skip menu "kimgio"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for kimgio by doxygen 1.9.1
This website is maintained by Timothy Pearson.