diff options
author | David Walter Seikel | 2014-01-13 19:47:58 +1000 |
---|---|---|
committer | David Walter Seikel | 2014-01-13 19:47:58 +1000 |
commit | f9158592e1478b2013afc7041d9ed041cf2d2f4a (patch) | |
tree | b16e389d7988700e21b4c9741044cefa536dcbae /libraries/irrlicht-1.8.1/source/Irrlicht/CImageLoaderBMP.cpp | |
parent | Libraries readme updated with change markers and more of the Irrlicht changes. (diff) | |
download | SledjHamr-f9158592e1478b2013afc7041d9ed041cf2d2f4a.zip SledjHamr-f9158592e1478b2013afc7041d9ed041cf2d2f4a.tar.gz SledjHamr-f9158592e1478b2013afc7041d9ed041cf2d2f4a.tar.bz2 SledjHamr-f9158592e1478b2013afc7041d9ed041cf2d2f4a.tar.xz |
Update Irrlicht to 1.8.1. Include actual change markers this time. lol
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8.1/source/Irrlicht/CImageLoaderBMP.cpp | 372 |
1 files changed, 372 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8.1/source/Irrlicht/CImageLoaderBMP.cpp b/libraries/irrlicht-1.8.1/source/Irrlicht/CImageLoaderBMP.cpp new file mode 100644 index 0000000..2ccb64c --- /dev/null +++ b/libraries/irrlicht-1.8.1/source/Irrlicht/CImageLoaderBMP.cpp | |||
@@ -0,0 +1,372 @@ | |||
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 "CImageLoaderBMP.h" | ||
6 | |||
7 | #ifdef _IRR_COMPILE_WITH_BMP_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 | namespace irr | ||
17 | { | ||
18 | namespace video | ||
19 | { | ||
20 | |||
21 | |||
22 | //! constructor | ||
23 | CImageLoaderBMP::CImageLoaderBMP() | ||
24 | { | ||
25 | #ifdef _DEBUG | ||
26 | setDebugName("CImageLoaderBMP"); | ||
27 | #endif | ||
28 | } | ||
29 | |||
30 | |||
31 | //! returns true if the file maybe is able to be loaded by this class | ||
32 | //! based on the file extension (e.g. ".tga") | ||
33 | bool CImageLoaderBMP::isALoadableFileExtension(const io::path& filename) const | ||
34 | { | ||
35 | return core::hasFileExtension ( filename, "bmp" ); | ||
36 | } | ||
37 | |||
38 | |||
39 | //! returns true if the file maybe is able to be loaded by this class | ||
40 | bool CImageLoaderBMP::isALoadableFileFormat(io::IReadFile* file) const | ||
41 | { | ||
42 | u16 headerID; | ||
43 | file->read(&headerID, sizeof(u16)); | ||
44 | #ifdef __BIG_ENDIAN__ | ||
45 | headerID = os::Byteswap::byteswap(headerID); | ||
46 | #endif | ||
47 | return headerID == 0x4d42; | ||
48 | } | ||
49 | |||
50 | |||
51 | void CImageLoaderBMP::decompress8BitRLE(u8*& bmpData, s32 size, s32 width, s32 height, s32 pitch) const | ||
52 | { | ||
53 | u8* p = bmpData; | ||
54 | u8* newBmp = new u8[(width+pitch)*height]; | ||
55 | u8* d = newBmp; | ||
56 | u8* destEnd = newBmp + (width+pitch)*height; | ||
57 | s32 line = 0; | ||
58 | |||
59 | while (bmpData - p < size && d < destEnd) | ||
60 | { | ||
61 | if (*p == 0) | ||
62 | { | ||
63 | ++p; | ||
64 | |||
65 | switch(*p) | ||
66 | { | ||
67 | case 0: // end of line | ||
68 | ++p; | ||
69 | ++line; | ||
70 | d = newBmp + (line*(width+pitch)); | ||
71 | break; | ||
72 | case 1: // end of bmp | ||
73 | delete [] bmpData; | ||
74 | bmpData = newBmp; | ||
75 | return; | ||
76 | case 2: | ||
77 | ++p; d +=(u8)*p; // delta | ||
78 | ++p; d += ((u8)*p)*(width+pitch); | ||
79 | ++p; | ||
80 | break; | ||
81 | default: | ||
82 | { | ||
83 | // absolute mode | ||
84 | s32 count = (u8)*p; ++p; | ||
85 | s32 readAdditional = ((2-(count%2))%2); | ||
86 | s32 i; | ||
87 | |||
88 | for (i=0; i<count; ++i) | ||
89 | { | ||
90 | *d = *p; | ||
91 | ++p; | ||
92 | ++d; | ||
93 | } | ||
94 | |||
95 | for (i=0; i<readAdditional; ++i) | ||
96 | ++p; | ||
97 | } | ||
98 | } | ||
99 | } | ||
100 | else | ||
101 | { | ||
102 | s32 count = (u8)*p; ++p; | ||
103 | u8 color = *p; ++p; | ||
104 | for (s32 i=0; i<count; ++i) | ||
105 | { | ||
106 | *d = color; | ||
107 | ++d; | ||
108 | } | ||
109 | } | ||
110 | } | ||
111 | |||
112 | delete [] bmpData; | ||
113 | bmpData = newBmp; | ||
114 | } | ||
115 | |||
116 | |||
117 | void CImageLoaderBMP::decompress4BitRLE(u8*& bmpData, s32 size, s32 width, s32 height, s32 pitch) const | ||
118 | { | ||
119 | s32 lineWidth = (width+1)/2+pitch; | ||
120 | u8* p = bmpData; | ||
121 | u8* newBmp = new u8[lineWidth*height]; | ||
122 | u8* d = newBmp; | ||
123 | u8* destEnd = newBmp + lineWidth*height; | ||
124 | s32 line = 0; | ||
125 | s32 shift = 4; | ||
126 | |||
127 | while (bmpData - p < size && d < destEnd) | ||
128 | { | ||
129 | if (*p == 0) | ||
130 | { | ||
131 | ++p; | ||
132 | |||
133 | switch(*p) | ||
134 | { | ||
135 | case 0: // end of line | ||
136 | ++p; | ||
137 | ++line; | ||
138 | d = newBmp + (line*lineWidth); | ||
139 | shift = 4; | ||
140 | break; | ||
141 | case 1: // end of bmp | ||
142 | delete [] bmpData; | ||
143 | bmpData = newBmp; | ||
144 | return; | ||
145 | case 2: | ||
146 | { | ||
147 | ++p; | ||
148 | s32 x = (u8)*p; ++p; | ||
149 | s32 y = (u8)*p; ++p; | ||
150 | d += x/2 + y*lineWidth; | ||
151 | shift = x%2==0 ? 4 : 0; | ||
152 | } | ||
153 | break; | ||
154 | default: | ||
155 | { | ||
156 | // absolute mode | ||
157 | s32 count = (u8)*p; ++p; | ||
158 | s32 readAdditional = ((2-((count)%2))%2); | ||
159 | s32 readShift = 4; | ||
160 | s32 i; | ||
161 | |||
162 | for (i=0; i<count; ++i) | ||
163 | { | ||
164 | s32 color = (((u8)*p) >> readShift) & 0x0f; | ||
165 | readShift -= 4; | ||
166 | if (readShift < 0) | ||
167 | { | ||
168 | ++*p; | ||
169 | readShift = 4; | ||
170 | } | ||
171 | |||
172 | u8 mask = 0x0f << shift; | ||
173 | *d = (*d & (~mask)) | ((color << shift) & mask); | ||
174 | |||
175 | shift -= 4; | ||
176 | if (shift < 0) | ||
177 | { | ||
178 | shift = 4; | ||
179 | ++d; | ||
180 | } | ||
181 | |||
182 | } | ||
183 | |||
184 | for (i=0; i<readAdditional; ++i) | ||
185 | ++p; | ||
186 | } | ||
187 | } | ||
188 | } | ||
189 | else | ||
190 | { | ||
191 | s32 count = (u8)*p; ++p; | ||
192 | s32 color1 = (u8)*p; color1 = color1 & 0x0f; | ||
193 | s32 color2 = (u8)*p; color2 = (color2 >> 4) & 0x0f; | ||
194 | ++p; | ||
195 | |||
196 | for (s32 i=0; i<count; ++i) | ||
197 | { | ||
198 | u8 mask = 0x0f << shift; | ||
199 | u8 toSet = (shift==0 ? color1 : color2) << shift; | ||
200 | *d = (*d & (~mask)) | (toSet & mask); | ||
201 | |||
202 | shift -= 4; | ||
203 | if (shift < 0) | ||
204 | { | ||
205 | shift = 4; | ||
206 | ++d; | ||
207 | } | ||
208 | } | ||
209 | } | ||
210 | } | ||
211 | |||
212 | delete [] bmpData; | ||
213 | bmpData = newBmp; | ||
214 | } | ||
215 | |||
216 | |||
217 | |||
218 | //! creates a surface from the file | ||
219 | IImage* CImageLoaderBMP::loadImage(io::IReadFile* file) const | ||
220 | { | ||
221 | SBMPHeader header; | ||
222 | |||
223 | file->read(&header, sizeof(header)); | ||
224 | |||
225 | #ifdef __BIG_ENDIAN__ | ||
226 | header.Id = os::Byteswap::byteswap(header.Id); | ||
227 | header.FileSize = os::Byteswap::byteswap(header.FileSize); | ||
228 | header.BitmapDataOffset = os::Byteswap::byteswap(header.BitmapDataOffset); | ||
229 | header.BitmapHeaderSize = os::Byteswap::byteswap(header.BitmapHeaderSize); | ||
230 | header.Width = os::Byteswap::byteswap(header.Width); | ||
231 | header.Height = os::Byteswap::byteswap(header.Height); | ||
232 | header.Planes = os::Byteswap::byteswap(header.Planes); | ||
233 | header.BPP = os::Byteswap::byteswap(header.BPP); | ||
234 | header.Compression = os::Byteswap::byteswap(header.Compression); | ||
235 | header.BitmapDataSize = os::Byteswap::byteswap(header.BitmapDataSize); | ||
236 | header.PixelPerMeterX = os::Byteswap::byteswap(header.PixelPerMeterX); | ||
237 | header.PixelPerMeterY = os::Byteswap::byteswap(header.PixelPerMeterY); | ||
238 | header.Colors = os::Byteswap::byteswap(header.Colors); | ||
239 | header.ImportantColors = os::Byteswap::byteswap(header.ImportantColors); | ||
240 | #endif | ||
241 | |||
242 | s32 pitch = 0; | ||
243 | |||
244 | //! return if the header is false | ||
245 | |||
246 | if (header.Id != 0x4d42) | ||
247 | return 0; | ||
248 | |||
249 | if (header.Compression > 2) // we'll only handle RLE-Compression | ||
250 | { | ||
251 | os::Printer::log("Compression mode not supported.", ELL_ERROR); | ||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | // adjust bitmap data size to dword boundary | ||
256 | header.BitmapDataSize += (4-(header.BitmapDataSize%4))%4; | ||
257 | |||
258 | // read palette | ||
259 | |||
260 | long pos = file->getPos(); | ||
261 | s32 paletteSize = (header.BitmapDataOffset - pos) / 4; | ||
262 | |||
263 | s32* paletteData = 0; | ||
264 | if (paletteSize) | ||
265 | { | ||
266 | paletteData = new s32[paletteSize]; | ||
267 | file->read(paletteData, paletteSize * sizeof(s32)); | ||
268 | #ifdef __BIG_ENDIAN__ | ||
269 | for (s32 i=0; i<paletteSize; ++i) | ||
270 | paletteData[i] = os::Byteswap::byteswap(paletteData[i]); | ||
271 | #endif | ||
272 | } | ||
273 | |||
274 | // read image data | ||
275 | |||
276 | if (!header.BitmapDataSize) | ||
277 | { | ||
278 | // okay, lets guess the size | ||
279 | // some tools simply don't set it | ||
280 | header.BitmapDataSize = static_cast<u32>(file->getSize()) - header.BitmapDataOffset; | ||
281 | } | ||
282 | |||
283 | file->seek(header.BitmapDataOffset); | ||
284 | |||
285 | f32 t = (header.Width) * (header.BPP / 8.0f); | ||
286 | s32 widthInBytes = (s32)t; | ||
287 | t -= widthInBytes; | ||
288 | if (t!=0.0f) | ||
289 | ++widthInBytes; | ||
290 | |||
291 | s32 lineData = widthInBytes + ((4-(widthInBytes%4)))%4; | ||
292 | pitch = lineData - widthInBytes; | ||
293 | |||
294 | u8* bmpData = new u8[header.BitmapDataSize]; | ||
295 | file->read(bmpData, header.BitmapDataSize); | ||
296 | |||
297 | // decompress data if needed | ||
298 | switch(header.Compression) | ||
299 | { | ||
300 | case 1: // 8 bit rle | ||
301 | decompress8BitRLE(bmpData, header.BitmapDataSize, header.Width, header.Height, pitch); | ||
302 | break; | ||
303 | case 2: // 4 bit rle | ||
304 | decompress4BitRLE(bmpData, header.BitmapDataSize, header.Width, header.Height, pitch); | ||
305 | break; | ||
306 | } | ||
307 | |||
308 | // create surface | ||
309 | |||
310 | // no default constructor from packed area! ARM problem! | ||
311 | core::dimension2d<u32> dim; | ||
312 | dim.Width = header.Width; | ||
313 | dim.Height = header.Height; | ||
314 | |||
315 | IImage* image = 0; | ||
316 | switch(header.BPP) | ||
317 | { | ||
318 | case 1: | ||
319 | image = new CImage(ECF_A1R5G5B5, dim); | ||
320 | if (image) | ||
321 | CColorConverter::convert1BitTo16Bit(bmpData, (s16*)image->lock(), header.Width, header.Height, pitch, true); | ||
322 | break; | ||
323 | case 4: | ||
324 | image = new CImage(ECF_A1R5G5B5, dim); | ||
325 | if (image) | ||
326 | CColorConverter::convert4BitTo16Bit(bmpData, (s16*)image->lock(), header.Width, header.Height, paletteData, pitch, true); | ||
327 | break; | ||
328 | case 8: | ||
329 | image = new CImage(ECF_A1R5G5B5, dim); | ||
330 | if (image) | ||
331 | CColorConverter::convert8BitTo16Bit(bmpData, (s16*)image->lock(), header.Width, header.Height, paletteData, pitch, true); | ||
332 | break; | ||
333 | case 16: | ||
334 | image = new CImage(ECF_A1R5G5B5, dim); | ||
335 | if (image) | ||
336 | CColorConverter::convert16BitTo16Bit((s16*)bmpData, (s16*)image->lock(), header.Width, header.Height, pitch, true); | ||
337 | break; | ||
338 | case 24: | ||
339 | image = new CImage(ECF_R8G8B8, dim); | ||
340 | if (image) | ||
341 | CColorConverter::convert24BitTo24Bit(bmpData, (u8*)image->lock(), header.Width, header.Height, pitch, true, true); | ||
342 | break; | ||
343 | case 32: // thx to Reinhard Ostermeier | ||
344 | image = new CImage(ECF_A8R8G8B8, dim); | ||
345 | if (image) | ||
346 | CColorConverter::convert32BitTo32Bit((s32*)bmpData, (s32*)image->lock(), header.Width, header.Height, pitch, true); | ||
347 | break; | ||
348 | }; | ||
349 | if (image) | ||
350 | image->unlock(); | ||
351 | |||
352 | // clean up | ||
353 | |||
354 | delete [] paletteData; | ||
355 | delete [] bmpData; | ||
356 | |||
357 | return image; | ||
358 | } | ||
359 | |||
360 | |||
361 | //! creates a loader which is able to load windows bitmaps | ||
362 | IImageLoader* createImageLoaderBMP() | ||
363 | { | ||
364 | return new CImageLoaderBMP; | ||
365 | } | ||
366 | |||
367 | |||
368 | } // end namespace video | ||
369 | } // end namespace irr | ||
370 | |||
371 | #endif | ||
372 | |||