• 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
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
27typedef TQ_UINT32 uint;
28typedef TQ_UINT16 ushort;
29typedef TQ_UINT8 uchar;
30
31namespace { // 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
241void 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
278void 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.4
This website is maintained by Timothy Pearson.