aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/irrlicht-1.8.1/source/Irrlicht/CImageLoaderPCX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/irrlicht-1.8.1/source/Irrlicht/CImageLoaderPCX.cpp')
-rw-r--r--src/others/irrlicht-1.8.1/source/Irrlicht/CImageLoaderPCX.cpp231
1 files changed, 231 insertions, 0 deletions
diff --git a/src/others/irrlicht-1.8.1/source/Irrlicht/CImageLoaderPCX.cpp b/src/others/irrlicht-1.8.1/source/Irrlicht/CImageLoaderPCX.cpp
new file mode 100644
index 0000000..50ddf6e
--- /dev/null
+++ b/src/others/irrlicht-1.8.1/source/Irrlicht/CImageLoaderPCX.cpp
@@ -0,0 +1,231 @@
1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// This file is part of the "Irrlicht Engine".
3// For conditions of distribution and use, see copyright notice in irrlicht.h
4
5#include "CImageLoaderPCX.h"
6
7#ifdef _IRR_COMPILE_WITH_PCX_LOADER_
8
9#include "IReadFile.h"
10#include "SColor.h"
11#include "CColorConverter.h"
12#include "CImage.h"
13#include "os.h"
14#include "irrString.h"
15
16
17namespace irr
18{
19namespace video
20{
21
22
23//! constructor
24CImageLoaderPCX::CImageLoaderPCX()
25{
26 #ifdef _DEBUG
27 setDebugName("CImageLoaderPCX");
28 #endif
29}
30
31
32//! returns true if the file maybe is able to be loaded by this class
33//! based on the file extension (e.g. ".tga")
34bool CImageLoaderPCX::isALoadableFileExtension(const io::path& filename) const
35{
36 return core::hasFileExtension ( filename, "pcx" );
37}
38
39
40
41//! returns true if the file maybe is able to be loaded by this class
42bool CImageLoaderPCX::isALoadableFileFormat(io::IReadFile* file) const
43{
44 u8 headerID;
45 file->read(&headerID, sizeof(headerID));
46 return headerID == 0x0a;
47}
48
49
50//! creates a image from the file
51IImage* CImageLoaderPCX::loadImage(io::IReadFile* file) const
52{
53 SPCXHeader header;
54 s32* paletteData = 0;
55
56 file->read(&header, sizeof(header));
57 #ifdef __BIG_ENDIAN__
58 header.XMin = os::Byteswap::byteswap(header.XMin);
59 header.YMin = os::Byteswap::byteswap(header.YMin);
60 header.XMax = os::Byteswap::byteswap(header.XMax);
61 header.YMax = os::Byteswap::byteswap(header.YMax);
62 header.HorizDPI = os::Byteswap::byteswap(header.HorizDPI);
63 header.VertDPI = os::Byteswap::byteswap(header.VertDPI);
64 header.BytesPerLine = os::Byteswap::byteswap(header.BytesPerLine);
65 header.PaletteType = os::Byteswap::byteswap(header.PaletteType);
66 header.HScrSize = os::Byteswap::byteswap(header.HScrSize);
67 header.VScrSize = os::Byteswap::byteswap(header.VScrSize);
68 #endif
69
70 //! return if the header is wrong
71 if (header.Manufacturer != 0x0a && header.Encoding != 0x01)
72 return 0;
73
74 // return if this isn't a supported type
75 if ((header.BitsPerPixel != 8) && (header.BitsPerPixel != 4) && (header.BitsPerPixel != 1))
76 {
77 os::Printer::log("Unsupported bits per pixel in PCX file.",
78 file->getFileName(), irr::ELL_WARNING);
79 return 0;
80 }
81
82 // read palette
83 if( (header.BitsPerPixel == 8) && (header.Planes == 1) )
84 {
85 // the palette indicator (usually a 0x0c is found infront of the actual palette data)
86 // is ignored because some exporters seem to forget to write it. This would result in
87 // no image loaded before, now only wrong colors will be set.
88 const long pos = file->getPos();
89 file->seek( file->getSize()-256*3, false );
90
91 u8 *tempPalette = new u8[768];
92 paletteData = new s32[256];
93 file->read( tempPalette, 768 );
94
95 for( s32 i=0; i<256; i++ )
96 {
97 paletteData[i] = (0xff000000 |
98 (tempPalette[i*3+0] << 16) |
99 (tempPalette[i*3+1] << 8) |
100 (tempPalette[i*3+2]));
101 }
102
103 delete [] tempPalette;
104
105 file->seek(pos);
106 }
107 else if( header.BitsPerPixel == 4 )
108 {
109 paletteData = new s32[16];
110 for( s32 i=0; i<16; i++ )
111 {
112 paletteData[i] = (0xff000000 |
113 (header.Palette[i*3+0] << 16) |
114 (header.Palette[i*3+1] << 8) |
115 (header.Palette[i*3+2]));
116 }
117 }
118
119 // read image data
120 const s32 width = header.XMax - header.XMin + 1;
121 const s32 height = header.YMax - header.YMin + 1;
122 const s32 imagebytes = header.BytesPerLine * header.Planes * header.BitsPerPixel * height / 8;
123 u8* PCXData = new u8[imagebytes];
124
125 u8 cnt, value;
126 s32 lineoffset=0, linestart=0, nextmode=1;
127 for(s32 offset = 0; offset < imagebytes; offset += cnt)
128 {
129 file->read(&cnt, 1);
130 if( !((cnt & 0xc0) == 0xc0) )
131 {
132 value = cnt;
133 cnt = 1;
134 }
135 else
136 {
137 cnt &= 0x3f;
138 file->read(&value, 1);
139 }
140 if (header.Planes==1)
141 memset(PCXData+offset, value, cnt);
142 else
143 {
144 for (u8 i=0; i<cnt; ++i)
145 {
146 PCXData[linestart+lineoffset]=value;
147 lineoffset += 3;
148 if (lineoffset>=3*header.BytesPerLine)
149 {
150 lineoffset=nextmode;
151 if (++nextmode==3)
152 nextmode=0;
153 if (lineoffset==0)
154 linestart += 3*header.BytesPerLine;
155 }
156 }
157 }
158 }
159
160 // create image
161 video::IImage* image = 0;
162 s32 pad = (header.BytesPerLine - width * header.BitsPerPixel / 8) * header.Planes;
163
164 if (pad < 0)
165 pad = -pad;
166
167 if (header.BitsPerPixel==8)
168 {
169 switch(header.Planes) // TODO: Other formats
170 {
171 case 1:
172 image = new CImage(ECF_A1R5G5B5, core::dimension2d<u32>(width, height));
173 if (image)
174 CColorConverter::convert8BitTo16Bit(PCXData, (s16*)image->lock(), width, height, paletteData, pad);
175 break;
176 case 3:
177 image = new CImage(ECF_R8G8B8, core::dimension2d<u32>(width, height));
178 if (image)
179 CColorConverter::convert24BitTo24Bit(PCXData, (u8*)image->lock(), width, height, pad);
180 break;
181 }
182 }
183 else if (header.BitsPerPixel==4)
184 {
185 if (header.Planes==1)
186 {
187 image = new CImage(ECF_A1R5G5B5, core::dimension2d<u32>(width, height));
188 if (image)
189 CColorConverter::convert4BitTo16Bit(PCXData, (s16*)image->lock(), width, height, paletteData, pad);
190 }
191 }
192 else if (header.BitsPerPixel==1)
193 {
194 if (header.Planes==4)
195 {
196 image = new CImage(ECF_A1R5G5B5, core::dimension2d<u32>(width, height));
197 if (image)
198 CColorConverter::convert4BitTo16Bit(PCXData, (s16*)image->lock(), width, height, paletteData, pad);
199 }
200 else if (header.Planes==1)
201 {
202 image = new CImage(ECF_A1R5G5B5, core::dimension2d<u32>(width, height));
203 if (image)
204 CColorConverter::convert1BitTo16Bit(PCXData, (s16*)image->lock(), width, height, pad);
205 }
206 }
207 if (image)
208 image->unlock();
209
210 // clean up
211
212 delete [] paletteData;
213 delete [] PCXData;
214
215 return image;
216}
217
218
219//! creates a loader which is able to load pcx images
220IImageLoader* createImageLoaderPCX()
221{
222 return new CImageLoaderPCX();
223}
224
225
226
227} // end namespace video
228} // end namespace irr
229
230#endif
231