aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8/source/Irrlicht/CImageLoaderPSD.cpp
diff options
context:
space:
mode:
authorDavid Walter Seikel2013-01-13 18:54:10 +1000
committerDavid Walter Seikel2013-01-13 18:54:10 +1000
commit959831f4ef5a3e797f576c3de08cd65032c997ad (patch)
treee7351908be5995f0b325b2ebeaa02d5a34b82583 /libraries/irrlicht-1.8/source/Irrlicht/CImageLoaderPSD.cpp
parentAdd info about changes to Irrlicht. (diff)
downloadSledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.zip
SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.gz
SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.bz2
SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.xz
Remove damned ancient DOS line endings from Irrlicht. Hopefully I did not go overboard.
Diffstat (limited to '')
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/CImageLoaderPSD.cpp750
1 files changed, 375 insertions, 375 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CImageLoaderPSD.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CImageLoaderPSD.cpp
index 3eb5c3b..8c8ae2e 100644
--- a/libraries/irrlicht-1.8/source/Irrlicht/CImageLoaderPSD.cpp
+++ b/libraries/irrlicht-1.8/source/Irrlicht/CImageLoaderPSD.cpp
@@ -1,375 +1,375 @@
1// Copyright (C) 2002-2012 Nikolaus Gebhardt 1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// This file is part of the "Irrlicht Engine". 2// This file is part of the "Irrlicht Engine".
3// For conditions of distribution and use, see copyright notice in irrlicht.h 3// For conditions of distribution and use, see copyright notice in irrlicht.h
4 4
5#include "CImageLoaderPSD.h" 5#include "CImageLoaderPSD.h"
6 6
7#ifdef _IRR_COMPILE_WITH_PSD_LOADER_ 7#ifdef _IRR_COMPILE_WITH_PSD_LOADER_
8 8
9#include "IReadFile.h" 9#include "IReadFile.h"
10#include "os.h" 10#include "os.h"
11#include "CImage.h" 11#include "CImage.h"
12#include "irrString.h" 12#include "irrString.h"
13 13
14 14
15namespace irr 15namespace irr
16{ 16{
17namespace video 17namespace video
18{ 18{
19 19
20 20
21//! constructor 21//! constructor
22CImageLoaderPSD::CImageLoaderPSD() 22CImageLoaderPSD::CImageLoaderPSD()
23{ 23{
24 #ifdef _DEBUG 24 #ifdef _DEBUG
25 setDebugName("CImageLoaderPSD"); 25 setDebugName("CImageLoaderPSD");
26 #endif 26 #endif
27} 27}
28 28
29 29
30//! returns true if the file maybe is able to be loaded by this class 30//! returns true if the file maybe is able to be loaded by this class
31//! based on the file extension (e.g. ".tga") 31//! based on the file extension (e.g. ".tga")
32bool CImageLoaderPSD::isALoadableFileExtension(const io::path& filename) const 32bool CImageLoaderPSD::isALoadableFileExtension(const io::path& filename) const
33{ 33{
34 return core::hasFileExtension ( filename, "psd" ); 34 return core::hasFileExtension ( filename, "psd" );
35} 35}
36 36
37 37
38 38
39//! returns true if the file maybe is able to be loaded by this class 39//! returns true if the file maybe is able to be loaded by this class
40bool CImageLoaderPSD::isALoadableFileFormat(io::IReadFile* file) const 40bool CImageLoaderPSD::isALoadableFileFormat(io::IReadFile* file) const
41{ 41{
42 if (!file) 42 if (!file)
43 return false; 43 return false;
44 44
45 u8 type[3]; 45 u8 type[3];
46 file->read(&type, sizeof(u8)*3); 46 file->read(&type, sizeof(u8)*3);
47 return (type[2]==2); // we currently only handle tgas of type 2. 47 return (type[2]==2); // we currently only handle tgas of type 2.
48} 48}
49 49
50 50
51 51
52//! creates a surface from the file 52//! creates a surface from the file
53IImage* CImageLoaderPSD::loadImage(io::IReadFile* file) const 53IImage* CImageLoaderPSD::loadImage(io::IReadFile* file) const
54{ 54{
55 u32* imageData = 0; 55 u32* imageData = 0;
56 56
57 PsdHeader header; 57 PsdHeader header;
58 file->read(&header, sizeof(PsdHeader)); 58 file->read(&header, sizeof(PsdHeader));
59 59
60#ifndef __BIG_ENDIAN__ 60#ifndef __BIG_ENDIAN__
61 header.version = os::Byteswap::byteswap(header.version); 61 header.version = os::Byteswap::byteswap(header.version);
62 header.channels = os::Byteswap::byteswap(header.channels); 62 header.channels = os::Byteswap::byteswap(header.channels);
63 header.height = os::Byteswap::byteswap(header.height); 63 header.height = os::Byteswap::byteswap(header.height);
64 header.width = os::Byteswap::byteswap(header.width); 64 header.width = os::Byteswap::byteswap(header.width);
65 header.depth = os::Byteswap::byteswap(header.depth); 65 header.depth = os::Byteswap::byteswap(header.depth);
66 header.mode = os::Byteswap::byteswap(header.mode); 66 header.mode = os::Byteswap::byteswap(header.mode);
67#endif 67#endif
68 68
69 if (header.signature[0] != '8' || 69 if (header.signature[0] != '8' ||
70 header.signature[1] != 'B' || 70 header.signature[1] != 'B' ||
71 header.signature[2] != 'P' || 71 header.signature[2] != 'P' ||
72 header.signature[3] != 'S') 72 header.signature[3] != 'S')
73 return 0; 73 return 0;
74 74
75 if (header.version != 1) 75 if (header.version != 1)
76 { 76 {
77 os::Printer::log("Unsupported PSD file version", file->getFileName(), ELL_ERROR); 77 os::Printer::log("Unsupported PSD file version", file->getFileName(), ELL_ERROR);
78 return 0; 78 return 0;
79 } 79 }
80 80
81 if (header.mode != 3 || header.depth != 8) 81 if (header.mode != 3 || header.depth != 8)
82 { 82 {
83 os::Printer::log("Unsupported PSD color mode or depth.\n", file->getFileName(), ELL_ERROR); 83 os::Printer::log("Unsupported PSD color mode or depth.\n", file->getFileName(), ELL_ERROR);
84 return 0; 84 return 0;
85 } 85 }
86 86
87 // skip color mode data 87 // skip color mode data
88 88
89 u32 l; 89 u32 l;
90 file->read(&l, sizeof(u32)); 90 file->read(&l, sizeof(u32));
91#ifndef __BIG_ENDIAN__ 91#ifndef __BIG_ENDIAN__
92 l = os::Byteswap::byteswap(l); 92 l = os::Byteswap::byteswap(l);
93#endif 93#endif
94 if (!file->seek(l, true)) 94 if (!file->seek(l, true))
95 { 95 {
96 os::Printer::log("Error seeking file pos to image resources.\n", file->getFileName(), ELL_ERROR); 96 os::Printer::log("Error seeking file pos to image resources.\n", file->getFileName(), ELL_ERROR);
97 return 0; 97 return 0;
98 } 98 }
99 99
100 // skip image resources 100 // skip image resources
101 101
102 file->read(&l, sizeof(u32)); 102 file->read(&l, sizeof(u32));
103#ifndef __BIG_ENDIAN__ 103#ifndef __BIG_ENDIAN__
104 l = os::Byteswap::byteswap(l); 104 l = os::Byteswap::byteswap(l);
105#endif 105#endif
106 if (!file->seek(l, true)) 106 if (!file->seek(l, true))
107 { 107 {
108 os::Printer::log("Error seeking file pos to layer and mask.\n", file->getFileName(), ELL_ERROR); 108 os::Printer::log("Error seeking file pos to layer and mask.\n", file->getFileName(), ELL_ERROR);
109 return 0; 109 return 0;
110 } 110 }
111 111
112 // skip layer & mask 112 // skip layer & mask
113 113
114 file->read(&l, sizeof(u32)); 114 file->read(&l, sizeof(u32));
115#ifndef __BIG_ENDIAN__ 115#ifndef __BIG_ENDIAN__
116 l = os::Byteswap::byteswap(l); 116 l = os::Byteswap::byteswap(l);
117#endif 117#endif
118 if (!file->seek(l, true)) 118 if (!file->seek(l, true))
119 { 119 {
120 os::Printer::log("Error seeking file pos to image data section.\n", file->getFileName(), ELL_ERROR); 120 os::Printer::log("Error seeking file pos to image data section.\n", file->getFileName(), ELL_ERROR);
121 return 0; 121 return 0;
122 } 122 }
123 123
124 // read image data 124 // read image data
125 125
126 u16 compressionType; 126 u16 compressionType;
127 file->read(&compressionType, sizeof(u16)); 127 file->read(&compressionType, sizeof(u16));
128#ifndef __BIG_ENDIAN__ 128#ifndef __BIG_ENDIAN__
129 compressionType = os::Byteswap::byteswap(compressionType); 129 compressionType = os::Byteswap::byteswap(compressionType);
130#endif 130#endif
131 131
132 if (compressionType != 1 && compressionType != 0) 132 if (compressionType != 1 && compressionType != 0)
133 { 133 {
134 os::Printer::log("Unsupported psd compression mode.\n", file->getFileName(), ELL_ERROR); 134 os::Printer::log("Unsupported psd compression mode.\n", file->getFileName(), ELL_ERROR);
135 return 0; 135 return 0;
136 } 136 }
137 137
138 // create image data block 138 // create image data block
139 139
140 imageData = new u32[header.width * header.height]; 140 imageData = new u32[header.width * header.height];
141 141
142 bool res = false; 142 bool res = false;
143 143
144 if (compressionType == 0) 144 if (compressionType == 0)
145 res = readRawImageData(file, header, imageData); // RAW image data 145 res = readRawImageData(file, header, imageData); // RAW image data
146 else 146 else
147 res = readRLEImageData(file, header, imageData); // RLE compressed data 147 res = readRLEImageData(file, header, imageData); // RLE compressed data
148 148
149 video::IImage* image = 0; 149 video::IImage* image = 0;
150 150
151 if (res) 151 if (res)
152 { 152 {
153 // create surface 153 // create surface
154 image = new CImage(ECF_A8R8G8B8, 154 image = new CImage(ECF_A8R8G8B8,
155 core::dimension2d<u32>(header.width, header.height), imageData); 155 core::dimension2d<u32>(header.width, header.height), imageData);
156 } 156 }
157 157
158 if (!image) 158 if (!image)
159 delete [] imageData; 159 delete [] imageData;
160 imageData = 0; 160 imageData = 0;
161 161
162 return image; 162 return image;
163} 163}
164 164
165 165
166bool CImageLoaderPSD::readRawImageData(io::IReadFile* file, const PsdHeader& header, u32* imageData) const 166bool CImageLoaderPSD::readRawImageData(io::IReadFile* file, const PsdHeader& header, u32* imageData) const
167{ 167{
168 u8* tmpData = new u8[header.width * header.height]; 168 u8* tmpData = new u8[header.width * header.height];
169 169
170 for (s32 channel=0; channel<header.channels && channel < 3; ++channel) 170 for (s32 channel=0; channel<header.channels && channel < 3; ++channel)
171 { 171 {
172 if (!file->read(tmpData, sizeof(c8) * header.width * header.height)) 172 if (!file->read(tmpData, sizeof(c8) * header.width * header.height))
173 { 173 {
174 os::Printer::log("Error reading color channel\n", file->getFileName(), ELL_ERROR); 174 os::Printer::log("Error reading color channel\n", file->getFileName(), ELL_ERROR);
175 break; 175 break;
176 } 176 }
177 177
178 s16 shift = getShiftFromChannel((c8)channel, header); 178 s16 shift = getShiftFromChannel((c8)channel, header);
179 if (shift != -1) 179 if (shift != -1)
180 { 180 {
181 u32 mask = 0xff << shift; 181 u32 mask = 0xff << shift;
182 182
183 for (u32 x=0; x<header.width; ++x) 183 for (u32 x=0; x<header.width; ++x)
184 { 184 {
185 for (u32 y=0; y<header.height; ++y) 185 for (u32 y=0; y<header.height; ++y)
186 { 186 {
187 s32 index = x + y*header.width; 187 s32 index = x + y*header.width;
188 imageData[index] = ~(~imageData[index] | mask); 188 imageData[index] = ~(~imageData[index] | mask);
189 imageData[index] |= tmpData[index] << shift; 189 imageData[index] |= tmpData[index] << shift;
190 } 190 }
191 } 191 }
192 } 192 }
193 193
194 } 194 }
195 195
196 delete [] tmpData; 196 delete [] tmpData;
197 return true; 197 return true;
198} 198}
199 199
200 200
201bool CImageLoaderPSD::readRLEImageData(io::IReadFile* file, const PsdHeader& header, u32* imageData) const 201bool CImageLoaderPSD::readRLEImageData(io::IReadFile* file, const PsdHeader& header, u32* imageData) const
202{ 202{
203 /* If the compression code is 1, the image data 203 /* If the compression code is 1, the image data
204 starts with the byte counts for all the scan lines in the channel 204 starts with the byte counts for all the scan lines in the channel
205 (LayerBottom LayerTop), with each count stored as a two 205 (LayerBottom LayerTop), with each count stored as a two
206 byte value. The RLE compressed data follows, with each scan line 206 byte value. The RLE compressed data follows, with each scan line
207 compressed separately. The RLE compression is the same compres-sion 207 compressed separately. The RLE compression is the same compres-sion
208 algorithm used by the Macintosh ROM routine PackBits, and 208 algorithm used by the Macintosh ROM routine PackBits, and
209 the TIFF standard. 209 the TIFF standard.
210 If the Layer's Size, and therefore the data, is odd, a pad byte will 210 If the Layer's Size, and therefore the data, is odd, a pad byte will
211 be inserted at the end of the row. 211 be inserted at the end of the row.
212 */ 212 */
213 213
214 /* 214 /*
215 A pseudo code fragment to unpack might look like this: 215 A pseudo code fragment to unpack might look like this:
216 216
217 Loop until you get the number of unpacked bytes you are expecting: 217 Loop until you get the number of unpacked bytes you are expecting:
218 Read the next source byte into n. 218 Read the next source byte into n.
219 If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. 219 If n is between 0 and 127 inclusive, copy the next n+1 bytes literally.
220 Else if n is between -127 and -1 inclusive, copy the next byte -n+1 220 Else if n is between -127 and -1 inclusive, copy the next byte -n+1
221 times. 221 times.
222 Else if n is -128, noop. 222 Else if n is -128, noop.
223 Endloop 223 Endloop
224 224
225 In the inverse routine, it is best to encode a 2-byte repeat run as a replicate run 225 In the inverse routine, it is best to encode a 2-byte repeat run as a replicate run
226 except when preceded and followed by a literal run. In that case, it is best to merge 226 except when preceded and followed by a literal run. In that case, it is best to merge
227 the three runs into one literal run. Always encode 3-byte repeats as replicate runs. 227 the three runs into one literal run. Always encode 3-byte repeats as replicate runs.
228 That is the essence of the algorithm. Here are some additional rules: 228 That is the essence of the algorithm. Here are some additional rules:
229 - Pack each row separately. Do not compress across row boundaries. 229 - Pack each row separately. Do not compress across row boundaries.
230 - The number of uncompressed bytes per row is defined to be (ImageWidth + 7) 230 - The number of uncompressed bytes per row is defined to be (ImageWidth + 7)
231 / 8. If the uncompressed bitmap is required to have an even number of bytes per 231 / 8. If the uncompressed bitmap is required to have an even number of bytes per
232 row, decompress into word-aligned buffers. 232 row, decompress into word-aligned buffers.
233 - If a run is larger than 128 bytes, encode the remainder of the run as one or more 233 - If a run is larger than 128 bytes, encode the remainder of the run as one or more
234 additional replicate runs. 234 additional replicate runs.
235 When PackBits data is decompressed, the result should be interpreted as per com-pression 235 When PackBits data is decompressed, the result should be interpreted as per com-pression
236 type 1 (no compression). 236 type 1 (no compression).
237 */ 237 */
238 238
239 u8* tmpData = new u8[header.width * header.height]; 239 u8* tmpData = new u8[header.width * header.height];
240 u16 *rleCount= new u16 [header.height * header.channels]; 240 u16 *rleCount= new u16 [header.height * header.channels];
241 241
242 s32 size=0; 242 s32 size=0;
243 243
244 for (u32 y=0; y<header.height * header.channels; ++y) 244 for (u32 y=0; y<header.height * header.channels; ++y)
245 { 245 {
246 if (!file->read(&rleCount[y], sizeof(u16))) 246 if (!file->read(&rleCount[y], sizeof(u16)))
247 { 247 {
248 delete [] tmpData; 248 delete [] tmpData;
249 delete [] rleCount; 249 delete [] rleCount;
250 os::Printer::log("Error reading rle rows\n", file->getFileName(), ELL_ERROR); 250 os::Printer::log("Error reading rle rows\n", file->getFileName(), ELL_ERROR);
251 return false; 251 return false;
252 } 252 }
253 253
254#ifndef __BIG_ENDIAN__ 254#ifndef __BIG_ENDIAN__
255 rleCount[y] = os::Byteswap::byteswap(rleCount[y]); 255 rleCount[y] = os::Byteswap::byteswap(rleCount[y]);
256#endif 256#endif
257 size += rleCount[y]; 257 size += rleCount[y];
258 } 258 }
259 259
260 s8 *buf = new s8[size]; 260 s8 *buf = new s8[size];
261 if (!file->read(buf, size)) 261 if (!file->read(buf, size))
262 { 262 {
263 delete [] rleCount; 263 delete [] rleCount;
264 delete [] buf; 264 delete [] buf;
265 delete [] tmpData; 265 delete [] tmpData;
266 os::Printer::log("Error reading rle rows\n", file->getFileName(), ELL_ERROR); 266 os::Printer::log("Error reading rle rows\n", file->getFileName(), ELL_ERROR);
267 return false; 267 return false;
268 } 268 }
269 269
270 u16 *rcount=rleCount; 270 u16 *rcount=rleCount;
271 271
272 s8 rh; 272 s8 rh;
273 u16 bytesRead; 273 u16 bytesRead;
274 u8 *dest; 274 u8 *dest;
275 s8 *pBuf = buf; 275 s8 *pBuf = buf;
276 276
277 // decompress packbit rle 277 // decompress packbit rle
278 278
279 for (s32 channel=0; channel<header.channels; channel++) 279 for (s32 channel=0; channel<header.channels; channel++)
280 { 280 {
281 for (u32 y=0; y<header.height; ++y, ++rcount) 281 for (u32 y=0; y<header.height; ++y, ++rcount)
282 { 282 {
283 bytesRead=0; 283 bytesRead=0;
284 dest = &tmpData[y*header.width]; 284 dest = &tmpData[y*header.width];
285 285
286 while (bytesRead < *rcount) 286 while (bytesRead < *rcount)
287 { 287 {
288 rh = *pBuf++; 288 rh = *pBuf++;
289 ++bytesRead; 289 ++bytesRead;
290 290
291 if (rh >= 0) 291 if (rh >= 0)
292 { 292 {
293 ++rh; 293 ++rh;
294 294
295 while (rh--) 295 while (rh--)
296 { 296 {
297 *dest = *pBuf++; 297 *dest = *pBuf++;
298 ++bytesRead; 298 ++bytesRead;
299 ++dest; 299 ++dest;
300 } 300 }
301 } 301 }
302 else 302 else
303 if (rh > -128) 303 if (rh > -128)
304 { 304 {
305 rh = -rh +1; 305 rh = -rh +1;
306 306
307 while (rh--) 307 while (rh--)
308 { 308 {
309 *dest = *pBuf; 309 *dest = *pBuf;
310 ++dest; 310 ++dest;
311 } 311 }
312 312
313 ++pBuf; 313 ++pBuf;
314 ++bytesRead; 314 ++bytesRead;
315 } 315 }
316 } 316 }
317 } 317 }
318 318
319 s16 shift = getShiftFromChannel((c8)channel, header); 319 s16 shift = getShiftFromChannel((c8)channel, header);
320 320
321 if (shift != -1) 321 if (shift != -1)
322 { 322 {
323 u32 mask = 0xff << shift; 323 u32 mask = 0xff << shift;
324 324
325 for (u32 x=0; x<header.width; ++x) 325 for (u32 x=0; x<header.width; ++x)
326 for (u32 y=0; y<header.height; ++y) 326 for (u32 y=0; y<header.height; ++y)
327 { 327 {
328 s32 index = x + y*header.width; 328 s32 index = x + y*header.width;
329 imageData[index] = ~(~imageData[index] | mask); 329 imageData[index] = ~(~imageData[index] | mask);
330 imageData[index] |= tmpData[index] << shift; 330 imageData[index] |= tmpData[index] << shift;
331 } 331 }
332 } 332 }
333 } 333 }
334 334
335 delete [] rleCount; 335 delete [] rleCount;
336 delete [] buf; 336 delete [] buf;
337 delete [] tmpData; 337 delete [] tmpData;
338 338
339 return true; 339 return true;
340} 340}
341 341
342 342
343s16 CImageLoaderPSD::getShiftFromChannel(c8 channelNr, const PsdHeader& header) const 343s16 CImageLoaderPSD::getShiftFromChannel(c8 channelNr, const PsdHeader& header) const
344{ 344{
345 switch(channelNr) 345 switch(channelNr)
346 { 346 {
347 case 0: 347 case 0:
348 return 16; // red 348 return 16; // red
349 case 1: 349 case 1:
350 return 8; // green 350 return 8; // green
351 case 2: 351 case 2:
352 return 0; // blue 352 return 0; // blue
353 case 3: 353 case 3:
354 return header.channels == 4 ? 24 : -1; // ? 354 return header.channels == 4 ? 24 : -1; // ?
355 case 4: 355 case 4:
356 return 24; // alpha 356 return 24; // alpha
357 default: 357 default:
358 return -1; 358 return -1;
359 } 359 }
360} 360}
361 361
362 362
363 363
364//! creates a loader which is able to load tgas 364//! creates a loader which is able to load tgas
365IImageLoader* createImageLoaderPSD() 365IImageLoader* createImageLoaderPSD()
366{ 366{
367 return new CImageLoaderPSD(); 367 return new CImageLoaderPSD();
368} 368}
369 369
370 370
371} // end namespace video 371} // end namespace video
372} // end namespace irr 372} // end namespace irr
373 373
374#endif 374#endif
375 375