bitmap.cpp.patch.cpp

Jeru, 02/08/2011 05:45 pm

Download (200.2 kB)

 
1
diff -r 4ea92975a277 code/nel/src/misc/bitmap.cpp
2
--- a/code/nel/src/misc/bitmap.cpp        Tue Feb 01 18:56:55 2011 +0100
3
+++ b/code/nel/src/misc/bitmap.cpp        Tue Feb 08 16:39:22 2011 +0100
4
@@ -1,4108 +1,4108 @@
5
-// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
6
-// Copyright (C) 2010  Winch Gate Property Limited
7
-//
8
-// This program is free software: you can redistribute it and/or modify
9
-// it under the terms of the GNU Affero General Public License as
10
-// published by the Free Software Foundation, either version 3 of the
11
-// License, or (at your option) any later version.
12
-//
13
-// This program is distributed in the hope that it will be useful,
14
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
15
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
-// GNU Affero General Public License for more details.
17
-//
18
-// You should have received a copy of the GNU Affero General Public License
19
-// along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
-
21
-#include "stdmisc.h"
22
-
23
-#include "nel/misc/bitmap.h"
24
-#include "nel/misc/stream.h"
25
-#include "nel/misc/file.h"
26
-
27
-// Define this to force all bitmap white (debug)
28
-// #define NEL_ALL_BITMAP_WHITE
29
-
30
-
31
-using namespace std;
32
-
33
-
34
-namespace NLMISC
35
-{
36
-
37
-struct EDDSBadHeader : public NLMISC::EStream
38
-{
39
-        EDDSBadHeader() : EStream( "Bad or unrecognized DDS file header" ) {}
40
-};
41
-
42
-struct ESeekFailed : public NLMISC::EStream
43
-{
44
-        ESeekFailed() : EStream( "Seek failed" ) {}
45
-};
46
-
47
-struct EAllocationFailure : public Exception
48
-{
49
-        EAllocationFailure() : Exception( "Can't allocate memory" ) {}
50
-};
51
-
52
-void blendFromui(NLMISC::CRGBA &c0, NLMISC::CRGBA &c1, uint coef);
53
-uint32 blend(uint32 &n0, uint32 &n1, uint32 coef0);
54
-
55
-const uint32 CBitmap::bitPerPixels[ModeCount]=
56
-{
57
-        32,                // RGBA
58
-        8,                // Luminance
59
-        8,                // Alpha
60
-        16,                // AlphaLuminance
61
-        4,                // DXTC1
62
-        4,                // DXTC1Alpha
63
-        8,                // DXTC3
64
-        8,                // DXTC5
65
-        16                // DsDt
66
-};
67
-
68
-const uint32 CBitmap::DXTC1HEADER = NL_MAKEFOURCC('D','X', 'T', '1');
69
-const uint32 CBitmap::DXTC3HEADER = NL_MAKEFOURCC('D','X', 'T', '3');
70
-const uint32 CBitmap::DXTC5HEADER = NL_MAKEFOURCC('D','X', 'T', '5');
71
-
72
-
73
-#ifdef NEL_ALL_BITMAP_WHITE
74
-// Make all the textures white
75
-void MakeWhite(CBitmap &bitmaps)
76
-{
77
-        for (uint i=0; i<bitmaps.getMipMapCount (); i++)
78
-        {
79
-                uint size = bitmaps.getPixels (i).size ();
80
-                bitmaps.getPixels (i).resize (0);
81
-                bitmaps.getPixels (i).resize (size);
82
-                bitmaps.getPixels (i).fill (0xff);
83
-        }
84
-}
85
-#endif // NEL_ALL_BITMAP_WHITE
86
-
87
-/*-------------------------------------------------------------------*\
88
-                                                                load
89
-\*-------------------------------------------------------------------*/
90
-uint8 CBitmap::load(NLMISC::IStream &f, uint mipMapSkip)
91
-{
92
-        /* ***********************************************
93
-         *        WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
94
-         *        It can be loaded/called through CAsyncFileManager for instance
95
-         * ***********************************************/
96
-
97
-        nlassert(f.isReading());
98
-
99
-        // testing if DDS
100
-        uint32 fileType = 0;;
101
-        f.serial(fileType);
102
-        if(fileType == DDS_HEADER)
103
-        {
104
-#ifdef NEL_ALL_BITMAP_WHITE
105
-                uint8 result = readDDS(f, mipMapSkip);
106
-                MakeWhite (*this);
107
-                return result;
108
-#else // NEL_ALL_BITMAP_WHITE
109
-                return readDDS(f, mipMapSkip);
110
-#endif // NEL_ALL_BITMAP_WHITE
111
-        }
112
-
113
-        if (fileType == PNG_HEADER)
114
-        {
115
-#ifdef NEL_ALL_BITMAP_WHITE
116
-                uint8 result = readPNG(f);
117
-                MakeWhite (*this);
118
-                return result;
119
-#else // NEL_ALL_BITMAP_WHITE
120
-                return readPNG(f);
121
-#endif // NEL_ALL_BITMAP_WHITE
122
-        }
123
-
124
-#ifdef USE_JPEG
125
-        if (fileType == JPG_HEADER)
126
-        {
127
-#ifdef NEL_ALL_BITMAP_WHITE
128
-                uint8 result = readJPG(f);
129
-                MakeWhite (*this);
130
-                return result;
131
-#else // NEL_ALL_BITMAP_WHITE
132
-                return readJPG(f);
133
-#endif // NEL_ALL_BITMAP_WHITE
134
-        }
135
-#endif // USE_JPEG
136
-
137
-        // assuming it's TGA
138
-        NLMISC::IStream::TSeekOrigin origin= f.begin;
139
-        if(!f.seek (0, origin))
140
-        {
141
-                throw ESeekFailed();
142
-        }
143
-
144
-        // Reading header,
145
-        // To make sure that the bitmap is TGA, we check imageType and imageDepth.
146
-        uint8        lengthID;
147
-        uint8        cMapType;
148
-        uint8        imageType;
149
-        uint16        tgaOrigin;
150
-        uint16        length;
151
-        uint8        depth;
152
-        uint16        xOrg;
153
-        uint16        yOrg;
154
-        uint16        width;
155
-        uint16        height;
156
-        uint8        imageDepth;
157
-        uint8        desc;
158
-
159
-        f.serial(lengthID);
160
-        f.serial(cMapType);
161
-        f.serial(imageType);
162
-        if(imageType!=2 && imageType!=3 && imageType!=10 && imageType!=11) return 0;
163
-        f.serial(tgaOrigin);
164
-        f.serial(length);
165
-        f.serial(depth);
166
-        f.serial(xOrg);
167
-        f.serial(yOrg);
168
-        f.serial(width);
169
-        f.serial(height);
170
-        f.serial(imageDepth);
171
-        if(imageDepth!=8 && imageDepth!=16 && imageDepth!=24 && imageDepth!=32) return 0;
172
-        f.serial(desc);
173
-
174
-        if(!f.seek (0, origin))
175
-        {
176
-                throw ESeekFailed();
177
-        }
178
-#ifdef NEL_ALL_BITMAP_WHITE
179
-        uint8 result = readTGA(f);
180
-        MakeWhite (*this);
181
-        return result;
182
-#else // NEL_ALL_BITMAP_WHITE
183
-        return readTGA(f);
184
-#endif // NEL_ALL_BITMAP_WHITE
185
-}
186
-
187
-
188
-/*-------------------------------------------------------------------*\
189
-                                                                makeDummy
190
-\*-------------------------------------------------------------------*/
191
-void        CBitmap::makeDummy()
192
-{
193
-        static        const uint8        bitmap[1024]= {
194
-                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
195
-                0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
196
-                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
197
-                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
198
-                0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,
199
-                0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,
200
-                0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,
201
-                0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,
202
-                0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,
203
-                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
204
-                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
205
-                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
206
-                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
207
-                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
208
-                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
209
-                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
210
-                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
211
-                0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
212
-                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
213
-                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
214
-                0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,
215
-                0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,
216
-                0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,
217
-                0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,
218
-                0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,
219
-                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
220
-                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
221
-                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
222
-                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
223
-                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
224
-                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
225
-                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
226
-        };
227
-
228
-        makeDummyFromBitField(bitmap);
229
-}
230
-
231
-
232
-/*-------------------------------------------------------------------*\
233
-                                                                makeDummy
234
-\*-------------------------------------------------------------------*/
235
-void        CBitmap::makeNonPowerOf2Dummy()
236
-{
237
-        static        const uint8        bitmap[1024]= {
238
-                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
239
-                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
240
-                0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,
241
-                0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,
242
-                0,0,0,0,1,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1,1,0,0,0,0,
243
-                0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,
244
-                0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,
245
-                0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,
246
-                0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,
247
-                0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,
248
-                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
249
-                0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,
250
-                0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,
251
-                0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,
252
-                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
253
-                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
254
-                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
255
-                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
256
-                0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,
257
-                0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,
258
-                0,0,0,0,1,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1,1,0,0,0,0,
259
-                0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,
260
-                0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,
261
-                0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,
262
-                0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,
263
-                0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,
264
-                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
265
-                0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,
266
-                0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,
267
-                0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,
268
-                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
269
-                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
270
-        };
271
-
272
-        makeDummyFromBitField(bitmap);
273
-}
274
-
275
-
276
-/*-------------------------------------------------------------------*\
277
-                                                makeDummyFromBitField
278
-\*-------------------------------------------------------------------*/
279
-void        CBitmap::makeDummyFromBitField(const uint8        bitmap[1024])
280
-{
281
-        PixelFormat = RGBA;
282
-        _MipMapCount = 1;
283
-        _Width= 32;
284
-        _Height= 32;
285
-        _Data[0].resize(_Width*_Height*sizeof(NLMISC::CRGBA));
286
-        for(sint m=1;m<MAX_MIPMAP;m++)
287
-                _Data[m].clear();
288
-        NLMISC::CRGBA        *pix= (NLMISC::CRGBA*)(_Data[0].getPtr());
289
-
290
-        for(sint i=0;i<(sint)(_Width*_Height);i++)
291
-        {
292
-                if(bitmap[i])
293
-                        pix[i].set(255,255,255,255);
294
-                else
295
-                        pix[i].set(0x80,0x80,0x80,0x40);
296
-        }
297
-}
298
-
299
-
300
-
301
-
302
-/*-------------------------------------------------------------------*\
303
-                                                                readDDS
304
-\*-------------------------------------------------------------------*/
305
-uint8 CBitmap::readDDS(NLMISC::IStream &f, uint mipMapSkip)
306
-{
307
-        /* ***********************************************
308
-         *        WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
309
-         *        It can be loaded/called through CAsyncFileManager for instance
310
-         * ***********************************************/
311
-
312
-        //------------------ Reading Header ------------------------
313
-
314
-        //-------------- reading entire header
315
-
316
-        uint32 size = 0;
317
-        f.serial(size); // size in Bytes of header(without "DDS")
318
-         uint32 * _DDSSurfaceDesc = new uint32[size];
319
-        _DDSSurfaceDesc[0]= size;
320
-
321
-#ifdef NL_LITTLE_ENDIAN
322
-        f.serialBuffer((uint8*)(_DDSSurfaceDesc+1), size-4);
323
-#else
324
-        for(uint i= 0; i<size/4 - 1; i++)
325
-        {
326
-                f.serial(_DDSSurfaceDesc[i+1]);
327
-        }
328
-#endif
329
-
330
-        // flags determines which members of the header structure contain valid data
331
-        uint32 flags = _DDSSurfaceDesc[1];
332
-
333
-        //verify if file have linearsize set
334
-        if(!(flags & DDSD_LINEARSIZE))
335
-    {
336
-                nlwarning("A DDS doesn't have the flag DDSD_LINEARSIZE");
337
-                //delete [] _DDSSurfaceDesc;
338
-                //throw EDDSBadHeader();
339
-        }
340
-
341
-        //-------------- extracting and testing useful info
342
-
343
-        _Height = _DDSSurfaceDesc[2];
344
-        _Width  = _DDSSurfaceDesc[3];
345
-        _MipMapCount= (uint8) _DDSSurfaceDesc[6];
346
-        // If no mipmap.
347
-        if(_MipMapCount==0)
348
-                _MipMapCount=1;
349
-        switch (_DDSSurfaceDesc[20])
350
-        {
351
-        case DXTC1HEADER:
352
-                PixelFormat=DXTC1;
353
-                break;
354
-        case DXTC3HEADER:
355
-                PixelFormat=DXTC3;
356
-                break;
357
-        case DXTC5HEADER:
358
-                PixelFormat=DXTC5;
359
-                break;
360
-        }
361
-
362
-        flags = _DDSSurfaceDesc[19]; //PixelFormat flags
363
-
364
-/*        ace: I changed this code because it's not a way to detect if DXTC1 has a alpha channel or not
365
-                There's no easy way to detect if the DXTC1 has an alpha channel or not, so, for now, we'll suppose
366
-                that all DXTC1 has alpha channel per default.
367
-
368
-                "There is no flag unfortunately, you need to read each block of DXT1 data, check if one of the colors
369
-                contains alpha, and check if that color is used in the data.
370
-                It's not that hard to write, but it IS a pain that it's the only way that I've found to check for alpha."
371
-                http://www.gamedev.net/community/forums/topic.asp?topic_id=177475
372
-
373
-                UPDATE: worst... on linux/opengl, it generates random alpha values
374
-                if we use alpha dxtc1 by default. So I only to that for windows
375
-                and leave the old test on linux
376
-
377
-                kervala: some used textures don't have an alpha channel and they are
378
-                (very) bad rendered with this fix        so we have to deactivate it the for moment
379
-*/
380
-
381
-//#ifdef NL_OS_WINDOWS
382
-//        if(PixelFormat==DXTC1) //AlphaBitDepth
383
-//        {
384
-//                PixelFormat = DXTC1Alpha;
385
-//        }
386
-//#else
387
-        if(PixelFormat==DXTC1 && _DDSSurfaceDesc[21]>0) //AlphaBitDepth
388
-        {
389
-                PixelFormat = DXTC1Alpha;
390
-        }
391
-//#endif
392
-
393
-        if(PixelFormat!= DXTC1 && PixelFormat!= DXTC1Alpha && PixelFormat!= DXTC3 && PixelFormat!= DXTC5)
394
-        {
395
-                delete [] _DDSSurfaceDesc;
396
-                throw EDDSBadHeader();
397
-        }
398
-
399
-        // compute the min power of 2 between width and height
400
-        uint        minSizeLevel= min(_Width, _Height);
401
-        minSizeLevel= getPowerOf2(minSizeLevel);
402
-
403
-        //------------- manage mipMapSkip
404
-        if(_MipMapCount>1 && mipMapSkip>0 && minSizeLevel>2)
405
-        {
406
-                // Keep at least the level where width and height are at least 4.
407
-                mipMapSkip= min(mipMapSkip, minSizeLevel-2);
408
-                // skip any mipmap
409
-                uint        seekSize= 0;
410
-                while(mipMapSkip>0 && _MipMapCount>1)
411
-                {
412
-                        // raise to next multiple of 4
413
-                        uint32 wtmp= (_Width+3)&(~3);
414
-                        uint32 htmp= (_Height+3)&(~3);
415
-                        wtmp= max(wtmp, uint32(4));
416
-                        htmp= max(htmp, uint32(4));
417
-
418
-                        uint32 mipMapSz;
419
-                        if(PixelFormat==DXTC1 || PixelFormat==DXTC1Alpha)
420
-                                mipMapSz = wtmp*htmp/2;
421
-                        else
422
-                                mipMapSz = wtmp*htmp;
423
-
424
-                        // add to how many to skip
425
-                        seekSize+= mipMapSz;
426
-
427
-                        // Size of final bitmap is reduced.
428
-                        _Width>>=1;
429
-                        _Height>>=1;
430
-                        _MipMapCount--;
431
-                        mipMapSkip--;
432
-                }
433
-                // skip data in file
434
-                if(seekSize>0)
435
-                {
436
-                        if(!f.seek(seekSize, IStream::current))
437
-                        {
438
-                                delete [] _DDSSurfaceDesc;
439
-                                throw ESeekFailed();
440
-                        }
441
-                }
442
-
443
-        }
444
-
445
-        //------------- preload all the mipmaps (one serialBuffer() is faster)
446
-        uint32 w = _Width;
447
-        uint32 h = _Height;
448
-        uint32        totalSize= 0;
449
-
450
-        uint8        m;
451
-        for(m= 0; m<_MipMapCount; m++)
452
-        {
453
-                // raise to next multiple of 4
454
-                uint32 wtmp= (w+3)&(~3);
455
-                uint32 htmp= (h+3)&(~3);
456
-                wtmp= max(wtmp, uint32(4));
457
-                htmp= max(htmp, uint32(4));
458
-
459
-                uint32 mipMapSz;
460
-                if(PixelFormat==DXTC1 || PixelFormat==DXTC1Alpha)
461
-                        mipMapSz = wtmp*htmp/2;
462
-                else
463
-                        mipMapSz = wtmp*htmp;
464
-
465
-
466
-                _Data[m].resize(mipMapSz);
467
-                totalSize+= mipMapSz;
468
-
469
-                  w = (w+1)/2;
470
-                h = (h+1)/2;
471
-        }
472
-
473
-        // Read all the data in one block.
474
-        vector<uint8>        pixData;
475
-        pixData.resize(totalSize);
476
-        f.serialBuffer(&(*pixData.begin()), totalSize);
477
-
478
-
479
-        //------------- reading mipmap levels from pixData
480
-
481
-        uint32 pixIndex= 0;
482
-
483
-        for(m= 0; m<_MipMapCount; m++)
484
-        {
485
-                uint32        mipMapSz= _Data[m].size();
486
-                memcpy(_Data[m].getPtr(), &(pixData[pixIndex]), mipMapSz);
487
-                pixIndex+= mipMapSz;
488
-        }
489
-
490
-        //------------- End
491
-
492
-        delete [] _DDSSurfaceDesc;
493
-
494
-        switch(PixelFormat)
495
-        {
496
-                case DXTC1  : return 24;
497
-                case DXTC1Alpha : return 32;
498
-                case DXTC3  : return 32;
499
-                case DXTC5  : return 32;
500
-                default  : break;
501
-        }
502
-
503
-        return 0;
504
-}
505
-
506
-
507
-
508
-
509
-/*-------------------------------------------------------------------*\
510
-                                                        convertToDXTC5
511
-\*-------------------------------------------------------------------*/
512
-bool CBitmap::convertToDXTC5()
513
-{
514
-        /* Yoyo: RGB encoding for DXTC1 and DXTC5/3 are actually different!!
515
-                DXTC3/5 don't rely on sign of color0>color1 to setup special encoding (ie use a special compression for Black)
516
-                Since this can arise if the src is DXTC1 , we can't simply compress it into DXTC5 without doing a
517
-                heavy compression...
518
-                (the inverse is false: DXTC5 to DXTC1 is possible, with maybe swap color0/color1 and bits).
519
-        */
520
-
521
-        return false;
522
-
523
-/*        uint32 i,j;
524
-
525
-        if(PixelFormat!=DXTC1) return false;
526
-
527
-        for(uint8 m= 0; m<_MipMapCount; m++)
528
-        {
529
-                CObjectVector<uint8> dataTmp;
530
-                dataTmp.resize(2*_Data[m].size());
531
-                uint        dstId= 0;
532
-
533
-                for(i=0; i<_Data[m].size(); i+=8)
534
-                {
535
-                        //64 bits alpha
536
-                        for(j=0; j<8; j++)
537
-                        {
538
-                                dataTmp[dstId++]= 255;
539
-                        }
540
-
541
-                        //64 bits RGB
542
-                        for(j=0; j<8; j++)
543
-                        {
544
-                                dataTmp[dstId++]= _Data[m][i+j];
545
-                        }
546
-                }
547
-                _Data[m] = dataTmp;
548
-        }
549
-        PixelFormat = DXTC5;
550
-        return true;
551
-*/
552
-}
553
-
554
-
555
-
556
-/*-------------------------------------------------------------------*\
557
-                                                        luminanceToRGBA()
558
-\*-------------------------------------------------------------------*/
559
-bool CBitmap::luminanceToRGBA()
560
-{
561
-        uint32 i;
562
-
563
-        if(_Width*_Height == 0)  return false;
564
-
565
-        for(uint8 m= 0; m<_MipMapCount; m++)
566
-        {
567
-                CObjectVector<uint8> dataTmp;
568
-                dataTmp.resize(_Data[m].size()*4);
569
-                uint        dstId= 0;
570
-
571
-                for(i=0; i<_Data[m].size(); i++)
572
-                {
573
-                        dataTmp[dstId++]= _Data[m][i];
574
-                        dataTmp[dstId++]= _Data[m][i];
575
-                        dataTmp[dstId++]= _Data[m][i];
576
-                        dataTmp[dstId++]= 255;
577
-                }
578
-                _Data[m] = dataTmp;
579
-        }
580
-        PixelFormat = RGBA;
581
-        return true;
582
-}
583
-
584
-/*-------------------------------------------------------------------*\
585
-                                                        alphaToRGBA()
586
-\*-------------------------------------------------------------------*/
587
-bool CBitmap::alphaToRGBA()
588
-{
589
-        uint32 i;
590
-
591
-        if(_Width*_Height == 0)  return false;
592
-
593
-        for(uint8 m= 0; m<_MipMapCount; m++)
594
-        {
595
-                CObjectVector<uint8> dataTmp;
596
-                dataTmp.resize(_Data[m].size()*4);
597
-                uint        dstId= 0;
598
-
599
-                for(i=0; i<_Data[m].size(); i++)
600
-                {
601
-                        dataTmp[dstId++]= 255;
602
-                        dataTmp[dstId++]= 255;
603
-                        dataTmp[dstId++]= 255;
604
-                        dataTmp[dstId++]= _Data[m][i];
605
-                }
606
-                _Data[m] = dataTmp;
607
-        }
608
-        PixelFormat = RGBA;
609
-        return true;
610
-}
611
-
612
-
613
-/*-------------------------------------------------------------------*\
614
-                                                        alphaLuminanceToRGBA()
615
-\*-------------------------------------------------------------------*/
616
-bool CBitmap::alphaLuminanceToRGBA()
617
-{
618
-        uint32 i;
619
-
620
-        if(_Width*_Height == 0)  return false;
621
-
622
-        for(uint8 m= 0; m<_MipMapCount; m++)
623
-        {
624
-                CObjectVector<uint8> dataTmp;
625
-                dataTmp.resize(_Data[m].size()*2);
626
-                uint        dstId= 0;
627
-
628
-                for(i=0; i<_Data[m].size(); i+=2)
629
-                {
630
-                        dataTmp[dstId++]= _Data[m][i];
631
-                        dataTmp[dstId++]= _Data[m][i];
632
-                        dataTmp[dstId++]= _Data[m][i];
633
-                        dataTmp[dstId++]= _Data[m][i+1];
634
-                }
635
-                _Data[m] = dataTmp;
636
-        }
637
-        PixelFormat = RGBA;
638
-        return true;
639
-}
640
-
641
-
642
-
643
-
644
-/*-------------------------------------------------------------------*\
645
-                                                        rgbaToAlphaLuminance
646
-\*-------------------------------------------------------------------*/
647
-bool CBitmap::rgbaToAlphaLuminance()
648
-{
649
-        uint32 i;
650
-
651
-        if(_Width*_Height == 0)  return false;
652
-
653
-        for(uint8 m= 0; m<_MipMapCount; m++)
654
-        {
655
-                CObjectVector<uint8> dataTmp;
656
-                dataTmp.resize(_Data[m].size()/2);
657
-                uint        dstId= 0;
658
-
659
-                for(i=0; i<_Data[m].size(); i+=4)
660
-                {
661
-                        dataTmp[dstId++]= (_Data[m][i]*77 + _Data[m][i+1]*150 + _Data[m][i+2]*28)/255;
662
-                        dataTmp[dstId++]= _Data[m][i+3];
663
-                }
664
-                NLMISC::contReset(_Data[m]);
665
-                _Data[m].resize(0);
666
-                _Data[m] = dataTmp;
667
-        }
668
-        PixelFormat = AlphaLuminance;
669
-        return true;
670
-}
671
-
672
-
673
-/*-------------------------------------------------------------------*\
674
-                                                        luminanceToAlphaLuminance
675
-\*-------------------------------------------------------------------*/
676
-bool CBitmap::luminanceToAlphaLuminance()
677
-{
678
-        uint32 i;
679
-
680
-        if(_Width*_Height == 0)  return false;
681
-
682
-        for(uint8 m= 0; m<_MipMapCount; m++)
683
-        {
684
-                CObjectVector<uint8> dataTmp;
685
-                dataTmp.resize(_Data[m].size()*2);
686
-                uint        dstId= 0;
687
-
688
-                for(i=0; i<_Data[m].size(); i++)
689
-                {
690
-                        dataTmp[dstId++]= _Data[m][i];
691
-                        dataTmp[dstId++]= 255;
692
-                }
693
-                _Data[m] = dataTmp;
694
-        }
695
-        PixelFormat = AlphaLuminance;
696
-        return true;
697
-}
698
-
699
-
700
-
701
-/*-------------------------------------------------------------------*\
702
-                                                        alphaToAlphaLuminance
703
-\*-------------------------------------------------------------------*/
704
-bool CBitmap::alphaToAlphaLuminance()
705
-{
706
-        uint32 i;
707
-
708
-        if(_Width*_Height == 0)  return false;
709
-
710
-        for(uint8 m= 0; m<_MipMapCount; m++)
711
-        {
712
-                CObjectVector<uint8> dataTmp;
713
-                dataTmp.resize(_Data[m].size()*2);
714
-                uint        dstId= 0;
715
-
716
-                for(i=0; i<_Data[m].size(); i++)
717
-                {
718
-                        dataTmp[dstId++]= 0;
719
-                        dataTmp[dstId++]= _Data[m][i];
720
-                }
721
-                _Data[m] = dataTmp;
722
-        }
723
-        PixelFormat = AlphaLuminance;
724
-        return true;
725
-}
726
-
727
-
728
-
729
-/*-------------------------------------------------------------------*\
730
-                                                        rgbaToLuminance
731
-\*-------------------------------------------------------------------*/
732
-bool CBitmap::rgbaToLuminance()
733
-{
734
-        uint32 i;
735
-
736
-        if(_Width*_Height == 0)  return false;
737
-
738
-        for(uint8 m= 0; m<_MipMapCount; m++)
739
-        {
740
-                CObjectVector<uint8> dataTmp;
741
-                dataTmp.resize(_Data[m].size()/4);
742
-                uint        dstId= 0;
743
-
744
-                for(i=0; i<_Data[m].size(); i+=4)
745
-                {
746
-                        dataTmp[dstId++]= (_Data[m][i]*77 + _Data[m][i+1]*150 + _Data[m][i+2]*28)/255;
747
-                }
748
-                NLMISC::contReset(_Data[m]);
749
-                _Data[m].resize(0);
750
-                _Data[m] = dataTmp;
751
-        }
752
-        PixelFormat = Luminance;
753
-        return true;
754
-}
755
-
756
-
757
-
758
-/*-------------------------------------------------------------------*\
759
-                                                        alphaToLuminance
760
-\*-------------------------------------------------------------------*/
761
-bool CBitmap::alphaToLuminance()
762
-{
763
-        if(_Width*_Height == 0)  return false;
764
-
765
-        PixelFormat = Luminance;
766
-        return true;
767
-}
768
-
769
-
770
-
771
-/*-------------------------------------------------------------------*\
772
-                                                        alphaLuminanceToLuminance
773
-\*-------------------------------------------------------------------*/
774
-bool CBitmap::alphaLuminanceToLuminance()
775
-{
776
-        uint32 i;
777
-
778
-        if(_Width*_Height == 0)  return false;
779
-
780
-        for(uint8 m= 0; m<_MipMapCount; m++)
781
-        {
782
-                CObjectVector<uint8> dataTmp;
783
-                dataTmp.resize(_Data[m].size()/2);
784
-                uint        dstId= 0;
785
-
786
-                for(i=0; i<_Data[m].size(); i+=2)
787
-                {
788
-                        dataTmp[dstId++]= 0;
789
-                        dataTmp[dstId++]= 0;
790
-                        dataTmp[dstId++]= 0;
791
-                        dataTmp[dstId++]= _Data[m][i];
792
-                }
793
-                NLMISC::contReset(_Data[m]);
794
-                _Data[m].resize(0);
795
-                _Data[m] = dataTmp;
796
-        }
797
-        PixelFormat = Luminance;
798
-        return true;
799
-}
800
-
801
-
802
-/*-------------------------------------------------------------------*\
803
-                                                        rgbaToAlpha
804
-\*-------------------------------------------------------------------*/
805
-bool CBitmap::rgbaToAlpha()
806
-{
807
-        uint32 i;
808
-
809
-        if(_Width*_Height == 0)  return false;
810
-
811
-        for(uint8 m= 0; m<_MipMapCount; m++)
812
-        {
813
-                CObjectVector<uint8> dataTmp;
814
-                dataTmp.resize(_Data[m].size()/4);
815
-                uint        dstId= 0;
816
-
817
-                for(i=0; i<_Data[m].size(); i+=4)
818
-                {
819
-                        dataTmp[dstId++]= _Data[m][i+3];
820
-                }
821
-                NLMISC::contReset(_Data[m]);
822
-                _Data[m].resize(0);
823
-                _Data[m] = dataTmp;
824
-        }
825
-        PixelFormat = Alpha;
826
-        return true;
827
-}
828
-
829
-
830
-/*-------------------------------------------------------------------*\
831
-                                                        luminanceToAlpha
832
-\*-------------------------------------------------------------------*/
833
-bool CBitmap::luminanceToAlpha()
834
-{
835
-        uint32 i;
836
-
837
-        if(_Width*_Height == 0)  return false;
838
-
839
-        for(uint8 m= 0; m<_MipMapCount; m++)
840
-        {
841
-                CObjectVector<uint8> dataTmp;
842
-                dataTmp.resize(_Data[m].size());
843
-                uint        dstId= 0;
844
-
845
-                for(i=0; i<_Data[m].size(); i++)
846
-                {
847
-                        dataTmp[dstId++]= _Data[m][i];
848
-                }
849
-                _Data[m] = dataTmp;
850
-        }
851
-        PixelFormat = Alpha;
852
-        return true;
853
-}
854
-
855
-
856
-/*-------------------------------------------------------------------*\
857
-                                                        alphaLuminanceToAlpha
858
-\*-------------------------------------------------------------------*/
859
-bool CBitmap::alphaLuminanceToAlpha()
860
-{
861
-        uint32 i;
862
-
863
-        if(_Width*_Height == 0)  return false;
864
-
865
-        for(uint8 m= 0; m<_MipMapCount; m++)
866
-        {
867
-                CObjectVector<uint8> dataTmp;
868
-                dataTmp.resize(_Data[m].size()/2);
869
-                uint        dstId= 0;
870
-
871
-                for(i=0; i<_Data[m].size(); i+=2)
872
-                {
873
-                        dataTmp[dstId++]= _Data[m][i+1];
874
-                }
875
-                NLMISC::contReset(_Data[m]);
876
-                _Data[m].resize(0);
877
-                _Data[m] = dataTmp;
878
-        }
879
-        PixelFormat = Alpha;
880
-        return true;
881
-}
882
-
883
-
884
-/*-------------------------------------------------------------------*\
885
-                                                        convertToLuminance
886
-\*-------------------------------------------------------------------*/
887
-bool CBitmap::convertToLuminance()
888
-{
889
-        switch(PixelFormat)
890
-        {
891
-                case RGBA :
892
-                        return rgbaToLuminance();
893
-                        break;
894
-
895
-                case Luminance :
896
-                        return true;
897
-                        break;
898
-
899
-                case Alpha :
900
-                        return alphaToLuminance();
901
-                        break;
902
-
903
-                case AlphaLuminance :
904
-                        return alphaLuminanceToLuminance();
905
-                        break;
906
-
907
-                default:
908
-                        break;
909
-        }
910
-        return false;
911
-}
912
-
913
-
914
-
915
-/*-------------------------------------------------------------------*\
916
-                                                        convertToAlpha
917
-\*-------------------------------------------------------------------*/
918
-bool CBitmap::convertToAlpha()
919
-{
920
-        switch(PixelFormat)
921
-        {
922
-                case RGBA :
923
-                        return rgbaToAlpha();
924
-                        break;
925
-
926
-                case Luminance :
927
-                        return luminanceToAlpha();
928
-                        break;
929
-
930
-                case Alpha :
931
-                        return true;
932
-                        break;
933
-
934
-                case AlphaLuminance :
935
-                        return alphaLuminanceToAlpha();
936
-                        break;
937
-
938
-                default:
939
-                        break;
940
-        }
941
-        return false;
942
-}
943
-
944
-
945
-
946
-/*-------------------------------------------------------------------*\
947
-                                                        convertToAlphaLuminance
948
-\*-------------------------------------------------------------------*/
949
-bool CBitmap::convertToAlphaLuminance()
950
-{
951
-        switch(PixelFormat)
952
-        {
953
-                case RGBA :
954
-                        return rgbaToAlphaLuminance();
955
-                        break;
956
-
957
-                case Luminance :
958
-                        return luminanceToAlphaLuminance();
959
-                        break;
960
-
961
-                case Alpha :
962
-                        return alphaToAlphaLuminance();
963
-                        break;
964
-
965
-                case AlphaLuminance :
966
-                        return true;
967
-                        break;
968
-
969
-                default:
970
-                        break;
971
-        }
972
-        return false;
973
-}
974
-
975
-
976
-/*-------------------------------------------------------------------*\
977
-                                                        convertToRGBA
978
-\*-------------------------------------------------------------------*/
979
-bool CBitmap::convertToRGBA()
980
-{
981
-        switch(PixelFormat)
982
-        {
983
-                case DXTC1 :
984
-                        return decompressDXT1(false);
985
-                        break;
986
-
987
-                case DXTC1Alpha :
988
-                        return decompressDXT1(true);
989
-                        break;
990
-
991
-                case DXTC3 :
992
-                        return decompressDXT3();
993
-                        break;
994
-
995
-                case DXTC5 :
996
-                        return decompressDXT5();
997
-                        break;
998
-
999
-                case Luminance :
1000
-                        return luminanceToRGBA();
1001
-                        break;
1002
-
1003
-                case Alpha :
1004
-                        return alphaToRGBA();
1005
-                        break;
1006
-
1007
-                case AlphaLuminance :
1008
-                        return alphaLuminanceToRGBA();
1009
-                        break;
1010
-                case RGBA:
1011
-                        return true;
1012
-                break;
1013
-                default:
1014
-                        break;
1015
-        }
1016
-        return false;
1017
-}
1018
-
1019
-
1020
-/*-------------------------------------------------------------------*\
1021
-                                                        convertToType
1022
-\*-------------------------------------------------------------------*/
1023
-bool CBitmap::convertToType(CBitmap::TType type)
1024
-{
1025
-        if(PixelFormat==type) return true;
1026
-
1027
-        switch(type)
1028
-        {
1029
-                case RGBA :
1030
-                        return convertToRGBA();
1031
-                        break;
1032
-
1033
-                case DXTC5 :
1034
-                        return convertToDXTC5();
1035
-                        break;
1036
-
1037
-                case Luminance :
1038
-                        return convertToLuminance();
1039
-                        break;
1040
-
1041
-                case Alpha :
1042
-                        return convertToAlpha();
1043
-                        break;
1044
-
1045
-                case AlphaLuminance :
1046
-                        return convertToAlphaLuminance();
1047
-                        break;
1048
-
1049
-                default:
1050
-                        break;
1051
-        }
1052
-
1053
-        return false;
1054
-}
1055
-
1056
-
1057
-
1058
-
1059
-/*-------------------------------------------------------------------*\
1060
-                                                        decompressDXT1
1061
-\*-------------------------------------------------------------------*/
1062
-bool CBitmap::decompressDXT1(bool alpha)
1063
-{
1064
-        uint32 i,j,k;
1065
-        NLMISC::CRGBA        c[4];
1066
-        CObjectVector<uint8> dataTmp[MAX_MIPMAP];
1067
-
1068
-        uint32 width= _Width;
1069
-        uint32 height= _Height;
1070
-
1071
-        for(uint8 m= 0; m<_MipMapCount; m++)
1072
-        {
1073
-                uint32 wtmp, htmp;
1074
-                if(width<4)
1075
-                        wtmp = 4;
1076
-                else
1077
-                        wtmp = width;
1078
-                if(height < 4)
1079
-                        htmp = 4;
1080
-                else
1081
-                        htmp = height;
1082
-                uint32 mipMapSz = wtmp*htmp*4;
1083
-                dataTmp[m].resize(mipMapSz);
1084
-                if(dataTmp[m].size()<mipMapSz)
1085
-                {
1086
-                        throw EAllocationFailure();
1087
-                }
1088
-                uint32 wBlockCount= wtmp/4;
1089
-
1090
-
1091
-
1092
-                for(i=0; i < _Data[m].size(); i+=8)
1093
-                {
1094
-                        uint16 color0;
1095
-                        uint16 color1;
1096
-                        uint32 bits;
1097
-                        memcpy(&color0,&_Data[m][i],2);
1098
-                        memcpy(&color1,&_Data[m][i+2],2);
1099
-                        memcpy(&bits,&_Data[m][i+4],4);
1100
-
1101
-                        uncompress(color0,c[0]);
1102
-                        uncompress(color1,c[1]);
1103
-
1104
-                        if (alpha)
1105
-                        {
1106
-                                c[0].A= 0;
1107
-                                c[1].A= 0;
1108
-                                c[2].A= 0;
1109
-                                c[3].A= 0;
1110
-                        }
1111
-                        else
1112
-                        {
1113
-                                c[0].A= 255;
1114
-                                c[1].A= 255;
1115
-                                c[2].A= 255;
1116
-                                c[3].A= 255;
1117
-                        }
1118
-
1119
-                        if(color0>color1)
1120
-                        {
1121
-                                c[2].blendFromui(c[0],c[1],85);
1122
-                                if(alpha) c[2].A= 255;
1123
-
1124
-                                c[3].blendFromui(c[0],c[1],171);
1125
-                                if(alpha) c[3].A= 255;
1126
-                        }
1127
-                        else
1128
-                        {
1129
-                                c[2].blendFromui(c[0],c[1],128);
1130
-                                if(alpha) c[2].A= 255;
1131
-
1132
-                                c[3].set(0,0,0,0);
1133
-                        }
1134
-
1135
-                        // computing the 16 RGBA of the block
1136
-
1137
-                        uint32 blockNum= i/8; //(64 bits)
1138
-                        // <previous blocks in above lines> * 4 (rows) * _Width (columns) + 4pix*4rgba*<same line previous blocks>
1139
-                        uint32 pixelsCount= 4*(blockNum/wBlockCount)*wtmp*4 + 4*4*(blockNum%wBlockCount);
1140
-                        for(j=0; j<4; j++)
1141
-                        {
1142
-                                for(k=0; k<4; k++)
1143
-                                {
1144
-                                        dataTmp[m][pixelsCount + j*wtmp*4 + 4*k]= c[bits&3].R;
1145
-                                        dataTmp[m][pixelsCount + j*wtmp*4 + 4*k+1]= c[bits&3].G;
1146
-                                        dataTmp[m][pixelsCount + j*wtmp*4 + 4*k+2]= c[bits&3].B;
1147
-                                        dataTmp[m][pixelsCount + j*wtmp*4 + 4*k+3]= c[bits&3].A;
1148
-                                        bits>>=2;
1149
-                                }
1150
-                        }
1151
-                }
1152
-
1153
-                // Copy result into the mipmap level.
1154
-                if(wtmp==width && htmp==height)
1155
-                {
1156
-                        // For mipmaps level >4 pixels.
1157
-                        _Data[m]= dataTmp[m];
1158
-                }
1159
-                else
1160
-                {
1161
-                        // For last mipmaps, level <4 pixels.
1162
-                        _Data[m].resize(width*height*4);
1163
-                        CRGBA        *src= (CRGBA*)&dataTmp[m][0];
1164
-                        CRGBA        *dst= (CRGBA*)&_Data[m][0];
1165
-                        uint        x,y;
1166
-                        for(y=0;y<height;y++)
1167
-                        {
1168
-                                for(x=0;x<width;x++)
1169
-                                        dst[y*width+x]= src[y*wtmp+x];
1170
-                        }
1171
-                }
1172
-
1173
-                // Next mipmap size.
1174
-                width = (width+1)/2;
1175
-                height = (height+1)/2;
1176
-        }
1177
-        PixelFormat = RGBA;
1178
-        return true;
1179
-}
1180
-
1181
-
1182
-
1183
-
1184
-/*-------------------------------------------------------------------*\
1185
-                                                        decompressDXT3
1186
-\*-------------------------------------------------------------------*/
1187
-bool CBitmap::decompressDXT3()
1188
-{
1189
-        uint32 i,j,k;
1190
-        NLMISC::CRGBA        c[4];
1191
-        CObjectVector<uint8> dataTmp[MAX_MIPMAP];
1192
-
1193
-        uint32 width= _Width;
1194
-        uint32 height= _Height;
1195
-
1196
-        for(uint8 m= 0; m<_MipMapCount; m++)
1197
-        {
1198
-                uint32 wtmp, htmp;
1199
-                if(width<4)
1200
-                        wtmp = 4;
1201
-                else
1202
-                        wtmp = width;
1203
-                if(height < 4)
1204
-                        htmp = 4;
1205
-                else
1206
-                        htmp = height;
1207
-                uint32 mipMapSz = wtmp*htmp*4;
1208
-                dataTmp[m].resize(mipMapSz);
1209
-                if(dataTmp[m].size()<mipMapSz)
1210
-                {
1211
-                        throw EAllocationFailure();
1212
-                }
1213
-                uint32 wBlockCount= wtmp/4;
1214
-
1215
-
1216
-                for(i=0; i < _Data[m].size(); i+=16)
1217
-                {
1218
-                        uint8 alpha[16];
1219
-                        uint64 alphatmp;
1220
-                        memcpy(&alphatmp,&_Data[m][i],8);
1221
-
1222
-                        for(j=0; j<16; j++)
1223
-                        {
1224
-                                uint8        a= (uint8)(alphatmp&15);
1225
-                                // expand to 0-255.
1226
-                                alpha[j]= a+(a<<4);
1227
-                                alphatmp>>=4;
1228
-                        }
1229
-
1230
-
1231
-                        uint16 color0;
1232
-                        uint16 color1;
1233
-                        uint32 bits;
1234
-                        memcpy(&color0,&_Data[m][i+8],2);
1235
-                        memcpy(&color1,&_Data[m][i+10],2);
1236
-                        memcpy(&bits,&_Data[m][i+12],4);
1237
-
1238
-                        uncompress(color0,c[0]);
1239
-                        uncompress(color1,c[1]);
1240
-
1241
-                        // ignore color0>color1 for DXT3 and DXT5.
1242
-                        c[2].blendFromui(c[0],c[1],85);
1243
-                        c[3].blendFromui(c[0],c[1],171);
1244
-
1245
-                        // computing the 16 RGBA of the block
1246
-
1247
-                        uint32 blockNum= i/16; //(128 bits)
1248
-                        // <previous blocks in above lines> * 4 (rows) * wtmp (columns) + 4pix*4rgba*<same line previous blocks>
1249
-                        uint32 pixelsCount= 4*(blockNum/wBlockCount)*wtmp*4 + 4*4*(blockNum%wBlockCount);
1250
-                        for(j=0; j<4; j++)
1251
-                        {
1252
-                                for(k=0; k<4; k++)
1253
-                                {
1254
-                                        dataTmp[m][pixelsCount + j*wtmp*4 + 4*k]= c[bits&3].R;
1255
-                                        dataTmp[m][pixelsCount + j*wtmp*4 + 4*k+1]= c[bits&3].G;
1256
-                                        dataTmp[m][pixelsCount + j*wtmp*4 + 4*k+2]= c[bits&3].B;
1257
-                                        dataTmp[m][pixelsCount + j*wtmp*4 + 4*k+3]= alpha[4*j+k];
1258
-                                        bits>>=2;
1259
-                                }
1260
-                        }
1261
-                }
1262
-
1263
-                // Copy result into the mipmap level.
1264
-                if(wtmp==width && htmp==height)
1265
-                {
1266
-                        // For mipmaps level >4 pixels.
1267
-                        _Data[m]= dataTmp[m];
1268
-                }
1269
-                else
1270
-                {
1271
-                        // For last mipmaps, level <4 pixels.
1272
-                        _Data[m].resize(width*height*4);
1273
-                        CRGBA        *src= (CRGBA*)&dataTmp[m][0];
1274
-                        CRGBA        *dst= (CRGBA*)&_Data[m][0];
1275
-                        uint        x,y;
1276
-                        for(y=0;y<height;y++)
1277
-                        {
1278
-                                for(x=0;x<width;x++)
1279
-                                        dst[y*width+x]= src[y*wtmp+x];
1280
-                        }
1281
-                }
1282
-
1283
-                // Next mipmap size.
1284
-                width = (width+1)/2;
1285
-                height = (height+1)/2;
1286
-        }
1287
-        PixelFormat = RGBA;
1288
-        return true;
1289
-}
1290
-
1291
-
1292
-
1293
-
1294
-/*-------------------------------------------------------------------*\
1295
-                                                        decompressDXT5
1296
-\*-------------------------------------------------------------------*/
1297
-bool CBitmap::decompressDXT5()
1298
-{
1299
-        uint32 i,j,k;
1300
-        NLMISC::CRGBA        c[4];
1301
-        CObjectVector<uint8> dataTmp[MAX_MIPMAP];
1302
-
1303
-        uint32 width= _Width;
1304
-        uint32 height= _Height;
1305
-
1306
-        for(uint8 m= 0; m<_MipMapCount; m++)
1307
-        {
1308
-                uint32 wtmp, htmp;
1309
-                if(width<4)
1310
-                        wtmp = 4;
1311
-                else
1312
-                        wtmp = width;
1313
-                if(height < 4)
1314
-                        htmp = 4;
1315
-                else
1316
-                        htmp = height;
1317
-                uint32 mipMapSz = wtmp*htmp*4;
1318
-                dataTmp[m].resize(mipMapSz);
1319
-                if(dataTmp[m].size()<mipMapSz)
1320
-                {
1321
-                        throw EAllocationFailure();
1322
-                }
1323
-                uint32 wBlockCount= wtmp/4;
1324
-
1325
-
1326
-
1327
-                for(i=0; i < _Data[m].size(); i+=16)
1328
-                {
1329
-                        uint64 bitsAlpha;
1330
-                        memcpy(&bitsAlpha,&_Data[m][i],8);
1331
-                        bitsAlpha>>= 16;
1332
-
1333
-                        uint32 alpha[8];
1334
-                        alpha[0]= _Data[m][i+0];
1335
-                        alpha[1]= _Data[m][i+1];
1336
-
1337
-                        if(alpha[0]>alpha[1])
1338
-                        {
1339
-                                alpha[2]= blend(alpha[0], alpha[1], 219);
1340
-                                alpha[3]= blend(alpha[0], alpha[1], 183);
1341
-                                alpha[4]= blend(alpha[0], alpha[1], 146);
1342
-                                alpha[5]= blend(alpha[0], alpha[1], 110);
1343
-                                alpha[6]= blend(alpha[0], alpha[1], 73);
1344
-                                alpha[7]= blend(alpha[0], alpha[1], 37);
1345
-                        }
1346
-                        else
1347
-                        {
1348
-                                alpha[2]= blend(alpha[0], alpha[1], 204);
1349
-                                alpha[3]= blend(alpha[0], alpha[1], 154);
1350
-                                alpha[4]= blend(alpha[0], alpha[1], 102);
1351
-                                alpha[5]= blend(alpha[0], alpha[1], 51);
1352
-                                alpha[6]= 0;
1353
-                                alpha[7]= 255;
1354
-                        }
1355
-
1356
-                        uint8 codeAlpha[16];
1357
-                        for(j=0; j<16; j++)
1358
-                        {
1359
-                                codeAlpha[j] = (uint8)(bitsAlpha & 7);
1360
-                                bitsAlpha>>=3;
1361
-                        }
1362
-
1363
-
1364
-                        uint16 color0;
1365
-                        uint16 color1;
1366
-                        uint32 bits;
1367
-                        memcpy(&color0,&_Data[m][i+8],2);
1368
-                        memcpy(&color1,&_Data[m][i+10],2);
1369
-                        memcpy(&bits,&_Data[m][i+12],4);
1370
-
1371
-                        uncompress(color0,c[0]);
1372
-                        uncompress(color1,c[1]);
1373
-
1374
-                        // ignore color0>color1 for DXT3 and DXT5.
1375
-                        c[2].blendFromui(c[0],c[1],85);
1376
-                        c[3].blendFromui(c[0],c[1],171);
1377
-
1378
-                        // computing the 16 RGBA of the block
1379
-
1380
-                        uint32 blockNum= i/16; //(128 bits)
1381
-
1382
-                        // <previous blocks in above lines> * 4 (rows) * wtmp (columns) + 4pix*<same line previous blocks>
1383
-                        uint32 pixelsCount= (blockNum/wBlockCount)*wtmp*4 + 4*(blockNum%wBlockCount);
1384
-                        // *sizeof(RGBA)
1385
-                        pixelsCount*=4;
1386
-                        for(j=0; j<4; j++)
1387
-                        {
1388
-                                for(k=0; k<4; k++)
1389
-                                {
1390
-                                        dataTmp[m][pixelsCount + (j*wtmp+k)*4 +0]= c[bits&3].R;
1391
-                                        dataTmp[m][pixelsCount + (j*wtmp+k)*4 +1]= c[bits&3].G;
1392
-                                        dataTmp[m][pixelsCount + (j*wtmp+k)*4 +2]= c[bits&3].B;
1393
-                                        dataTmp[m][pixelsCount + (j*wtmp+k)*4 +3]= (uint8) alpha[codeAlpha[4*j+k]];
1394
-                                        bits>>=2;
1395
-                                }
1396
-                        }
1397
-
1398
-                }
1399
-
1400
-                // Copy result into the mipmap level.
1401
-                if(wtmp==width && htmp==height)
1402
-                {
1403
-                        // For mipmaps level >4 pixels.
1404
-                        _Data[m]= dataTmp[m];
1405
-                }
1406
-                else
1407
-                {
1408
-                        // For last mipmaps, level <4 pixels.
1409
-                        _Data[m].resize(width*height*4);
1410
-                        CRGBA        *src= (CRGBA*)&dataTmp[m][0];
1411
-                        CRGBA        *dst= (CRGBA*)&_Data[m][0];
1412
-                        uint        x,y;
1413
-                        for(y=0;y<height;y++)
1414
-                        {
1415
-                                for(x=0;x<width;x++)
1416
-                                        dst[y*width+x]= src[y*wtmp+x];
1417
-                        }
1418
-                }
1419
-
1420
-                // Next mipmap size.
1421
-                width = (width+1)/2;
1422
-                height = (height+1)/2;
1423
-        }
1424
-        PixelFormat = RGBA;
1425
-        return true;
1426
-
1427
-}
1428
-
1429
-
1430
-
1431
-
1432
-/*-------------------------------------------------------------------*\
1433
-                                                        blend
1434
-\*-------------------------------------------------------------------*/
1435
-uint32 CBitmap::blend(uint32 &n0, uint32 &n1, uint32 coef0)
1436
-{
1437
-        int        a0 = coef0;
1438
-        int        a1 = 256-a0;
1439
-        return ((n0*a0 + n1*a1) >>8);
1440
-}
1441
-
1442
-
1443
-
1444
-/*-------------------------------------------------------------------*\
1445
-                                                        uncompress
1446
-\*-------------------------------------------------------------------*/
1447
-inline void CBitmap::uncompress(uint16 color, NLMISC::CRGBA &r)
1448
-{
1449
-        r.A= 0;
1450
-        r.R= ((color>>11)&31) << 3; r.R+= r.R>>5;
1451
-        r.G= ((color>>5)&63) << 2;  r.G+= r.G>>6;
1452
-        r.B= ((color)&31) << 3;     r.B+= r.B>>5;
1453
-}
1454
-
1455
-
1456
-
1457
-/*-------------------------------------------------------------------*\
1458
-                                                        getWidth
1459
-\*-------------------------------------------------------------------*/
1460
-uint32 CBitmap::getWidth(uint32 mipMap) const
1461
-{
1462
-        if(mipMap==0) return _Width;
1463
-
1464
-        uint32 w = _Width;
1465
-        uint32 h = _Height;
1466
-        uint32 m = 0;
1467
-
1468
-        do
1469
-        {
1470
-                m++;
1471
-                w = (w+1)/2;
1472
-                h = (h+1)/2;
1473
-                if(m==mipMap) return w;
1474
-        }
1475
-        while(w!=1 || h!=1);
1476
-
1477
-        return 0;
1478
-}
1479
-
1480
-
1481
-
1482
-/*-------------------------------------------------------------------*\
1483
-                                                        getHeight
1484
-\*-------------------------------------------------------------------*/
1485
-uint32 CBitmap::getHeight(uint32 mipMap) const
1486
-{
1487
-        if(mipMap==0) return _Height;
1488
-
1489
-        uint32 w = _Width;
1490
-        uint32 h = _Height;
1491
-        uint32 m = 0;
1492
-
1493
-        do
1494
-        {
1495
-                m++;
1496
-                w = (w+1)/2;
1497
-                h = (h+1)/2;
1498
-                if(m==mipMap) return h;
1499
-        }
1500
-        while(w!=1 || h!=1);
1501
-
1502
-        return 0;
1503
-}
1504
-
1505
-
1506
-/*-------------------------------------------------------------------*\
1507
-                                                        getSize
1508
-\*-------------------------------------------------------------------*/
1509
-uint32 CBitmap::getSize(uint32 numMipMap) const
1510
-{
1511
-        return getHeight(numMipMap)*getWidth(numMipMap);
1512
-}
1513
-
1514
-
1515
-
1516
-/*-------------------------------------------------------------------*\
1517
-                                                        buildMipMaps
1518
-\*-------------------------------------------------------------------*/
1519
-void CBitmap::buildMipMaps()
1520
-{
1521
-        uint32 i,j;
1522
-
1523
-        if(PixelFormat!=RGBA) return;
1524
-        if(_MipMapCount!=1) return;
1525
-        if(!NLMISC::isPowerOf2(_Width)) return;
1526
-        if(!NLMISC::isPowerOf2(_Height)) return;
1527
-
1528
-        uint32 w = _Width;
1529
-        uint32 h = _Height;
1530
-
1531
-        while(w>1 || h>1)
1532
-        {
1533
-                uint32 precw = w;
1534
-                uint32 prech = h;
1535
-                w = (w+1)/2;
1536
-                h = (h+1)/2;
1537
-                uint32        mulw= precw/w;
1538
-                uint32        mulh= prech/h;
1539
-
1540
-                _Data[_MipMapCount].resize(w*h*4);
1541
-
1542
-                NLMISC::CRGBA *pRgba = (NLMISC::CRGBA*)&_Data[_MipMapCount][0];
1543
-                NLMISC::CRGBA *pRgbaPrev = (NLMISC::CRGBA*)&_Data[_MipMapCount-1][0];
1544
-                for(i=0; i<h; i++)
1545
-                {
1546
-                        sint        i0= mulh*i;
1547
-                        sint        i1= mulh*i+1;
1548
-                        if(mulh==1)
1549
-                                i1=i0;
1550
-                        i0*=precw;
1551
-                        i1*=precw;
1552
-                        for(j=0; j<w; j++)
1553
-                        {
1554
-                                sint        j0= mulw*j;
1555
-                                sint        j1= mulw*j+1;
1556
-                                if(mulw==1)
1557
-                                        j1=j0;
1558
-                                CRGBA        &c0= pRgbaPrev[i0+j0];
1559
-                                CRGBA        &c1= pRgbaPrev[i0+j1];
1560
-                                CRGBA        &c2= pRgbaPrev[i1+j0];
1561
-                                CRGBA        &c3= pRgbaPrev[i1+j1];
1562
-                                pRgba[i*w + j].R = (c0.R +
1563
-                                                                        c1.R +
1564
-                                                                        c2.R +
1565
-                                                                        c3.R + 2 ) /4;
1566
-                                pRgba[i*w + j].G = (c0.G +
1567
-                                                                        c1.G +
1568
-                                                                        c2.G +
1569
-                                                                        c3.G + 2 ) /4;
1570
-                                pRgba[i*w + j].B = (c0.B +
1571
-                                                                        c1.B +
1572
-                                                                        c2.B +
1573
-                                                                        c3.B + 2 ) /4;
1574
-                                pRgba[i*w + j].A = (c0.A +
1575
-                                                                        c1.A +
1576
-                                                                        c2.A +
1577
-                                                                        c3.A + 2 ) /4;
1578
-                        }
1579
-                }
1580
-
1581
-                _MipMapCount++;
1582
-        }
1583
-}
1584
-
1585
-/*-------------------------------------------------------------------*\
1586
-                                                        computeNeededMipMapCount
1587
-\*-------------------------------------------------------------------*/
1588
-uint32 CBitmap::computeNeededMipMapCount() const
1589
-{
1590
-        if(_MipMapCount == 0) return 0;
1591
-        if(!NLMISC::isPowerOf2(_Width)) return 1;
1592
-        if(!NLMISC::isPowerOf2(_Height)) return 1;
1593
-
1594
-        uint32 mipMapCount = 1;
1595
-        uint32 w = _Width;
1596
-        uint32 h = _Height;
1597
-
1598
-        while(w>1 || h>1)
1599
-        {
1600
-                w = (w+1)/2;
1601
-                h = (h+1)/2;
1602
-                ++mipMapCount;
1603
-        }
1604
-        return mipMapCount;
1605
-}
1606
-
1607
-/*-------------------------------------------------------------------*\
1608
-                                                        releaseMipMaps
1609
-\*-------------------------------------------------------------------*/
1610
-void CBitmap::releaseMipMaps()
1611
-{
1612
-        if(_MipMapCount<=1) return;
1613
-
1614
-        _MipMapCount=1;
1615
-        for(sint i=1;i<MAX_MIPMAP;i++)
1616
-        {
1617
-                NLMISC::contReset(_Data[i]);
1618
-        }
1619
-}
1620
-
1621
-/*-------------------------------------------------------------------*\
1622
-                                                        resample
1623
-\*-------------------------------------------------------------------*/
1624
-void CBitmap::resample(sint32 nNewWidth, sint32 nNewHeight)
1625
-{
1626
-        nlassert(PixelFormat == RGBA);
1627
-        bool needRebuild = false;
1628
-
1629
-        // Deleting mipmaps
1630
-        //logResample("Resample: 10");
1631
-        if(_MipMapCount>1)
1632
-                needRebuild = true;
1633
-        releaseMipMaps();
1634
-        //logResample("Resample: 20");
1635
-
1636
-        if(nNewWidth==0 || nNewHeight==0)
1637
-        {
1638
-                _Width = _Height = 0;
1639
-                //logResample("Resample: 25");
1640
-                return;
1641
-        }
1642
-
1643
-        //logResample("Resample: 30");
1644
-        CObjectVector<uint8> pDestui;
1645
-        pDestui.resize(nNewWidth*nNewHeight*4);
1646
-        //logResample("Resample: 40");
1647
-        NLMISC::CRGBA *pDestRgba = (NLMISC::CRGBA*)&pDestui[0];
1648
-        //logResample("Resample: 50");
1649
-
1650
-        resamplePicture32 ((NLMISC::CRGBA*)&_Data[0][0], pDestRgba, _Width, _Height, nNewWidth, nNewHeight);
1651
-        //logResample("Resample: 60");
1652
-
1653
-        NLMISC::contReset(_Data[0]); // free memory
1654
-        //logResample("Resample: 70");
1655
-
1656
-        _Data[0] =  pDestui;
1657
-        //logResample("Resample: 80");
1658
-        _Width= nNewWidth;
1659
-        _Height= nNewHeight;
1660
-
1661
-        // Rebuilding mipmaps
1662
-        //logResample("Resample: 90");
1663
-        if(needRebuild)
1664
-        {
1665
-                buildMipMaps();
1666
-                //logResample("Resample: 95");
1667
-        }
1668
-        //logResample("Resample: 100");
1669
-}
1670
-
1671
-
1672
-/*-------------------------------------------------------------------*\
1673
-                                                        resize
1674
-\*-------------------------------------------------------------------*/
1675
-void CBitmap::resize (sint32 nNewWidth, sint32 nNewHeight, TType newType, bool resetTo0)
1676
-{
1677
-        // Deleting mipmaps
1678
-        releaseMipMaps();
1679
-
1680
-        // Change type of bitmap ?
1681
-        if (newType!=DonTKnow)
1682
-                PixelFormat=newType;
1683
-
1684
-        _Width = nNewWidth;
1685
-        _Height = nNewHeight;
1686
-
1687
-        // resize the level 0 only.
1688
-        resizeMipMap(0, nNewWidth, nNewHeight, resetTo0);
1689
-}
1690
-
1691
-
1692
-/*-------------------------------------------------------------------*\
1693
-                                                        resizeMipMap
1694
-\*-------------------------------------------------------------------*/
1695
-void CBitmap::resizeMipMap (uint32 numMipMap, sint32 nNewWidth, sint32 nNewHeight, bool resetTo0)
1696
-{
1697
-        nlassert(numMipMap<MAX_MIPMAP);
1698
-
1699
-        // free memory
1700
-        NLMISC::contReset(_Data[numMipMap]);
1701
-
1702
-        // DXTC compressed??
1703
-        //bool        isDXTC= PixelFormat==DXTC1 || PixelFormat==DXTC1Alpha || PixelFormat==DXTC3 || PixelFormat==DXTC5;
1704
-        // if yes, must round up width and height to 4, for allocation
1705
-        nNewWidth= 4*((nNewWidth+3)/4);
1706
-        nNewHeight= 4*((nNewHeight+3)/4);
1707
-
1708
-        // resize the buffer
1709
-        _Data[numMipMap].resize (((uint32)(nNewWidth*nNewHeight)*bitPerPixels[PixelFormat])/8);
1710
-
1711
-        // Fill 0?
1712
-        if( resetTo0 )
1713
-                _Data[numMipMap].fill(0);
1714
-}
1715
-
1716
-
1717
-/*-------------------------------------------------------------------*\
1718
-                                                        reset
1719
-\*-------------------------------------------------------------------*/
1720
-void CBitmap::setMipMapCount(uint32 mmc)
1721
-{
1722
-        _MipMapCount= uint8(mmc);
1723
-}
1724
-
1725
-
1726
-/*-------------------------------------------------------------------*\
1727
-                                                        reset
1728
-\*-------------------------------------------------------------------*/
1729
-void CBitmap::reset(TType type)
1730
-{
1731
-        for(uint i=0; i<_MipMapCount; i++)
1732
-        {
1733
-                NLMISC::contReset(_Data[i]);
1734
-                _Data[i].resize(0);
1735
-        }
1736
-        _Width = _Height = 0;
1737
-        _MipMapCount= 1;
1738
-
1739
-        // Change pixel format
1740
-        PixelFormat=type;
1741
-}
1742
-
1743
-
1744
-
1745
-/*-------------------------------------------------------------------*\
1746
-                                                        resamplePicture32
1747
-\*-------------------------------------------------------------------*/
1748
-void CBitmap::resamplePicture32 (const NLMISC::CRGBA *pSrc, NLMISC::CRGBA *pDest,
1749
-                                                                 sint32 nSrcWidth, sint32 nSrcHeight,
1750
-                                                                 sint32 nDestWidth, sint32 nDestHeight)
1751
-{
1752
-        //logResample("RP32: 0 pSrc=%p pDest=%p, Src=%d x %d Dest=%d x %d", pSrc, pDest, nSrcWidth, nSrcHeight, nDestWidth, nDestHeight);
1753
-        if ((nSrcWidth<=0)||(nSrcHeight<=0)||(nDestHeight<=0)||(nDestHeight<=0))
1754
-                return;
1755
-
1756
-        // If we're reducing it by 2, call the fast resample
1757
-        if (((nSrcHeight / 2) == nDestHeight) && ((nSrcHeight % 2) == 0) &&
1758
-                ((nSrcWidth  / 2) == nDestWidth)  && ((nSrcWidth  % 2) == 0))
1759
-        {
1760
-                resamplePicture32Fast(pSrc, pDest, nSrcWidth, nSrcHeight, nDestWidth, nDestHeight);
1761
-                return;
1762
-        }
1763
-
1764
-        bool bXMag=(nDestWidth>=nSrcWidth);
1765
-        bool bYMag=(nDestHeight>=nSrcHeight);
1766
-        bool bXEq=(nDestWidth==nSrcWidth);
1767
-        bool bYEq=(nDestHeight==nSrcHeight);
1768
-        std::vector<NLMISC::CRGBAF> pIterm (nDestWidth*nSrcHeight);
1769
-
1770
-        if (bXMag)
1771
-        {
1772
-                float fXdelta=(float)(nSrcWidth)/(float)(nDestWidth);
1773
-                NLMISC::CRGBAF *pItermPtr=&*pIterm.begin();
1774
-                sint32 nY;
1775
-                for (nY=0; nY<nSrcHeight; nY++)
1776
-                {
1777
-                        const NLMISC::CRGBA *pSrcLine=pSrc;
1778
-                        float fX=0.f;
1779
-                        sint32 nX;
1780
-                        for (nX=0; nX<nDestWidth; nX++)
1781
-                        {
1782
-                                float fVirgule=fX-(float)floor(fX);
1783
-                                nlassert (fVirgule>=0.f);
1784
-                                NLMISC::CRGBAF vColor;
1785
-                                if (fVirgule>=0.5f)
1786
-                                {
1787
-                                        if (fX<(float)(nSrcWidth-1))
1788
-                                        {
1789
-                                                NLMISC::CRGBAF vColor1 (pSrcLine[(sint32)floor(fX)]);
1790
-                                                NLMISC::CRGBAF vColor2 (pSrcLine[(sint32)floor(fX)+1]);
1791
-                                                vColor=vColor1*(1.5f-fVirgule)+vColor2*(fVirgule-0.5f);
1792
-                                        }
1793
-                                        else
1794
-                                                vColor=NLMISC::CRGBAF (pSrcLine[(sint32)floor(fX)]);
1795
-                                }
1796
-                                else
1797
-                                {
1798
-                                        if (fX>=1.f)
1799
-                                        {
1800
-                                                NLMISC::CRGBAF vColor1 (pSrcLine[(sint32)floor(fX)]);
1801
-                                                NLMISC::CRGBAF vColor2 (pSrcLine[(sint32)floor(fX)-1]);
1802
-                                                vColor=vColor1*(0.5f+fVirgule)+vColor2*(0.5f-fVirgule);
1803
-                                        }
1804
-                                        else
1805
-                                                vColor=NLMISC::CRGBAF (pSrcLine[(sint32)floor(fX)]);
1806
-                                }
1807
-                                *(pItermPtr++)=vColor;
1808
-                                fX+=fXdelta;
1809
-                        }
1810
-                        pSrc+=nSrcWidth;
1811
-                }
1812
-        }
1813
-        else if (bXEq)
1814
-        {
1815
-                NLMISC::CRGBAF *pItermPtr=&*pIterm.begin();
1816
-                for (sint32 nY=0; nY<nSrcHeight; nY++)
1817
-                {
1818
-                        const NLMISC::CRGBA *pSrcLine=pSrc;
1819
-                        sint32 nX;
1820
-                        for (nX=0; nX<nDestWidth; nX++)
1821
-                                *(pItermPtr++)=NLMISC::CRGBAF (pSrcLine[nX]);
1822
-                        pSrc+=nSrcWidth;
1823
-                }
1824
-        }
1825
-        else
1826
-        {
1827
-                double fXdelta=(double)(nSrcWidth)/(double)(nDestWidth);
1828
-                nlassert (fXdelta>1.f);
1829
-                NLMISC::CRGBAF *pItermPtr=&*pIterm.begin();
1830
-                sint32 nY;
1831
-                for (nY=0; nY<nSrcHeight; nY++)
1832
-                {
1833
-                        const NLMISC::CRGBA *pSrcLine=pSrc;
1834
-                        double fX=0.f;
1835
-                        sint32 nX;
1836
-                        for (nX=0; nX<nDestWidth; nX++)
1837
-                        {
1838
-                                NLMISC::CRGBAF vColor (0.f, 0.f, 0.f, 0.f);
1839
-                                double fFinal=fX+fXdelta;
1840
-                                while ((fX<fFinal)&&((sint32)fX!=nSrcWidth))
1841
-                                {
1842
-                                        double fNext=(double)floor (fX)+1.f;
1843
-                                        if (fNext>fFinal)
1844
-                                                fNext=fFinal;
1845
-                                        vColor+=((float)(fNext-fX))*NLMISC::CRGBAF (pSrcLine[(sint32)floor(fX)]);
1846
-                                        fX=fNext;
1847
-                                }
1848
-                                fX = fFinal; // ensure fX == fFinal
1849
-                                vColor/=(float)fXdelta;
1850
-                                *(pItermPtr++)=vColor;
1851
-                        }
1852
-                        pSrc+=nSrcWidth;
1853
-                }
1854
-        }
1855
-
1856
-        if (bYMag)
1857
-        {
1858
-                double fYdelta=(double)(nSrcHeight)/(double)(nDestHeight);
1859
-                sint32 nX;
1860
-                for (nX=0; nX<nDestWidth; nX++)
1861
-                {
1862
-                        double fY=0.f;
1863
-                        sint32 nY;
1864
-                        for (nY=0; nY<nDestHeight; nY++)
1865
-                        {
1866
-                                double fVirgule=fY-(double)floor(fY);
1867
-                                nlassert (fVirgule>=0.f);
1868
-                                NLMISC::CRGBAF vColor;
1869
-                                if (fVirgule>=0.5f)
1870
-                                {
1871
-                                        if (fY<(double)(nSrcHeight-1))
1872
-                                        {
1873
-                                                NLMISC::CRGBAF vColor1=pIterm[((sint32)floor(fY))*nDestWidth+nX];
1874
-                                                NLMISC::CRGBAF vColor2=pIterm[(((sint32)floor(fY))+1)*nDestWidth+nX];
1875
-                                                vColor=vColor1*(1.5f-(float)fVirgule)+vColor2*((float)fVirgule-0.5f);
1876
-                                        }
1877
-                                        else
1878
-                                                vColor=pIterm[((sint32)floor(fY))*nDestWidth+nX];
1879
-                                }
1880
-                                else
1881
-                                {
1882
-                                        if (fY>=1.f)
1883
-                                        {
1884
-                                                NLMISC::CRGBAF vColor1=pIterm[((sint32)floor(fY))*nDestWidth+nX];
1885
-                                                NLMISC::CRGBAF vColor2=pIterm[(((sint32)floor(fY))-1)*nDestWidth+nX];
1886
-                                                vColor=vColor1*(0.5f+(float)fVirgule)+vColor2*(0.5f-(float)fVirgule);
1887
-                                        }
1888
-                                        else
1889
-                                                vColor=pIterm[((sint32)floor(fY))*nDestWidth+nX];
1890
-                                }
1891
-                                pDest[nX+nY*nDestWidth]=vColor;
1892
-                                fY+=fYdelta;
1893
-                        }
1894
-                }
1895
-        }
1896
-        else if (bYEq)
1897
-        {
1898
-                for (sint32 nX=0; nX<nDestWidth; nX++)
1899
-                {
1900
-                        sint32 nY;
1901
-                        for (nY=0; nY<nDestHeight; nY++)
1902
-                        {
1903
-                                pDest[nX+nY*nDestWidth]=pIterm[nY*nDestWidth+nX];
1904
-                        }
1905
-                }
1906
-        }
1907
-        else
1908
-        {
1909
-                double fYdelta=(double)(nSrcHeight)/(double)(nDestHeight);
1910
-                nlassert (fYdelta>1.f);
1911
-                sint32 nX;
1912
-                for (nX=0; nX<nDestWidth; nX++)
1913
-                {
1914
-                        double fY=0.f;
1915
-                        sint32 nY;
1916
-                        for (nY=0; nY<nDestHeight; nY++)
1917
-                        {
1918
-                                NLMISC::CRGBAF vColor (0.f, 0.f, 0.f, 0.f);
1919
-                                double fFinal=fY+fYdelta;
1920
-                                while ((fY<fFinal)&&((sint32)fY!=nSrcHeight))
1921
-                                {
1922
-                                        double fNext=(double)floor (fY)+1.f;
1923
-                                        if (fNext>fFinal)
1924
-                                                fNext=fFinal;
1925
-                                        vColor+=((float)(fNext-fY))*pIterm[((sint32)floor(fY))*nDestWidth+nX];
1926
-                                        fY=fNext;
1927
-                                }
1928
-                                vColor/=(float)fYdelta;
1929
-                                pDest[nX+nY*nDestWidth]=vColor;
1930
-                        }
1931
-                }
1932
-        }
1933
-}
1934
-
1935
-/*-------------------------------------------------------------------*\
1936
-                                                        resamplePicture32Fast
1937
-\*-------------------------------------------------------------------*/
1938
-void CBitmap::resamplePicture32Fast (const NLMISC::CRGBA *pSrc, NLMISC::CRGBA *pDest,
1939
-                                                                         sint32 nSrcWidth, sint32 nSrcHeight,
1940
-                                                                         sint32 nDestWidth, sint32 nDestHeight)
1941
-{
1942
-        // the image is divided by two : 1 pixel in dest = 4 pixels in src
1943
-        // the resulting pixel in dest is an average of the four pixels in src
1944
-
1945
-        nlassert(nSrcWidth  % 2 == 0);
1946
-        nlassert(nSrcHeight % 2 == 0);
1947
-        nlassert(nSrcWidth  / 2 == nDestWidth);
1948
-        nlassert(nSrcHeight / 2 == nDestHeight);
1949
-
1950
-        sint32 x, y, twoX, twoSrcWidthByY;
1951
-
1952
-        for (y=0 ; y<nDestHeight ; y++)
1953
-        {
1954
-                twoSrcWidthByY = 2*nSrcWidth*y;
1955
-                for (x=0 ; x<nDestWidth ; x++)
1956
-                {
1957
-                        twoX = 2*x;
1958
-                        pDest[x+y*nDestWidth].avg4( pSrc[twoX   + twoSrcWidthByY             ],
1959
-                                                                                pSrc[twoX   + twoSrcWidthByY + nSrcWidth ],
1960
-                                                                                pSrc[twoX+1 + twoSrcWidthByY             ],
1961
-                                                                                pSrc[twoX+1 + twoSrcWidthByY + nSrcWidth ]);
1962
-                }
1963
-        }
1964
-}
1965
-
1966
-
1967
-
1968
-/*-------------------------------------------------------------------*\
1969
-                                                        readTGA
1970
-\*-------------------------------------------------------------------*/
1971
-uint8 CBitmap::readTGA( NLMISC::IStream &f)
1972
-{
1973
-        /* ***********************************************
1974
-         *        WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
1975
-         *        It can be loaded/called through CAsyncFileManager for instance
1976
-         * ***********************************************/
1977
-
1978
-        if(!f.isReading()) return 0;
1979
-
1980
-        uint32                        size;
1981
-        uint32                        x,y;
1982
-        sint32                        slsize;
1983
-        uint8                        *scanline;
1984
-        uint8                        r,g,b;
1985
-        sint32                        i,j,k;
1986
-
1987
-        // TGA file header fields
1988
-        uint8        lengthID;
1989
-        uint8        cMapType;
1990
-        uint8        imageType;
1991
-        uint16        origin;
1992
-        uint16        length;
1993
-        uint8        depth;
1994
-        uint16        xOrg;
1995
-        uint16        yOrg;
1996
-        uint16        width;
1997
-        uint16        height;
1998
-        uint8        imageDepth;
1999
-        uint8        desc;
2000
-
2001
-
2002
-        // Determining whether file is in Original or New TGA format
2003
-
2004
-        bool newTgaFormat;
2005
-        uint32 extAreaOffset;
2006
-        uint32 devDirectoryOffset;
2007
-        char signature[16];
2008
-
2009
-        f.seek (0, f.end);
2010
-        newTgaFormat = false;
2011
-        if (f.getPos() >= 26)
2012
-        {
2013
-                f.seek (-26, f.end);
2014
-                f.serial(extAreaOffset);
2015
-                f.serial(devDirectoryOffset);
2016
-                for(i=0; i<16; i++)
2017
-                {
2018
-                        f.serial(signature[i]);
2019
-                }
2020
-                if(strncmp(signature,"TRUEVISION-XFILE",16)==0)
2021
-                        newTgaFormat = true;
2022
-        }
2023
-
2024
-
2025
-
2026
-        // Reading TGA file header
2027
-        f.seek (0, f.begin);
2028
-
2029
-        f.serial(lengthID);
2030
-        f.serial(cMapType);
2031
-        f.serial(imageType);
2032
-        f.serial(origin);
2033
-        f.serial(length);
2034
-        f.serial(depth);
2035
-        f.serial(xOrg);
2036
-        f.serial(yOrg);
2037
-        f.serial(width);
2038
-        f.serial(height);
2039
-        f.serial(imageDepth);
2040
-        f.serial(desc);
2041
-
2042
-        if(cMapType!=0)
2043
-        {
2044
-                nlinfo("readTga : color-map not supported");
2045
-        }
2046
-
2047
-        if(lengthID>0)
2048
-        {
2049
-                uint8        dummy;
2050
-                for(i=0; i<lengthID; i++)
2051
-                        f.serial(dummy);
2052
-        }
2053
-
2054
-
2055
-
2056
-        // Reading TGA image data
2057
-
2058
-        _Width = width;
2059
-        _Height = height;
2060
-        size = _Width * _Height * (imageDepth/8);
2061
-
2062
-        switch(imageType)
2063
-        {
2064
-                // Uncompressed RGB or RGBA
2065
-                case 2:
2066
-                {
2067
-                        _Data[0].resize(_Width*_Height*4);
2068
-                        uint8 upSideDown = ((desc & (1 << 5))==0);
2069
-                        slsize = _Width * imageDepth / 8;
2070
-
2071
-                        scanline = new uint8[slsize];
2072
-                        if(!scanline)
2073
-                        {
2074
-                                throw EAllocationFailure();
2075
-                        }
2076
-
2077
-                        for(y=0; y<_Height;y++)
2078
-                        {
2079
-                                // Serial buffer: more efficient way to load.
2080
-                                f.serialBuffer (scanline, slsize);
2081
-
2082
-                                if(imageDepth==24 || imageDepth==32)
2083
-                                {
2084
-                                        sint32 mult = 3;
2085
-                                        if(imageDepth==16)
2086
-                                        {
2087
-                                                mult = 2;
2088
-                                        }
2089
-                                        if(imageDepth==32)
2090
-                                        {
2091
-                                                mult = 4;
2092
-                                        }
2093
-                                        if(imageDepth!=16)
2094
-                                        {
2095
-                                                for(x=0; x<_Width; x++)
2096
-                                                {
2097
-                                                        // RGB(A)
2098
-                                                        r = scanline[x*mult+0];
2099
-                                                        g = scanline[x*mult+1];
2100
-                                                        b = scanline[x*mult+2];
2101
-                                                        // Switching to BGR(A)
2102
-                                                        scanline[x*mult+0] = b;
2103
-                                                        scanline[x*mult+1] = g;
2104
-                                                        scanline[x*mult+2] = r;
2105
-                                                }
2106
-                                        }
2107
-                                }
2108
-
2109
-                                k=0;
2110
-                                for(i=0; i<width; i++)
2111
-                                {
2112
-                                        if(upSideDown)
2113
-                                        {
2114
-                                                if(imageDepth==16)
2115
-                                                {
2116
-                                                        uint16 toto = (uint16)scanline[k++];
2117
-                                                        toto |= scanline[k++]<<8;
2118
-                                                        uint _r = toto>>10;
2119
-                                                        uint _g = (toto>>5)&0x1f;
2120
-                                                        uint _b = toto&0x1f;
2121
-                                                        _Data[0][(height-y-1)*width*4 + 4*i] = uint8((_r<<3) | (_r>>2));
2122
-                                                        _Data[0][(height-y-1)*width*4 + 4*i + 1] = uint8((_g<<3) | (_g>>2));
2123
-                                                        _Data[0][(height-y-1)*width*4 + 4*i + 2] = uint8((_b<<3) | (_b>>2));
2124
-                                                        _Data[0][(height-y-1)*width*4 + 4*i + 3] = 255;
2125
-                                                }
2126
-                                                else
2127
-                                                {
2128
-                                                        _Data[0][(height-y-1)*width*4 + 4*i] = scanline[k++];
2129
-                                                        _Data[0][(height-y-1)*width*4 + 4*i + 1] = scanline[k++];
2130
-                                                        _Data[0][(height-y-1)*width*4 + 4*i + 2] = scanline[k++];
2131
-                                                        if(imageDepth==32)
2132
-                                                                _Data[0][(height-y-1)*width*4 + 4*i + 3] = scanline[k++];
2133
-                                                        else
2134
-                                                                _Data[0][(height-y-1)*width*4 + 4*i + 3] = 255;
2135
-                                                }
2136
-                                        }
2137
-                                        else
2138
-                                        {
2139
-                                                if(imageDepth==16)
2140
-                                                {
2141
-                                                        uint16 toto = (uint16)scanline[k++];
2142
-                                                        toto |= scanline[k++]<<8;
2143
-                                                        int _r = toto>>10;
2144
-                                                        int _g = toto&(0x3e0)>>5;
2145
-                                                        int _b = toto&0x1f;
2146
-                                                        _Data[0][y*width*4 + 4*i] = uint8((_r<<3) | (_r>>2));
2147
-                                                        _Data[0][y*width*4 + 4*i + 1] = uint8((_g<<3) | (_g>>2));
2148
-                                                        _Data[0][y*width*4 + 4*i + 2] = uint8((_b<<3) | (_b>>2));
2149
-                                                        _Data[0][y*width*4 + 4*i + 3] = 255;
2150
-                                                }
2151
-                                                else
2152
-                                                {
2153
-                                                        _Data[0][y*width*4 + 4*i] = scanline[k++];
2154
-                                                        _Data[0][y*width*4 + 4*i + 1] = scanline[k++];
2155
-                                                        _Data[0][y*width*4 + 4*i + 2] = scanline[k++];
2156
-                                                        if(imageDepth==32)
2157
-                                                                _Data[0][y*width*4 + 4*i + 3] = scanline[k++];
2158
-                                                        else
2159
-                                                                _Data[0][y*width*4 + 4*i + 3] = 255;
2160
-                                                }
2161
-                                        }
2162
-                                }
2163
-                        }
2164
-
2165
-                        PixelFormat = RGBA;
2166
-                        delete []scanline;
2167
-                };
2168
-                break;
2169
-
2170
-                // Uncompressed Grayscale bitmap
2171
-                case 3:
2172
-                {
2173
-                        _Data[0].resize(_Width*_Height);
2174
-                        uint8 upSideDown = ((desc & (1 << 5))==0);
2175
-                        slsize = _Width;
2176
-
2177
-                        scanline = new uint8[slsize];
2178
-                        if(!scanline)
2179
-                        {
2180
-                                throw EAllocationFailure();
2181
-                        }
2182
-
2183
-                        for(y=0; y<_Height;y++)
2184
-                        {
2185
-                                // Serial buffer: more efficient way to load.
2186
-                                f.serialBuffer (scanline, slsize);
2187
-
2188
-                                k=0;
2189
-                                for(i=0; i<width; i++)
2190
-                                {
2191
-                                        if(upSideDown)
2192
-                                                _Data[0][(height-y-1)*width + i] = scanline[k++];
2193
-                                        else
2194
-                                                _Data[0][y*width + i] = scanline[k++];
2195
-                                }
2196
-                        }
2197
-
2198
-                        PixelFormat = _LoadGrayscaleAsAlpha?Alpha:Luminance;
2199
-                        delete []scanline;
2200
-                };
2201
-                break;
2202
-
2203
-                // Compressed RGB or RGBA
2204
-                case 10:
2205
-                {
2206
-                        uint8 packet;
2207
-                        uint8 pixel[4];
2208
-                        uint32 imageSize = width*height;
2209
-                        uint32 readSize = 0;
2210
-                        uint8 upSideDown = ((desc & (1 << 5))==0);
2211
-                        _Data[0].resize(_Width*_Height*4);
2212
-                        uint        dstId= 0;
2213
-
2214
-                        while(readSize < imageSize)
2215
-                        {
2216
-                                f.serial(packet);
2217
-                                if((packet & 0x80) > 0) // packet RLE
2218
-                                {
2219
-                                        for(i=0; i<imageDepth/8; i++)
2220
-                                        {
2221
-                                                f.serial(pixel[i]);
2222
-                                        }
2223
-                                        for (i=0; i < (packet & 0x7F) + 1; i++)
2224
-                                        {
2225
-                                                if(imageDepth==32)
2226
-                                                {
2227
-                                                        _Data[0][dstId++]= pixel[2];
2228
-                                                        _Data[0][dstId++]= pixel[1];
2229
-                                                        _Data[0][dstId++]= pixel[0];
2230
-                                                        _Data[0][dstId++]= pixel[3];
2231
-                                                }
2232
-                                                if(imageDepth==24)
2233
-                                                {
2234
-                                                        _Data[0][dstId++]= pixel[2];
2235
-                                                        _Data[0][dstId++]= pixel[1];
2236
-                                                        _Data[0][dstId++]= pixel[0];
2237
-                                                        _Data[0][dstId++]= 0;
2238
-                                                }
2239
-                                        }
2240
-                                }
2241
-                                else        // packet Raw
2242
-                                {
2243
-                                        for(i=0; i<((packet & 0x7F) + 1); i++)
2244
-                                        {
2245
-                                                for(j=0; j<imageDepth/8; j++)
2246
-                                                {
2247
-                                                        f.serial(pixel[j]);
2248
-                                                }
2249
-                                                if(imageDepth==32)
2250
-                                                {
2251
-                                                        _Data[0][dstId++]= pixel[2];
2252
-                                                        _Data[0][dstId++]= pixel[1];
2253
-                                                        _Data[0][dstId++]= pixel[0];
2254
-                                                        _Data[0][dstId++]= pixel[3];
2255
-                                                }
2256
-                                                if(imageDepth==24)
2257
-                                                {
2258
-                                                        _Data[0][dstId++]= pixel[2];
2259
-                                                        _Data[0][dstId++]= pixel[1];
2260
-                                                        _Data[0][dstId++]= pixel[0];
2261
-                                                        _Data[0][dstId++]= 0;
2262
-                                                }
2263
-                                        }
2264
-                                  }
2265
-                                readSize += (packet & 0x7F) + 1;
2266
-                        }
2267
-                        PixelFormat = RGBA;
2268
-
2269
-                        if (upSideDown) flipV();
2270
-                };
2271
-                break;
2272
-
2273
-                // Compressed Grayscale bitmap (not tested)
2274
-                case 11:
2275
-                {
2276
-                        uint8 packet;
2277
-                        uint8 pixel[4];
2278
-                        uint32 imageSize = width*height;
2279
-                        uint32 readSize = 0;
2280
-                        _Data[0].resize(_Width*_Height);
2281
-                        uint        dstId= 0;
2282
-
2283
-                        while(readSize < imageSize)
2284
-                        {
2285
-                                f.serial(packet);
2286
-                                if((packet & 0x80) > 0) // packet RLE
2287
-                                {
2288
-                                        f.serial(pixel[0]);
2289
-                                        for (i=0; i < (packet & 0x7F) + 1; i++)
2290
-                                        {
2291
-                                                _Data[0][dstId++]= pixel[0];
2292
-                                        }
2293
-                                }
2294
-                                else        // packet Raw
2295
-                                {
2296
-                                        for(i=0; i<((packet & 0x7F) + 1); i++)
2297
-                                        {
2298
-                                                f.serial(pixel[0]);
2299
-                                                _Data[0][dstId++]= pixel[0];
2300
-                                        }
2301
-                                  }
2302
-                                readSize += (packet & 0x7F) + 1;
2303
-                        }
2304
-                        PixelFormat = _LoadGrayscaleAsAlpha?Alpha:Luminance;
2305
-                };
2306
-                break;
2307
-
2308
-                default:
2309
-                        return 0;
2310
-        }
2311
-
2312
-        _MipMapCount = 1;
2313
-        return(imageDepth);
2314
-
2315
-}
2316
-
2317
-/*-------------------------------------------------------------------*\
2318
-                                                        writeTGA
2319
-\*-------------------------------------------------------------------*/
2320
-bool CBitmap::writeTGA( NLMISC::IStream &f, uint32 d, bool upsideDown)
2321
-{
2322
-        if(f.isReading()) return false;
2323
-        if (d==0)
2324
-        {
2325
-                switch (PixelFormat)
2326
-                {
2327
-                case RGBA:
2328
-                        d = 32;
2329
-                        break;
2330
-                case Luminance:
2331
-                        d = 8;
2332
-                        break;
2333
-                case Alpha:
2334
-                        d = 8;
2335
-                        break;
2336
-                default:
2337
-                        ;
2338
-                }
2339
-        }
2340
-        if(d!=24 && d!=32 && d!=16 && d!=8) return false;
2341
-        if ((PixelFormat != RGBA)&&(PixelFormat != Alpha)&&(PixelFormat != Luminance)) return false;
2342
-        if ((PixelFormat == Alpha) && (d != 8)) return false;
2343
-        if ((PixelFormat == Luminance) && (d != 8)) return false;
2344
-
2345
-        sint32        i,j,x,y;
2346
-        uint8        * scanline;
2347
-        uint8        r,g,b,a;
2348
-
2349
-        uint8        lengthID = 0;
2350
-        uint8        cMapType = 0;
2351
-        uint8        imageType = 2;
2352
-        uint16        origin = 0;
2353
-        uint16        length = 0;
2354
-        uint8        depth = 0;
2355
-        uint16        xOrg = 0;
2356
-        uint16        yOrg = 0;
2357
-        uint16        width = (uint16)_Width;
2358
-        uint16        height = (uint16)_Height;
2359
-        uint8        imageDepth = (uint8)d;
2360
-        uint8        desc = 0;
2361
-        if (upsideDown)
2362
-                desc |= 1<<5;
2363
-
2364
-        if ((PixelFormat == Alpha) || (PixelFormat == Luminance))
2365
-                imageType = 3; // Uncompressed grayscale
2366
-
2367
-        f.serial(lengthID);
2368
-        f.serial(cMapType);
2369
-        f.serial(imageType);
2370
-        f.serial(origin);
2371
-        f.serial(length);
2372
-        f.serial(depth);
2373
-        f.serial(xOrg);
2374
-        f.serial(yOrg);
2375
-        f.serial(width);
2376
-        f.serial(height);
2377
-        f.serial(imageDepth);
2378
-        f.serial(desc);
2379
-
2380
-        if ((PixelFormat == Alpha)||(PixelFormat == Luminance))
2381
-                scanline = new uint8[width];
2382
-        else
2383
-                scanline = new uint8[width*4];
2384
-        if(!scanline)
2385
-        {
2386
-                throw EAllocationFailure();
2387
-        }
2388
-
2389
-        for(y=0; y<(sint32)height; y++)
2390
-        {
2391
-
2392
-                uint32 k=0;
2393
-                if (PixelFormat == Alpha)
2394
-                {
2395
-                        for(i=0; i<width; ++i) // Alpha
2396
-                        {
2397
-                                scanline[k++] = _Data[0][(height-y-1)*width + i];
2398
-                        }
2399
-                }
2400
-                else if (PixelFormat == Luminance)
2401
-                {
2402
-                        for(i=0; i<width; ++i) // Luminance
2403
-                        {
2404
-                                scanline[k++] = _Data[0][(height-y-1)*width + i];
2405
-                        }
2406
-                }
2407
-                else
2408
-                {
2409
-                        for(i=0; i<width*4; i+=4) // 4:RGBA
2410
-                        {
2411
-                                if(d==16)
2412
-                                {
2413
-                                        for(j=0; j<(sint32)4; j++)
2414
-                                        {
2415
-                                                scanline[k++] = _Data[0][(height-y-1)*width*4 + i + j];
2416
-                                        }
2417
-                                }
2418
-                                else
2419
-                                {
2420
-                                        for(j=0; j<(sint32)d/8; j++)
2421
-                                        {
2422
-                                                scanline[k++] = _Data[0][(height-y-1)*width*4 + i + j];
2423
-                                        }
2424
-                                }
2425
-                        }
2426
-                }
2427
-
2428
-                if(d==16)
2429
-                {
2430
-                        for(x=0; x<(sint32)width; x++)
2431
-                        {
2432
-                                r = scanline[x*4+0];
2433
-                                g = scanline[x*4+1];
2434
-                                b = scanline[x*4+2];
2435
-                                int rr = r >>3;
2436
-                                int gg = g >>3;
2437
-                                int bb = b >>3;
2438
-                                uint16 c16 = uint16((rr<<10) | (gg<<5) | bb);
2439
-                                scanline[x*2+0] = c16&0xff;
2440
-                                scanline[x*2+1] = c16>>8;
2441
-                        }
2442
-                }
2443
-                if(d==24)
2444
-                {
2445
-                        for(x=0; x<(sint32)width; x++)
2446
-                        {
2447
-                                r = scanline[x*3+0];
2448
-                                g = scanline[x*3+1];
2449
-                                b = scanline[x*3+2];
2450
-                                scanline[x*3+0] = b;
2451
-                                scanline[x*3+1] = g;
2452
-                                scanline[x*3+2] = r;
2453
-                        }
2454
-                }
2455
-                if(d==32)
2456
-                {
2457
-                        for(x=0; x<(sint32)width; x++)
2458
-                        {
2459
-                                r = scanline[x*4+0];
2460
-                                g = scanline[x*4+1];
2461
-                                b = scanline[x*4+2];
2462
-                                a= scanline[x*4+3];
2463
-                                scanline[x*4+0] = b;
2464
-                                scanline[x*4+1] = g;
2465
-                                scanline[x*4+2] = r;
2466
-                                scanline[x*4+3] = a;
2467
-                        }
2468
-                }
2469
-
2470
-                int finaleSize=width*d/8;
2471
-                for(i=0; i<finaleSize; i++)
2472
-                {
2473
-                        f.serial(scanline[i]);
2474
-                }
2475
-        }
2476
-        delete []scanline;
2477
-        return true;
2478
-}
2479
-
2480
-
2481
-template<class T>
2482
-void rotateCCW (const T* src, T* dst, uint srcWidth, uint srcHeight)
2483
-{
2484
-        for (uint y=0; y<srcHeight; y++)
2485
-        for (uint x=0; x<srcWidth; x++)
2486
-        {
2487
-                uint dstX=y;
2488
-                uint dstY=srcWidth-x-1;
2489
-                dst[dstX+dstY*srcHeight]=src[x+y*srcWidth];
2490
-        }
2491
-}
2492
-
2493
-/*template<class T>
2494
-void rotateCCW (const vector<T>& src, vector<T>& dst, uint srcWidth, uint srcHeight)
2495
-{
2496
-        for (uint y=0; y<srcHeight; y++)
2497
-        for (uint x=0; x<srcWidth; x++)
2498
-        {
2499
-                uint dstX=y;
2500
-                uint dstY=srcWidth-x;
2501
-                dst[dstX+dstY*srcHeight]=src[x+y*srcWidth];
2502
-        }
2503
-}
2504
-*/
2505
-void CBitmap::rotateCCW()
2506
-{
2507
-        // Copy the array
2508
-        CObjectVector<uint8> copy=_Data[0];
2509
-
2510
-        switch (PixelFormat)
2511
-        {
2512
-        case RGBA:
2513
-                NLMISC::rotateCCW ((uint32*)&(_Data[0][0]), (uint32*)&(copy[0]), _Width, _Height);
2514
-                break;
2515
-        case Luminance:
2516
-        case Alpha:
2517
-                NLMISC::rotateCCW (&_Data[0][0], &copy[0], _Width, _Height);
2518
-                break;
2519
-        case AlphaLuminance:
2520
-                NLMISC::rotateCCW ((uint16*)&(_Data[0][0]), (uint16*)&(copy[0]), _Width, _Height);;
2521
-                break;
2522
-        default: break;
2523
-        }
2524
-
2525
-        uint32 tmp=_Width;
2526
-        _Width=_Height;
2527
-        _Height=tmp;
2528
-        _Data[0]=copy;
2529
-}
2530
-
2531
-void CBitmap::blit(const CBitmap &src, sint srcX, sint srcY, sint srcWidth, sint srcHeight, sint destX, sint destY)
2532
-{
2533
-        nlassert(PixelFormat == RGBA);
2534
-        nlassert(src.PixelFormat == RGBA);
2535
-        // clip x
2536
-        if (srcX < 0)
2537
-        {
2538
-                srcWidth += srcX;
2539
-                if (srcWidth <= 0) return;
2540
-                destX -= srcX;
2541
-                srcX = 0;
2542
-        }
2543
-        if (srcX + srcWidth > (sint) src.getWidth())
2544
-        {
2545
-                srcWidth = src.getWidth() - srcX;
2546
-                if (srcWidth <= 0) return;
2547
-        }
2548
-        if (destX < 0)
2549
-        {
2550
-                srcWidth += destX;
2551
-                if (srcWidth <= 0) return;
2552
-                srcX -= destX;
2553
-                destX = 0;
2554
-        }
2555
-        if (destX + srcWidth > (sint) getWidth())
2556
-        {
2557
-                srcWidth = getWidth() - destX;
2558
-                if (srcWidth <= 0) return;
2559
-        }
2560
-        // clip y
2561
-        if (srcY < 0)
2562
-        {
2563
-                srcHeight += srcY;
2564
-                if (srcHeight <= 0) return;
2565
-                destY -= srcY;
2566
-                srcY = 0;
2567
-        }
2568
-        if (srcY + srcHeight > (sint) src.getHeight())
2569
-        {
2570
-                srcHeight = src.getHeight() - srcY;
2571
-                if (srcHeight <= 0) return;
2572
-        }
2573
-        if (destY < 0)
2574
-        {
2575
-                srcHeight += destY;
2576
-                if (srcHeight <= 0) return;
2577
-                srcY -= destY;
2578
-                destY = 0;
2579
-        }
2580
-        if (destY + srcHeight > (sint) getHeight())
2581
-        {
2582
-                srcHeight = getHeight() - destY;
2583
-                if (srcHeight <= 0) return;
2584
-        }
2585
-        uint32 *srcPixels = (uint32 *) &src.getPixels()[0];
2586
-        uint32 *srcPtr = &(srcPixels[srcX + srcY * src.getWidth()]);
2587
-        uint32 *srcEndPtr = srcPtr + srcHeight * src.getWidth();
2588
-        uint32 *destPixels = (uint32 *) &getPixels()[0];
2589
-        uint32 *destPtr =         &(destPixels[destX + destY * getWidth()]);
2590
-        while (srcPtr != srcEndPtr)
2591
-        {
2592
-                memcpy(destPtr, srcPtr, sizeof(uint32) * srcWidth);
2593
-                srcPtr += src.getWidth();
2594
-                destPtr += getWidth();
2595
-        }
2596
-
2597
-}
2598
-
2599
-
2600
-bool CBitmap::blit(const CBitmap *src, sint32 x, sint32 y)
2601
-{
2602
-
2603
-        nlassert(this->PixelFormat == src->PixelFormat);
2604
-        if (this->PixelFormat != src->PixelFormat)
2605
-        {
2606
-                return false;
2607
-        }
2608
-
2609
-
2610
-        // check for dxtc use
2611
-
2612
-        const bool useDXTC   =  PixelFormat == DXTC1 || PixelFormat == DXTC1Alpha || PixelFormat == DXTC3 || PixelFormat ==        DXTC5;
2613
-
2614
-        // number of bits for a 4x4 pix block
2615
-        const uint dxtcNumBits  =  PixelFormat == DXTC1 || PixelFormat == DXTC1Alpha ? 64 : 128;
2616
-
2617
-
2618
-        if (useDXTC)
2619
-        {
2620
-                // blit pos must be multiple of 4
2621
-
2622
-                nlassert(! (x & 3 || y & 3) );
2623
-                if (x & 3 || y & 3) return false;
2624
-
2625
-        }
2626
-
2627
-        nlassert(PixelFormat != DonTKnow);
2628
-
2629
-        // the width to copy
2630
-        sint width = src->_Width;
2631
-        // the height to copy
2632
-        sint height = src->_Height;
2633
-
2634
-        uint destStartX, destStartY;
2635
-        uint srcStartX, srcStartY;
2636
-
2637
-
2638
-        // clip against left
2639
-        if (x < 0)
2640
-        {
2641
-                width += x;
2642
-                if (width <= 0) return true;
2643
-                destStartX = 0;
2644
-                srcStartX = -x;
2645
-        }
2646
-        else
2647
-        {
2648
-                destStartX = x;
2649
-                srcStartX = 0;
2650
-        }
2651
-
2652
-        // clip against top
2653
-        if (y < 0)
2654
-        {
2655
-                height += y;
2656
-                if (height <= 0) return true;
2657
-                srcStartY = -y;
2658
-                destStartY = 0;
2659
-        }
2660
-        else
2661
-        {
2662
-                destStartY = y;
2663
-                srcStartY = 0;
2664
-        }
2665
-
2666
-        // clip against right
2667
-        if ((destStartX + width - 1) >= _Width)
2668
-        {
2669
-                width = _Width - destStartX;
2670
-                if (width <= 0) return true;
2671
-        }
2672
-
2673
-        // clip against bottom
2674
-        if ((destStartY + height - 1) >= _Height)
2675
-        {
2676
-                height = _Height - destStartY;
2677
-                if (width <= 0) return true;
2678
-        }
2679
-
2680
-
2681
-        // divide all distance by 4 when using DXTC
2682
-        if (useDXTC)
2683
-        {
2684
-                destStartX >>= 2;
2685
-                destStartY >>= 2;
2686
-                srcStartX >>= 2;
2687
-                srcStartY >>= 2;
2688
-                width >>= 2;
2689
-                height >>= 2;
2690
-        }
2691
-
2692
-
2693
-        // bytes per pixs is for either one pixel or 16 (a 4x4 block in DXTC)
2694
-        const uint bytePerPixs = ( useDXTC ? dxtcNumBits : bitPerPixels[PixelFormat] ) >> 3 /* divide by 8 to get the number of bytes */;
2695
-
2696
-
2697
-        const uint destRealWidth = useDXTC ? (_Width >> 2) : _Width;
2698
-        const uint srcRealWidth = useDXTC ? (src->_Width >> 2) : src->_Width;
2699
-
2700
-
2701
-        // size to go to the next line in the destination
2702
-        const uint destStride = destRealWidth * bytePerPixs;
2703
-
2704
-        // size to go to the next line in the source
2705
-        const uint srcStride = srcRealWidth * bytePerPixs;
2706
-
2707
-        // length in bytes of a line to copy
2708
-        const uint lineLength = width * bytePerPixs;
2709
-
2710
-
2711
-        uint8  *destPos = &(_Data[0][0]) + destStride * destStartY + bytePerPixs * destStartX;
2712
-        const uint8 *srcPos = &(src->_Data[0][0]) + srcStride * srcStartY + bytePerPixs * srcStartX;
2713
-
2714
-        // copy each hline
2715
-        for (sint k = 0; k < height; ++k)
2716
-        {
2717
-                ::memcpy(destPos, srcPos, lineLength);
2718
-                destPos += destStride;
2719
-                srcPos += srcStride;
2720
-        }
2721
-
2722
-
2723
-        return true;
2724
-}
2725
-
2726
-// Private :
2727
-float CBitmap::getColorInterp (float x, float y, float colorInXY00, float colorInXY10, float colorInXY01, float colorInXY11) const
2728
-{
2729
-        float res =        colorInXY00*(1.0f-x)*(1.0f-y) +
2730
-                                colorInXY10*(     x)*(1.0f-y) +
2731
-                                colorInXY01*(1.0f-x)*(     y) +
2732
-                                colorInXY11*(     x)*(     y);
2733
-        clamp (res, 0.0f, 255.0f);
2734
-        return res;
2735
-}
2736
-
2737
-// Public:
2738
-CRGBAF CBitmap::getColor (float x, float y) const
2739
-{
2740
-                if (x < 0.0f) x = 0.0f;
2741
-        if (x > 1.0f) x = 1.0f;
2742
-        if (y < 0.0f) y = 0.0f;
2743
-        if (y > 1.0f) y = 1.0f;
2744
-
2745
-        sint32 nWidth = getWidth(0);
2746
-        sint32 nHeight = getHeight(0);
2747
-
2748
-        if (nWidth == 0 || nHeight == 0) return CRGBAF(0, 0, 0, 0);
2749
-
2750
-        const CObjectVector<uint8> &rBitmap = getPixels(0);
2751
-        sint32 nX[4], nY[4];
2752
-
2753
-        x *= nWidth-1;
2754
-        y *= nHeight-1;
2755
-
2756
-        // Integer part of (x,y)
2757
-        //nX[0] = ((sint32)floor(x-0.5f));
2758
-        //nY[0] = ((sint32)floor(y-0.5f));
2759
-        nX[0] = ((sint32)floor(x));
2760
-        nY[0] = ((sint32)floor(y));
2761
-
2762
-        nX[1] = (nX[0] < (nWidth-1) ? nX[0]+1 : nX[0]);
2763
-        nY[1] = nY[0];
2764
-
2765
-        nX[2] = nX[0];
2766
-        nY[2] = (nY[0] < (nHeight-1) ? nY[0]+1 : nY[0]);
2767
-
2768
-        nX[3] = nX[1];
2769
-        nY[3] = nY[2];
2770
-
2771
-        uint32 i;
2772
-
2773
-        for (i = 0; i < 4; ++i)
2774
-        {
2775
-                nlassert (nX[i] >= 0);
2776
-                nlassert (nY[i] >= 0 );
2777
-                nlassert (nX[i] < nWidth);
2778
-                nlassert (nY[i] < nHeight);
2779
-        }
2780
-
2781
-        // Decimal part of (x,y)
2782
-        x = x - (float)nX[0];
2783
-        y = y - (float)nY[0];
2784
-
2785
-        switch (this->PixelFormat)
2786
-        {
2787
-                case RGBA:
2788
-                case DXTC1:
2789
-                case DXTC1Alpha:
2790
-                case DXTC3:
2791
-                case DXTC5:
2792
-                {
2793
-                        CRGBAF finalVal;
2794
-                        CRGBA val[4];
2795
-
2796
-                        if (this->PixelFormat == RGBA)
2797
-                        {
2798
-                                for (i = 0; i < 4; ++i)
2799
-                                {
2800
-                                        val[i] = CRGBA (rBitmap[(nX[i]+nY[i]*nWidth)*4+0],
2801
-                                                                        rBitmap[(nX[i]+nY[i]*nWidth)*4+1],
2802
-                                                                        rBitmap[(nX[i]+nY[i]*nWidth)*4+2],
2803
-                                                                        rBitmap[(nX[i]+nY[i]*nWidth)*4+3]);
2804
-                                }
2805
-                        }
2806
-                        else
2807
-                        {
2808
-                                // slower version : get from DXT
2809
-                                for (i = 0; i < 4; ++i)
2810
-                                {
2811
-                                        val[i] = getPixelColor(nX[i], nY[i]);
2812
-                                }
2813
-                        }
2814
-
2815
-                        finalVal.R = getColorInterp (x, y, val[0].R, val[1].R, val[2].R, val[3].R);
2816
-                        finalVal.G = getColorInterp (x, y, val[0].G, val[1].G, val[2].G, val[3].G);
2817
-                        finalVal.B = getColorInterp (x, y, val[0].B, val[1].B, val[2].B, val[3].B);
2818
-                        finalVal.A = getColorInterp (x, y, val[0].A, val[1].A, val[2].A, val[3].A);
2819
-                        finalVal /= 255.f;
2820
-
2821
-                        return finalVal;
2822
-                }
2823
-                break;
2824
-                case Alpha:
2825
-                case Luminance:
2826
-                {
2827
-
2828
-                        float finalVal;
2829
-                        float val[4];
2830
-
2831
-                        for (i = 0; i < 4; ++i)
2832
-                                val[i] = rBitmap[(nX[i]+nY[i]*nWidth)];
2833
-
2834
-                        finalVal = getColorInterp (x, y, val[0], val[1], val[2], val[3]);
2835
-                        finalVal /= 255.f;
2836
-
2837
-                        if (this->PixelFormat == Alpha)
2838
-                                return CRGBAF (1.f, 1.f, 1.f, finalVal);
2839
-                        else // Luminance
2840
-                                return CRGBAF (finalVal, finalVal, finalVal, 1.f);
2841
-                }
2842
-                break;
2843
-                default: break;
2844
-        }
2845
-
2846
-        return CRGBAF (0.0f, 0.0f, 0.0f, 0.0f);
2847
-}
2848
-
2849
-// wrap a value inside the given range (for positive value it is like a modulo)
2850
-static inline uint32 wrap(sint32 value, uint32 range)
2851
-{
2852
-        return value >= 0 ? (value % range) : range - 1 - (- value - 1) % range;
2853
-}
2854
-
2855
-
2856
-CRGBAF CBitmap::getColor(float x, float y, bool tileU, bool tileV) const
2857
-{
2858
-        sint32 nWidth = getWidth(0);
2859
-        sint32 nHeight = getHeight(0);
2860
-        if (nWidth == 0 || nHeight == 0) return CRGBAF(0, 0, 0, 0);
2861
-
2862
-        sint32 nX[4], nY[4];
2863
-
2864
-        if (!tileU)
2865
-        {
2866
-                if (x < 0.0f) x = 0.0f;
2867
-                if (x > 1.0f) x = 1.0f;
2868
-                x *= nWidth-1;
2869
-                nX[0] = ((sint32)floor(x));
2870
-                nX[1] = (nX[0] < (nWidth-1) ? nX[0]+1 : nX[0]);
2871
-                nX[2] = nX[0];
2872
-                nX[3] = nX[1];
2873
-                uint32 i;
2874
-                for (i = 0; i < 4; ++i)
2875
-                {
2876
-                        nlassert (nX[i] >= 0);
2877
-                        nlassert (nX[i] < nWidth);
2878
-                }
2879
-        }
2880
-        else
2881
-        {
2882
-                x *= nWidth;
2883
-                nX[0] = wrap((sint32)floorf(x), nWidth);
2884
-                nX[1] = wrap(nX[0] + 1, nWidth);
2885
-                nX[2] = nX[0];
2886
-                nX[3] = nX[1];
2887
-        }
2888
-        //
2889
-        if (!tileV)
2890
-        {
2891
-                if (y < 0.0f) y = 0.0f;
2892
-                if (y > 1.0f) y = 1.0f;
2893
-                y *= nHeight-1;
2894
-                nY[0] = ((sint32)floor(y));
2895
-                nY[1] = nY[0];
2896
-                nY[2] = (nY[0] < (nHeight-1) ? nY[0]+1 : nY[0]);
2897
-                nY[3] = nY[2];
2898
-                uint32 i;
2899
-                for (i = 0; i < 4; ++i)
2900
-                {
2901
-                        nlassert (nY[i] >= 0 );
2902
-                        nlassert (nY[i] < nHeight);
2903
-                }
2904
-        }
2905
-        else
2906
-        {
2907
-                y *= nHeight;
2908
-                nY[0] = wrap((sint32)floorf(y), nHeight);
2909
-                nY[1] = nY[0];
2910
-                nY[2] = wrap(nY[0] + 1, nHeight);
2911
-                nY[3] = nY[2];
2912
-        }
2913
-        // Decimal part of (x,y)
2914
-        x = x - (float)nX[0];
2915
-        y = y - (float)nY[0];
2916
-        const CObjectVector<uint8> &rBitmap = getPixels(0);
2917
-        switch (this->PixelFormat)
2918
-        {
2919
-                case RGBA:
2920
-                case DXTC1:
2921
-                case DXTC1Alpha:
2922
-                case DXTC3:
2923
-                case DXTC5:
2924
-                {
2925
-                        CRGBAF finalVal;
2926
-                        CRGBA val[4];
2927
-
2928
-                        if (this->PixelFormat == RGBA)
2929
-                        {
2930
-                                for (uint32 i = 0; i < 4; ++i)
2931
-                                {
2932
-                                        val[i] = CRGBA (rBitmap[(nX[i]+nY[i]*nWidth)*4+0],
2933
-                                                                        rBitmap[(nX[i]+nY[i]*nWidth)*4+1],
2934
-                                                                        rBitmap[(nX[i]+nY[i]*nWidth)*4+2],
2935
-                                                                        rBitmap[(nX[i]+nY[i]*nWidth)*4+3]);
2936
-                                }
2937
-                        }
2938
-                        else
2939
-                        {
2940
-                                // slower version : get from DXT
2941
-                                for (uint32 i = 0; i < 4; ++i)
2942
-                                {
2943
-                                        val[i] = getPixelColor(nX[i], nY[i]);
2944
-                                }
2945
-                        }
2946
-
2947
-                        finalVal.R = getColorInterp (x, y, val[0].R, val[1].R, val[2].R, val[3].R);
2948
-                        finalVal.G = getColorInterp (x, y, val[0].G, val[1].G, val[2].G, val[3].G);
2949
-                        finalVal.B = getColorInterp (x, y, val[0].B, val[1].B, val[2].B, val[3].B);
2950
-                        finalVal.A = getColorInterp (x, y, val[0].A, val[1].A, val[2].A, val[3].A);
2951
-                        finalVal /= 255.f;
2952
-
2953
-                        return finalVal;
2954
-                }
2955
-                break;
2956
-                case Alpha:
2957
-                case Luminance:
2958
-                {
2959
-
2960
-                        float finalVal;
2961
-                        float val[4];
2962
-
2963
-                        for (uint32 i = 0; i < 4; ++i)
2964
-                                val[i] = rBitmap[(nX[i]+nY[i]*nWidth)];
2965
-
2966
-                        finalVal = getColorInterp (x, y, val[0], val[1], val[2], val[3]);
2967
-                        finalVal /= 255.f;
2968
-
2969
-                        if (this->PixelFormat == Alpha)
2970
-                                return CRGBAF (1.f, 1.f, 1.f, finalVal);
2971
-                        else // Luminance
2972
-                                return CRGBAF (finalVal, finalVal, finalVal, 1.f);
2973
-                }
2974
-                break;
2975
-                default: break;
2976
-        }
2977
-        return CRGBAF (0.0f, 0.0f, 0.0f, 0.0f);
2978
-}
2979
-
2980
-
2981
-
2982
-void        CBitmap::loadSize(NLMISC::IStream &f, uint32 &retWidth, uint32 &retHeight)
2983
-{
2984
-        retWidth= 0;
2985
-        retHeight= 0;
2986
-
2987
-        nlassert(f.isReading());
2988
-
2989
-        // testing if DDS
2990
-        uint32 fileType = 0;
2991
-        f.serial(fileType);
2992
-        if(fileType == DDS_HEADER)
2993
-        {
2994
-                // read entire DDS header.
2995
-                uint32 size = 0;
2996
-                f.serial(size); // size in Bytes of header(without "DDS")
2997
-                uint32 * _DDSSurfaceDesc = new uint32[size];
2998
-                _DDSSurfaceDesc[0]= size;
2999
-
3000
-                for(uint i= 0; i<size/4 - 1; i++)
3001
-                {
3002
-                        f.serial(_DDSSurfaceDesc[i+1]);
3003
-                }
3004
-
3005
-                // flags determines which members of the header structure contain valid data
3006
-                uint32 flags = _DDSSurfaceDesc[1];
3007
-
3008
-                //verify if file have linearsize set
3009
-                if(!(flags & DDSD_LINEARSIZE))
3010
-                {
3011
-                        nlwarning("A DDS doesn't have the flag DDSD_LINEARSIZE");
3012
-                        //delete [] _DDSSurfaceDesc;
3013
-                        //throw EDDSBadHeader();
3014
-                }
3015
-
3016
-                //-------------- extracting and testing useful info
3017
-                retHeight  = _DDSSurfaceDesc[2];
3018
-                retWidth = _DDSSurfaceDesc[3];
3019
-
3020
-                delete [] _DDSSurfaceDesc;
3021
-        }
3022
-        else if(fileType == PNG_HEADER)
3023
-        {
3024
-                // check second part of header
3025
-                f.serialCheck(0x0a1a0a0d);
3026
-
3027
-                uint32 chunkLength = 0;
3028
-                uint32 chunkName = 0;
3029
-                bool eof = false;
3030
-
3031
-                do
3032
-                {
3033
-                        try
3034
-                        {
3035
-                                // length of chunk data
3036
-                                f.serial(chunkLength);
3037
-                                NLMISC_BSWAP32(chunkLength);
3038
-
3039
-                                // name of chunk
3040
-                                f.serial(chunkName);
3041
-
3042
-                                // size of image is a part of IHDR chunk
3043
-                                if (chunkName == NL_MAKEFOURCC('I', 'H', 'D', 'R'))
3044
-                                {
3045
-                                        uint32 val;
3046
-                                        f.serial(val);
3047
-                                        NLMISC_BSWAP32(val);
3048
-                                        retWidth = val;
3049
-
3050
-                                        f.serial(val);
3051
-                                        NLMISC_BSWAP32(val);
3052
-                                        retHeight = val;
3053
-
3054
-                                        break;
3055
-                                }
3056
-                                // end of file chunk
3057
-                                else if (chunkName == NL_MAKEFOURCC('I', 'E', 'N', 'D'))
3058
-                                {
3059
-                                        break;
3060
-                                }
3061
-
3062
-                                // skip data of this chunk and CRC32
3063
-                                f.seek(chunkLength+4, IStream::current);
3064
-                        }
3065
-                        catch(...)
3066
-                        {
3067
-                                eof = true;
3068
-                        }
3069
-                }
3070
-                while(!eof);
3071
-        }
3072
-        else if(fileType == JPG_HEADER)
3073
-        {
3074
-                uint8 blockMarker1 = 0;
3075
-                uint8 blockMarker2 = 0;
3076
-                uint16 blockSize = 0;
3077
-                bool eof = false;
3078
-
3079
-                do
3080
-                {
3081
-                        try
3082
-                        {
3083
-                                // marker of a block
3084
-                                f.serial(blockMarker1);
3085
-
3086
-                                if (blockMarker1 == 0xff)
3087
-                                {
3088
-                                        // marker of a block
3089
-                                        f.serial(blockMarker2);
3090
-
3091
-                                        // 0xff00 is only found in image data
3092
-                                        if (blockMarker2 == 0x00)
3093
-                                        {
3094
-                                                // image data 0xff
3095
-                                        }
3096
-                                        // 0xffda is image data
3097
-                                        else if (blockMarker2 == 0xda)
3098
-                                        {
3099
-                                                // next data is image data which must end with 0xffd9
3100
-                                        }
3101
-                                        // 0xffd9 is the end of an image
3102
-                                        else if (blockMarker2 == 0xd9)
3103
-                                        {
3104
-                                                // real end of file
3105
-                                                break;
3106
-                                        }
3107
-                                        else if (blockMarker2 == 0xdd || blockMarker2 == 0xdc)
3108
-                                        {
3109
-                                                f.seek(4, IStream::current);
3110
-                                        }
3111
-                                        else if (blockMarker2 == 0xdf)
3112
-                                        {
3113
-                                                f.seek(3, IStream::current);
3114
-                                        }
3115
-                                        else if (blockMarker2 >= 0xd0 && blockMarker2 <= 0xd8)
3116
-                                        {
3117
-                                                // no content
3118
-                                        }
3119
-                                        else
3120
-                                        {
3121
-                                                // size of a block
3122
-                                                f.serial(blockSize);
3123
-                                                NLMISC_BSWAP16(blockSize);
3124
-
3125
-                                                // frame marker (which contains image width and height)
3126
-                                                if (blockMarker2 >= 0xc0 && blockMarker2 <= 0xc3)
3127
-                                                {
3128
-                                                        uint8 imagePrecision = 0; // sample precision
3129
-                                                        uint32 imageSize = 0; // width and height
3130
-                                                        f.serial(imagePrecision); 
3131
-                                                        f.serial(imageSize);
3132
-                                                        NLMISC_BSWAP32(imageSize);
3133
-
3134
-                                                        retWidth = imageSize & 0xffff;
3135
-                                                        retHeight = (imageSize & 0xffff0000) >> 16;
3136
-
3137
-                                                        break;
3138
-                                                }
3139
-
3140
-                                                // skip the block
3141
-                                                f.seek(blockSize - 2, IStream::current);
3142
-                                        }
3143
-                                }
3144
-                        }
3145
-                        catch(...)
3146
-                        {
3147
-                                eof = true;
3148
-                        }
3149
-                }
3150
-                while(!eof);
3151
-        }
3152
-        // assuming it's TGA
3153
-        else
3154
-        {
3155
-                if(!f.seek (0, NLMISC::IStream::begin))
3156
-                {
3157
-                        throw ESeekFailed();
3158
-                }
3159
-
3160
-                // Reading header,
3161
-                // To make sure that the bitmap is TGA, we check imageType and imageDepth.
3162
-                uint8        lengthID;
3163
-                uint8        cMapType;
3164
-                uint8        imageType;
3165
-                uint16        tgaOrigin;
3166
-                uint16        length;
3167
-                uint8        depth;
3168
-                uint16        xOrg;
3169
-                uint16        yOrg;
3170
-                uint16        width;
3171
-                uint16        height;
3172
-                uint8        imageDepth;
3173
-                uint8        desc;
3174
-
3175
-                f.serial(lengthID);
3176
-                f.serial(cMapType);
3177
-                f.serial(imageType);
3178
-                if(imageType!=2 && imageType!=3 && imageType!=10 && imageType!=11)
3179
-                {
3180
-                        nlwarning("Invalid TGA format, type %u in not supported (must be 2,3,10 or 11)", imageType);
3181
-                        return;
3182
-                }
3183
-                f.serial(tgaOrigin);
3184
-                f.serial(length);
3185
-                f.serial(depth);
3186
-                f.serial(xOrg);
3187
-                f.serial(yOrg);
3188
-                f.serial(width);
3189
-                f.serial(height);
3190
-                f.serial(imageDepth);
3191
-                if(imageDepth!=8 && imageDepth!=16 && imageDepth!=24 && imageDepth!=32)
3192
-                {
3193
-                        nlwarning("Invalid TGA format, bit depth %u in not supported (must be 8,16,24 or 32)", imageDepth);
3194
-                        return;
3195
-                }
3196
-                f.serial(desc);
3197
-
3198
-                // Ok, we have width and height.
3199
-                retWidth= width;
3200
-                retHeight= height;
3201
-        }
3202
-
3203
-        // reset stream.
3204
-        if(!f.seek (0, NLMISC::IStream::begin))
3205
-        {
3206
-                throw ESeekFailed();
3207
-        }
3208
-}
3209
-
3210
-
3211
-void        CBitmap::loadSize(const std::string &path, uint32 &retWidth, uint32 &retHeight)
3212
-{
3213
-        retWidth= 0;
3214
-        retHeight= 0;
3215
-
3216
-        CIFile                f(path);
3217
-        if(f.open(path))
3218
-                loadSize(f, retWidth, retHeight);
3219
-}
3220
-
3221
-// ***************************************************************************
3222
-void        CBitmap::flipHDXTCBlockColor(uint8 *bitColor, uint32 w)
3223
-{
3224
-        // pack each line in a u32 (NB: the following works either in Little and Big Endian)
3225
-        uint32        bits= *(uint32*)bitColor;
3226
-
3227
-        // swap in X for each line
3228
-        uint32        res;
3229
-        if(w!=2)
3230
-        {
3231
-                res = (bits & 0xC0C0C0C0) >> 6;
3232
-                res+= (bits & 0x30303030) >> 2;
3233
-                res+= (bits & 0x0C0C0C0C) << 2;
3234
-                res+= (bits & 0x03030303) << 6;
3235
-        }
3236
-        // special case where w==2
3237
-        else
3238
-        {
3239
-                res = (bits & 0x0C0C0C0C) >> 2;
3240
-                res+= (bits & 0x03030303) << 2;
3241
-        }
3242
-
3243
-        // copy
3244
-        *((uint32*)bitColor)= res;
3245
-}
3246
-
3247
-// ***************************************************************************
3248
-void        CBitmap::flipVDXTCBlockColor(uint8 *bitColor, uint32 h)
3249
-{
3250
-        // swap just bytes (work either in Little and Big Endian)
3251
-        if(h!=2)
3252
-        {
3253
-                std::swap(bitColor[0], bitColor[3]);
3254
-                std::swap(bitColor[1], bitColor[2]);
3255
-        }
3256
-        // special case where h==2)
3257
-        else
3258
-        {
3259
-                // whatever Little or Big endian, the first byte is the first line, and the second byte is the second line
3260
-                std::swap(bitColor[0], bitColor[1]);
3261
-        }
3262
-}
3263
-
3264
-// ***************************************************************************
3265
-void        CBitmap::flipHDXTCBlockAlpha3(uint8 *blockAlpha, uint32 w)
3266
-{
3267
-#ifdef NL_LITTLE_ENDIAN
3268
-        uint64        bits= *(uint64*)blockAlpha;
3269
-#else
3270
-        uint64        bits= (uint64)blockAlpha[0] + ((uint64)blockAlpha[1]<<8) +
3271
-                ((uint64)blockAlpha[2]<<16) + ((uint64)blockAlpha[3]<<24) +
3272
-                ((uint64)blockAlpha[4]<<32) + ((uint64)blockAlpha[5]<<40) +
3273
-                ((uint64)blockAlpha[6]<<48) + ((uint64)blockAlpha[7]<<56);
3274
-#endif
3275
-
3276
-        // swap in X for each line
3277
-        uint64        res;
3278
-        if(w!=2)
3279
-        {
3280
-                res = (bits & INT64_CONSTANT(0xF000F000F000F000)) >> 12;
3281
-                res+= (bits & INT64_CONSTANT(0x0F000F000F000F00)) >> 4;
3282
-                res+= (bits & INT64_CONSTANT(0x00F000F000F000F0)) << 4;
3283
-                res+= (bits & INT64_CONSTANT(0x000F000F000F000F)) << 12;
3284
-        }
3285
-        // special case where w==2
3286
-        else
3287
-        {
3288
-                res = (bits & INT64_CONSTANT(0x00F000F000F000F0)) >> 4;
3289
-                res+= (bits & INT64_CONSTANT(0x000F000F000F000F)) << 4;
3290
-        }
3291
-
3292
-        // copy
3293
-#ifdef NL_LITTLE_ENDIAN
3294
-        *((uint64*)blockAlpha)= res;
3295
-#else
3296
-        blockAlpha[0]= res & 255;
3297
-        blockAlpha[1]= (res>>8) & 255;
3298
-        blockAlpha[2]= (res>>16) & 255;
3299
-        blockAlpha[3]= (res>>24) & 255;
3300
-        blockAlpha[4]= (res>>32) & 255;
3301
-        blockAlpha[5]= (res>>40) & 255;
3302
-        blockAlpha[6]= (res>>48) & 255;
3303
-        blockAlpha[7]= (res>>56) & 255;
3304
-#endif
3305
-}
3306
-
3307
-// ***************************************************************************
3308
-void        CBitmap::flipVDXTCBlockAlpha3(uint8 *blockAlpha, uint32 h)
3309
-{
3310
-        uint16        *wAlpha= (uint16*)blockAlpha;
3311
-
3312
-        // swap just words (work either in Little and Big Endian)
3313
-        if(h!=2)
3314
-        {
3315
-                std::swap(wAlpha[0], wAlpha[3]);
3316
-                std::swap(wAlpha[1], wAlpha[2]);
3317
-        }
3318
-        // special case where h==2)
3319
-        else
3320
-        {
3321
-                // whatever Little or Big endian, the first byte is the first line, and the second byte is the second line
3322
-                std::swap(wAlpha[0], wAlpha[1]);
3323
-        }
3324
-}
3325
-
3326
-// ***************************************************************************
3327
-void        CBitmap::flipHDXTCBlockAlpha5(uint8 *bitAlpha, uint32 w)
3328
-{
3329
-        // pack into bits. Little Indian in all cases
3330
-        uint64        bits= (uint64)bitAlpha[0] + ((uint64)bitAlpha[1]<<8) +
3331
-                ((uint64)bitAlpha[2]<<16) + ((uint64)bitAlpha[3]<<24) +
3332
-                ((uint64)bitAlpha[4]<<32) + ((uint64)bitAlpha[5]<<40);
3333
-
3334
-        // swap in X for each line
3335
-        uint64        res;
3336
-        if(w!=2)
3337
-        {
3338
-                res = (bits & INT64_CONSTANT(0xE00E00E00E00)) >> 9;
3339
-                res+= (bits & INT64_CONSTANT(0x1C01C01C01C0)) >> 3;
3340
-                res+= (bits & INT64_CONSTANT(0x038038038038)) << 3;
3341
-                res+= (bits & INT64_CONSTANT(0x007007007007)) << 9;
3342
-        }
3343
-        // special case where w==2
3344
-        else
3345
-        {
3346
-                res = (bits & INT64_CONSTANT(0x038038038038)) >> 3;
3347
-                res+= (bits & INT64_CONSTANT(0x007007007007)) << 3;
3348
-        }
3349
-
3350
-        // copy. Little Indian in all cases
3351
-        bitAlpha[0]= uint8(res & 255);
3352
-        bitAlpha[1]= uint8((res>>8) & 255);
3353
-        bitAlpha[2]= uint8((res>>16) & 255);
3354
-        bitAlpha[3]= uint8((res>>24) & 255);
3355
-        bitAlpha[4]= uint8((res>>32) & 255);
3356
-        bitAlpha[5]= uint8((res>>40) & 255);
3357
-}
3358
-
3359
-// ***************************************************************************
3360
-void        CBitmap::flipVDXTCBlockAlpha5(uint8 *bitAlpha, uint32 h)
3361
-{
3362
-        // pack into bits. Little Indian in all cases
3363
-        uint64        bits= (uint64)bitAlpha[0] + ((uint64)bitAlpha[1]<<8) +
3364
-                ((uint64)bitAlpha[2]<<16) + ((uint64)bitAlpha[3]<<24) +
3365
-                ((uint64)bitAlpha[4]<<32) + ((uint64)bitAlpha[5]<<40);
3366
-
3367
-        // swap in Y
3368
-        uint64        res;
3369
-        if(h!=2)
3370
-        {
3371
-                res = (bits & INT64_CONSTANT(0xFFF000000000)) >> 36;
3372
-                res+= (bits & INT64_CONSTANT(0x000FFF000000)) >> 12;
3373
-                res+= (bits & INT64_CONSTANT(0x000000FFF000)) << 12;
3374
-                res+= (bits & INT64_CONSTANT(0x000000000FFF)) << 36;
3375
-        }
3376
-        // special case where h==2
3377
-        else
3378
-        {
3379
-                res = (bits & INT64_CONSTANT(0x000000FFF000)) >> 12;
3380
-                res+= (bits & INT64_CONSTANT(0x000000000FFF)) << 12;
3381
-        }
3382
-
3383
-        // copy. Little Indian in all cases
3384
-        bitAlpha[0]= uint8(res & 255);
3385
-        bitAlpha[1]= uint8((res>>8) & 255);
3386
-        bitAlpha[2]= uint8((res>>16) & 255);
3387
-        bitAlpha[3]= uint8((res>>24) & 255);
3388
-        bitAlpha[4]= uint8((res>>32) & 255);
3389
-        bitAlpha[5]= uint8((res>>40) & 255);
3390
-}
3391
-
3392
-// ***************************************************************************
3393
-void        CBitmap::flipDXTCMipMap(bool vertical, uint mm, uint type)
3394
-{
3395
-        nlassert(mm<MAX_MIPMAP);
3396
-        // size of a DXTC block. 64 bits (2 U32) for DXTC1, else 128 bits (4*U32)
3397
-        uint        blockSizeU32= type==1? 2 : 4;
3398
-        // get size in block
3399
-        sint32        width = getWidth(mm);
3400
-        sint32        height = getHeight(mm);
3401
-        if(width==0 || height==0)
3402
-                return;
3403
-        uint32        wBlock= (width+3)/4;
3404
-        uint32        hBlock= (height+3)/4;
3405
-        // get data ptr and check size.
3406
-        uint32        *data= (uint32*)(&_Data[mm][0]);
3407
-        nlassert(_Data[mm].size()==wBlock*hBlock*blockSizeU32*4);
3408
-
3409
-        // get the offset (in bytes) to the start of color pixels bits
3410
-        uint32        offsetColorBits= type==1? 4 : 12;
3411
-
3412
-        // abort if swap is nonsense
3413
-        if(vertical && height==1)
3414
-                return;
3415
-        if(!vertical && width==1)
3416
-                return;
3417
-
3418
-        // *** First reverse Blocks
3419
-        if(vertical)
3420
-        {
3421
-                // reverse vertical
3422
-                for(uint yBlock=0;yBlock<hBlock/2;yBlock++)
3423
-                {
3424
-                        uint32        *src0= data + (yBlock*wBlock)*blockSizeU32;
3425
-                        uint32        *src1= data + ((hBlock-yBlock-1)*wBlock)*blockSizeU32;
3426
-                        for(uint xBlock=0;xBlock<wBlock;xBlock++, src0+=blockSizeU32, src1+=blockSizeU32)
3427
-                        {
3428
-                                uint32        *block0= src0;
3429
-                                uint32        *block1= src1;
3430
-                                // swap the blocks
3431
-                                for(uint i=0;i<blockSizeU32;i++, block0++, block1++)
3432
-                                {
3433
-                                        std::swap(*block0, *block1);
3434
-                                }
3435
-                        }
3436
-                }
3437
-        }
3438
-        else
3439
-        {
3440
-                // reverse horizontal
3441
-                for(uint yBlock=0;yBlock<hBlock;yBlock++)
3442
-                {
3443
-                        uint32        *src0= data + (yBlock*wBlock)*blockSizeU32;
3444
-                        uint32        *src1= data + (yBlock*wBlock + wBlock-1)*blockSizeU32;
3445
-                        for(uint xBlock=0;xBlock<wBlock/2;xBlock++, src0+=blockSizeU32, src1-=blockSizeU32)
3446
-                        {
3447
-                                uint32        *block0= src0;
3448
-                                uint32        *block1= src1;
3449
-                                // swap the blocks
3450
-                                for(uint i=0;i<blockSizeU32;i++, block0++, block1++)
3451
-                                {
3452
-                                        std::swap(*block0, *block1);
3453
-                                }
3454
-                        }
3455
-                }
3456
-        }
3457
-
3458
-        // *** Then reverse Bits
3459
-        for(uint yBlock=0;yBlock<hBlock;yBlock++)
3460
-        {
3461
-                uint32        *src= data + (yBlock*wBlock)*blockSizeU32;
3462
-                for(uint xBlock=0;xBlock<wBlock;xBlock++, src+=blockSizeU32)
3463
-                {
3464
-                        uint8        *block= (uint8*)src;
3465
-
3466
-                        // flip color bits
3467
-                        if(vertical)        flipVDXTCBlockColor(block+offsetColorBits, height);
3468
-                        else                        flipHDXTCBlockColor(block+offsetColorBits, width);
3469
-
3470
-                        // flip alpha bits if any
3471
-                        if(type==3)
3472
-                        {
3473
-                                // point to the alpha part (16*4 bits)
3474
-                                if(vertical)        flipVDXTCBlockAlpha3(block, height);
3475
-                                else                        flipHDXTCBlockAlpha3(block, width);
3476
-                        }
3477
-                        else if(type==5)
3478
-                        {
3479
-                                // point to the bit alpha part (16*3 bits)
3480
-                                if(vertical)        flipVDXTCBlockAlpha5(block+2, height);
3481
-                                else                        flipHDXTCBlockAlpha5(block+2, width);
3482
-                        }
3483
-                }
3484
-        }
3485
-
3486
-}
3487
-
3488
-
3489
-// ***************************************************************************
3490
-void        CBitmap::flipDXTC(bool vertical)
3491
-{
3492
-        // get type
3493
-        uint        type;
3494
-        if(PixelFormat == DXTC1 || PixelFormat == DXTC1Alpha )
3495
-                type=1;
3496
-        else if(PixelFormat == DXTC3)
3497
-                type=3;
3498
-        else if(PixelFormat == DXTC5)
3499
-                type=5;
3500
-        else
3501
-                return;
3502
-
3503
-        // correct width/height?
3504
-        sint32 nWidth = getWidth(0);
3505
-        sint32 nHeight = getHeight(0);
3506
-        if(!isPowerOf2(nWidth) || !isPowerOf2(nHeight))
3507
-                return;
3508
-
3509
-        // flip all mipmaps
3510
-        for(uint mm=0;mm<_MipMapCount;mm++)
3511
-        {
3512
-                flipDXTCMipMap(vertical, mm, type);
3513
-        }
3514
-}
3515
-
3516
-
3517
-// ***************************************************************************
3518
-void        CBitmap::flipH()
3519
-{
3520
-        if (PixelFormat != RGBA)
3521
-        {
3522
-                // try for DXTC
3523
-                flipDXTC(false);
3524
-
3525
-                // then quit (whether it worked or not)
3526
-                return;
3527
-        }
3528
-
3529
-        sint32 nWidth = getWidth(0);
3530
-        sint32 nHeight = getHeight(0);
3531
-        sint32 i, j;
3532
-        NLMISC::CRGBA *pBitmap = (NLMISC::CRGBA*)&_Data[0][0];
3533
-        bool needRebuild = false;
3534
-        CRGBA temp;
3535
-
3536
-        if(_MipMapCount>1)
3537
-                needRebuild = true;
3538
-        releaseMipMaps();
3539
-
3540
-        for( i = 0; i < nHeight; ++i )
3541
-                for( j = 0; j < nWidth/2; ++j )
3542
-                {
3543
-                        temp = pBitmap[i*nWidth+j];
3544
-                        pBitmap[i*nWidth+j] = pBitmap[i*nWidth+nWidth-j-1];
3545
-                        pBitmap[i*nWidth+nWidth-j-1] = temp;
3546
-                }
3547
-
3548
-        // Rebuilding mipmaps
3549
-        if(needRebuild)
3550
-        {
3551
-                buildMipMaps();
3552
-        }
3553
-}
3554
-
3555
-
3556
-// ***************************************************************************
3557
-void        CBitmap::flipV()
3558
-{
3559
-        if (PixelFormat != RGBA)
3560
-        {
3561
-                // try for DXTC
3562
-                flipDXTC(true);
3563
-
3564
-                // then quit (whether it worked or not)
3565
-                return;
3566
-        }
3567
-
3568
-        sint32 nWidth = getWidth(0);
3569
-        sint32 nHeight = getHeight(0);
3570
-        sint32 i, j;
3571
-        NLMISC::CRGBA *pBitmap = (NLMISC::CRGBA*)&_Data[0][0];
3572
-        bool needRebuild = false;
3573
-        CRGBA temp;
3574
-
3575
-        if(_MipMapCount>1)
3576
-                needRebuild = true;
3577
-        releaseMipMaps();
3578
-
3579
-        for( j = 0; j < nHeight/2; ++j )
3580
-                for( i = 0; i < nWidth; ++i )
3581
-                {
3582
-                        temp = pBitmap[j*nWidth+i];
3583
-                        pBitmap[j*nWidth+i] = pBitmap[(nHeight-j-1)*nWidth+i];
3584
-                        pBitmap[(nHeight-j-1)*nWidth+i] = temp;
3585
-                }
3586
-
3587
-        // Rebuilding mipmaps
3588
-        if(needRebuild)
3589
-        {
3590
-                buildMipMaps();
3591
-        }
3592
-}
3593
-
3594
-
3595
-void        CBitmap::rot90CW()
3596
-{
3597
-        if (PixelFormat != RGBA)
3598
-                return;
3599
-        sint32 nWidth = getWidth(0);
3600
-        sint32 nHeight = getHeight(0);
3601
-        sint32 i, j;
3602
-        NLMISC::CRGBA *pSrcRgba = (NLMISC::CRGBA*)&_Data[0][0];
3603
-        bool needRebuild = false;
3604
-
3605
-        if(_MipMapCount>1)
3606
-                needRebuild = true;
3607
-        releaseMipMaps();
3608
-
3609
-        CObjectVector<uint8> pDestui;
3610
-        pDestui.resize(nWidth*nHeight*4);
3611
-        NLMISC::CRGBA *pDestRgba = (NLMISC::CRGBA*)&pDestui[0];
3612
-
3613
-        for( j = 0; j < nHeight; ++j )
3614
-        for( i = 0; i < nWidth;  ++i )
3615
-                pDestRgba[j+i*nHeight] = pSrcRgba[i+(nHeight-1-j)*nWidth];
3616
-
3617
-        uint32 nTemp = _Width;
3618
-        _Width = _Height;
3619
-        _Height = nTemp;
3620
-
3621
-        NLMISC::contReset(_Data[0]); // free memory
3622
-        _Data[0] =  pDestui;
3623
-        // Rebuilding mipmaps
3624
-        if(needRebuild)
3625
-        {
3626
-                buildMipMaps();
3627
-        }
3628
-}
3629
-
3630
-void        CBitmap::rot90CCW()
3631
-{
3632
-        if (PixelFormat != RGBA)
3633
-                return;
3634
-        sint32 nWidth = getWidth(0);
3635
-        sint32 nHeight = getHeight(0);
3636
-        sint32 i, j;
3637
-        NLMISC::CRGBA *pSrcRgba = (NLMISC::CRGBA*)&_Data[0][0];
3638
-        bool needRebuild = false;
3639
-
3640
-        if(_MipMapCount>1)
3641
-                needRebuild = true;
3642
-        releaseMipMaps();
3643
-
3644
-        CObjectVector<uint8> pDestui;
3645
-        pDestui.resize(nWidth*nHeight*4);
3646
-        NLMISC::CRGBA *pDestRgba = (NLMISC::CRGBA*)&pDestui[0];
3647
-
3648
-        for( j = 0; j < nHeight; ++j )
3649
-        for( i = 0; i < nWidth;  ++i )
3650
-                pDestRgba[j+i*nHeight] = pSrcRgba[nWidth-1-i+j*nWidth];
3651
-
3652
-        uint32 nTemp = _Width;
3653
-        _Width = _Height;
3654
-        _Height = nTemp;
3655
-
3656
-        NLMISC::contReset(_Data[0]); // free memory
3657
-        _Data[0] =  pDestui;
3658
-        // Rebuilding mipmaps
3659
-        if(needRebuild)
3660
-        {
3661
-                buildMipMaps();
3662
-        }
3663
-}
3664
-
3665
-//===========================================================================
3666
-void CBitmap::blend(CBitmap &Bm0, CBitmap &Bm1, uint16 factor, bool inputBitmapIsMutable /*= false*/)
3667
-{
3668
-        nlassert(factor <= 256);
3669
-
3670
-        nlassert(Bm0._Width != 0 && Bm0._Height != 0
3671
-                         && Bm1._Width != 0 && Bm1._Height != 0);
3672
-
3673
-        nlassert(Bm0._Width  == Bm1._Width);        // the bitmap should have the same size
3674
-        nlassert(Bm0._Height == Bm1._Height);
3675
-
3676
-        const CBitmap *nBm0, *nBm1; // pointer to the bitmap that is used for blending, or to a copy is a conversion wa required
3677
-
3678
-        CBitmap cp0, cp1; // these bitmap are copies of Bm1 and Bm0 if a conversion was needed
3679
-
3680
-        if (Bm0.PixelFormat != RGBA)
3681
-        {
3682
-                if (inputBitmapIsMutable)
3683
-                {
3684
-                        Bm0.convertToRGBA();
3685
-                        nBm0 = &Bm0;
3686
-                }
3687
-                else
3688
-                {
3689
-                        cp0 = Bm0;
3690
-                        cp0.convertToRGBA();
3691
-                        nBm0 = &cp0;
3692
-                }
3693
-        }
3694
-        else
3695
-        {
3696
-                nBm0 = &Bm0;
3697
-        }
3698
-
3699
-
3700
-        if (Bm1.PixelFormat != RGBA)
3701
-        {
3702
-                if (inputBitmapIsMutable)
3703
-                {
3704
-                        Bm1.convertToRGBA();
3705
-                        nBm1 = &Bm1;
3706
-                }
3707
-                else
3708
-                {
3709
-                        cp1 = Bm1;
3710
-                        cp1.convertToRGBA();
3711
-                        nBm1 = &cp1;
3712
-                }
3713
-        }
3714
-        else
3715
-        {
3716
-                nBm1 = &Bm1;
3717
-        }
3718
-
3719
-        if (this != nBm0 && this != nBm1)
3720
-        {
3721
-                // if source is the same than the dets, don't resize because this clear the bitmap
3722
-                this->resize(Bm0._Width, Bm0._Height, RGBA);
3723
-        }
3724
-
3725
-        uint numPix = _Width * _Height; // 4 component per pixels
3726
-
3727
-
3728
-        const uint8 *src0                = &(nBm0->_Data[0][0]);
3729
-        const uint8 *src1                = &(nBm1->_Data[0][0]);
3730
-        uint8 *dest                                = &(this->_Data[0][0]);
3731
-
3732
-
3733
-        #if defined(NL_OS_WINDOWS) && !defined(NL_NO_ASM)
3734
-        if (CSystemInfo::hasMMX())
3735
-        {
3736
-                // On a P4 2GHz, with a 256x256 texture, I got the following results :
3737
-                // without mmx : 5.2 ms
3738
-        // with mmx    : 1.7 ms
3739
-                // I'm sure this can be further optimized..
3740
-
3741
-                uint numPixLeft = numPix & 1; // process 2 pixels at once, so special case for odd number
3742
-                numPix = numPix & ~1;
3743
-                // do fast blend with mmx
3744
-                uint64 blendFactor0;
3745
-                uint64 blendFactor1;
3746
-                uint16 *bf0 = (uint16 *) &blendFactor0;
3747
-                uint16 *bf1 = (uint16 *) &blendFactor1;
3748
-                bf0[0] = bf0[1] = bf0[2] = bf0[3] = (1 << 6) * (factor);
3749
-                bf1[0] = bf1[1] = bf1[2] = bf1[3] = (1 << 6) * (256 - factor);
3750
-                __asm
3751
-                {
3752
-                        mov esi, src0
3753
-                        mov eax, src1
3754
-                        mov edi, dest
3755
-                        mov ebx, -8
3756
-                        mov ecx, numPix
3757
-                        shr ecx, 1 // process pixels 2 by 2
3758
-                        movq mm1, blendFactor0
3759
-                        movq mm0, blendFactor1
3760
-
3761
-                myLoop:
3762
-                        pxor mm6, mm6
3763
-                        lea  ebx, [ebx + 8] // points next location
3764
-                        pxor mm7, mm7
3765
-                        movq mm2, [esi + ebx]
3766
-                        movq mm3, [eax + ebx]
3767
-                        // do blend
3768
-                        punpckhbw mm7, mm2  // mm7 contains src0 color 0 in high bytes
3769
-                        punpckhbw mm6, mm3  // mm6 contains src1 color 0 in high bytes
3770
-                        psrl          mm7, 1
3771
-                        pxor mm4, mm4       // mm4 = 0
3772
-                        psrl          mm6, 1
3773
-                        pmulhw mm7, mm0     // src0 = src0 * blendFactor
3774
-                        pxor mm5, mm5       // mm5 = 0
3775
-                        pmulhw mm6, mm1     // src1 = src1 * (1 - blendfactor)
3776
-                        punpcklbw mm4, mm2  // mm4 contains src0 color 1 in high bytes
3777
-                        paddusw mm6, mm7    // mm6 = src0[0] blended with src1[0]
3778
-                        psrl      mm4, 1
3779
-                        psrlw     mm6, 5
3780
-                        punpcklbw mm5, mm3  // mm4 contains src1 color 1 in high bytes
3781
-                        psrl      mm5, 1
3782
-                        pmulhw    mm4, mm0     // src0 = src0 * blendFactor
3783
-                        pmulhw    mm5, mm1     // src1 = src1 * (1 - blendfactor)
3784
-                        paddusw   mm4, mm5    // mm6 = src0[1] blended with src1[1]
3785
-                        psrlw     mm4, 5
3786
-                        // pack result
3787
-                        packuswb  mm4, mm6
3788
-                        dec                  ecx
3789
-                        movq      [edi + ebx], mm4  // store result
3790
-                        jne myLoop
3791
-                        emms
3792
-                }
3793
-                if (numPixLeft)
3794
-                {
3795
-                        // case of odd number of pixels
3796
-                        src0 += 4 * numPix;
3797
-                        src1 += 4 * numPix;
3798
-                        dest += 4 * numPix;
3799
-                        uint blendFact    = (uint) factor;
3800
-                        uint invblendFact = 256 - blendFact;
3801
-                        *dest = (uint8) (((blendFact * *src1)                + (invblendFact * *src0)) >> 8);
3802
-                        *(dest + 1) = (uint8) (((blendFact * *(src1 + 1)) + (invblendFact * *(src0 + 1))) >> 8);
3803
-                        *(dest + 2) = (uint8) (((blendFact * *(src1 + 2)) + (invblendFact * *(src0 + 2))) >> 8);
3804
-                        *(dest + 3)  = (uint8) (((blendFact * *(src1 + 3)) + (invblendFact * *(src0 + 3))) >> 8);
3805
-                }
3806
-        }
3807
-        else
3808
-        #endif //#ifdef NL_OS_WINDOWS
3809
-        {
3810
-                uint8 *endPix                        = dest + (numPix << 2);
3811
-                // no mmx version
3812
-                uint blendFact    = (uint) factor;
3813
-                uint invblendFact = 256 - blendFact;
3814
-                do
3815
-                {
3816
-                        /// blend 4 component at each pass
3817
-                        *dest = (uint8) (((blendFact * *src1)                + (invblendFact * *src0)) >> 8);
3818
-                        *(dest + 1) = (uint8) (((blendFact * *(src1 + 1)) + (invblendFact * *(src0 + 1))) >> 8);
3819
-                        *(dest + 2) = (uint8) (((blendFact * *(src1 + 2)) + (invblendFact * *(src0 + 2))) >> 8);
3820
-                        *(dest + 3)  = (uint8) (((blendFact * *(src1 + 3)) + (invblendFact * *(src0 + 3))) >> 8);
3821
-
3822
-                        src0 = src0 + 4;
3823
-                        src1 = src1 + 4;
3824
-                        dest = dest + 4;
3825
-                }
3826
-                while (dest != endPix);
3827
-        }
3828
-}
3829
-
3830
-
3831
-
3832
-//-----------------------------------------------
3833
-CRGBA CBitmap::getRGBAPixel(sint x, sint y, uint32 numMipMap /*=0*/) const
3834
-{
3835
-        uint w = getWidth(numMipMap);
3836
-        uint h = getHeight(numMipMap);
3837
-        if (w == 0 || (uint) x >= w || (uint) y >= h) return CRGBA::Black; // include negative cases
3838
-        const uint8 *pix = &getPixels(numMipMap)[(x + y * w) << 2];
3839
-        return CRGBA(pix[0], pix[1], pix[2], pix[3]);
3840
-}
3841
-
3842
-//-----------------------------------------------
3843
-CRGBA CBitmap::getDXTCColorFromBlock(const uint8 *block, sint x, sint y)
3844
-{
3845
-        uint16  col0;
3846
-        uint16  col1;
3847
-        memcpy(&col0, block, sizeof(uint16));
3848
-        memcpy(&col1, block + 2, sizeof(uint16));
3849
-        uint        colIndex = (block[4 + (y & 3)] >> ((x & 3) << 1)) & 3;
3850
-        CRGBA   result, c0, c1;
3851
-        if (col0 > col1)
3852
-        {
3853
-                switch(colIndex)
3854
-                {
3855
-                        case 0:
3856
-                                uncompress(col0, result);
3857
-                        break;
3858
-                        case 1:
3859
-                                uncompress(col1, result);
3860
-                        break;
3861
-                        case 2:
3862
-                                uncompress(col0, c0);
3863
-                                uncompress(col1, c1);
3864
-                                result.blendFromui(c0, c1, 85);
3865
-                        break;
3866
-                        case 3:
3867
-                                uncompress(col0, c0);
3868
-                                uncompress(col1, c1);
3869
-                                result.blendFromui(c0, c1, 171);
3870
-                        break;
3871
-                default:
3872
-                        ;
3873
-                }
3874
-                result.A = 255;
3875
-        }
3876
-        else
3877
-        {
3878
-                switch(colIndex)
3879
-                {
3880
-                        case 0:
3881
-                                uncompress(col0, result);
3882
-                                result.A = 255;
3883
-                        break;
3884
-                        case 1:
3885
-                                uncompress(col1, result);
3886
-                                result.A = 255;
3887
-                        break;
3888
-                        case 2:
3889
-                                uncompress(col0, c0);
3890
-                                uncompress(col1, c1);
3891
-                                result.blendFromui(c0, c1, 128);
3892
-                                result.A = 255;
3893
-                        break;
3894
-                        case 3:
3895
-                                result.set(0, 0, 0, 0);
3896
-                        break;
3897
-                }
3898
-        }
3899
-        return result;
3900
-}
3901
-
3902
-//-----------------------------------------------
3903
-CRGBA CBitmap::getDXTC1Texel(sint x, sint y, uint32 numMipMap) const
3904
-{
3905
-        uint w = getWidth(numMipMap);
3906
-        uint h = getHeight(numMipMap);
3907
-        if (w == 0 || h == 0 || (uint) x >= w || (uint) y >= h) return CRGBA::Black; // include negative cases
3908
-        uint numRowBlocks   = std::max((w + 3) >> 2, 1u);
3909
-        const uint8 *pix    = &getPixels(numMipMap)[0];
3910
-        const uint8 *block  = pix + ((y >> 2) * (numRowBlocks << 3) + ((x >> 2) << 3));
3911
-        return getDXTCColorFromBlock(block, x, y);
3912
-}
3913
-
3914
-
3915
-//-----------------------------------------------
3916
-CRGBA CBitmap::getDXTC3Texel(sint x, sint y, uint32 numMipMap) const
3917
-{
3918
-        uint w = getWidth(numMipMap);
3919
-        uint h = getHeight(numMipMap);
3920
-        if (w == 0 || h == 0 || (uint) x >= w || (uint) y >= h) return CRGBA::Black; // include negative cases
3921
-        uint numRowBlocks   = std::max((w + 3) >> 2, 1u);
3922
-        const uint8 *pix    = &getPixels(numMipMap)[0];
3923
-        const uint8 *block  = pix + ((y >> 2) * (numRowBlocks << 4) + ((x >> 2) << 4));
3924
-        CRGBA result = getDXTCColorFromBlock(block + 8, x, y);
3925
-        // get alpha part
3926
-        uint8 alphaByte = block[((y & 3) << 1) + ((x & 2) >> 1)];
3927
-        result.A = (x & 1) ?  (alphaByte & 0xf0) : ((alphaByte & 0x0f) << 4);
3928
-        return result;
3929
-}
3930
-
3931
-//-----------------------------------------------
3932
-CRGBA CBitmap::getDXTC5Texel(sint x, sint y, uint32 numMipMap) const
3933
-{
3934
-        uint w = getWidth(numMipMap);
3935
-        uint h = getHeight(numMipMap);
3936
-        if (w == 0 || h == 0 || (uint) x >= w || (uint) y >= h) return CRGBA::Black; // include negative cases
3937
-        uint numRowBlocks   = std::max((w + 3) >> 2, 1u);
3938
-        const uint8 *pix    = &getPixels(numMipMap)[0];
3939
-        const uint8 *block  = pix + ((y >> 2) * (numRowBlocks << 4) + ((x >> 2) << 4));
3940
-        CRGBA result = getDXTCColorFromBlock(block + 8, x, y);
3941
-        // get alpha part
3942
-        uint8 alpha0 = block[0];
3943
-        uint8 alpha1 = block[1];
3944
-
3945
-        uint alphaIndex;
3946
-        uint tripletIndex = (x & 3) + ((y & 3) << 2);
3947
-        if (tripletIndex < 8)
3948
-        {
3949
-                alphaIndex = (((uint32 &) block[2]) >> (tripletIndex * 3)) & 7;
3950
-        }
3951
-        else
3952
-        {
3953
-                alphaIndex = (((uint32 &) block[5]) >> ((tripletIndex - 8) * 3)) & 7; // we can read a dword there because there are color datas following he alpha datas
3954
-        }
3955
-
3956
-        if (alpha0 > alpha1)
3957
-        {
3958
-                switch (alphaIndex)
3959
-                {
3960
-                        case 0: result.A = alpha0; break;
3961
-                        case 1: result.A = alpha1; break;
3962
-                        case 2: result.A = (uint8) ((6 * (uint) alpha0 + (uint) alpha1) / 7); break;
3963
-                        case 3: result.A = (uint8) ((5 * (uint) alpha0 + 2 * (uint) alpha1) / 7); break;
3964
-                        case 4: result.A = (uint8) ((4 * (uint) alpha0 + 3 * (uint) alpha1) / 7); break;
3965
-                        case 5: result.A = (uint8) ((3 * (uint) alpha0 + 4 * (uint) alpha1) / 7); break;
3966
-                        case 6: result.A = (uint8) ((2 * (uint) alpha0 + 5 * (uint) alpha1) / 7); break;
3967
-                        case 7: result.A = (uint8) (((uint) alpha0 + (uint) 6 * alpha1) / 7); break;
3968
-                }
3969
-        }
3970
-        else
3971
-        {
3972
-                switch (alphaIndex)
3973
-                {
3974
-                        case 0: result.A = alpha0; break;
3975
-                        case 1: result.A = alpha1; break;
3976
-                        case 2: result.A = (uint8) ((4 * (uint) alpha0 + (uint) alpha1) / 5); break;
3977
-                        case 3: result.A = (uint8) ((3 * (uint) alpha0 + 2 * (uint) alpha1) / 5); break;
3978
-                        case 4: result.A = (uint8) ((2 * (uint) alpha0 + 3 * (uint) alpha1) / 5); break;
3979
-                        case 5: result.A = (uint8) (((uint) alpha0 + 4 * (uint) alpha1) / 5); break;
3980
-                        case 6: result.A = 0;        break;
3981
-                        case 7: result.A = 255; break;
3982
-                }
3983
-        }
3984
-        return result;
3985
-}
3986
-
3987
-
3988
-//-----------------------------------------------
3989
-CRGBA CBitmap::getPixelColor(sint x, sint y, uint32 numMipMap /*=0*/) const
3990
-{
3991
-
3992
-        switch (PixelFormat)
3993
-        {
3994
-                case RGBA:
3995
-                        return getRGBAPixel(x, y, numMipMap);
3996
-                case DXTC1:
3997
-                case DXTC1Alpha:
3998
-                        return getDXTC1Texel(x, y, numMipMap);
3999
-                case DXTC3:
4000
-                        return getDXTC3Texel(x, y, numMipMap);
4001
-                case DXTC5:
4002
-                        return getDXTC5Texel(x, y, numMipMap);
4003
-                default:
4004
-                        nlstop;
4005
-                break;
4006
-        }
4007
-        return CRGBA::Black;
4008
-}
4009
-
4010
-
4011
-//-----------------------------------------------
4012
-void CBitmap::swap(CBitmap &other)
4013
-{
4014
-        std::swap(PixelFormat, other.PixelFormat);
4015
-        std::swap(_MipMapCount, other._MipMapCount);
4016
-        std::swap(_LoadGrayscaleAsAlpha, other._LoadGrayscaleAsAlpha);
4017
-        std::swap(_Width, other._Width);
4018
-        std::swap(_Height, other._Height);
4019
-        for(uint k = 0; k < MAX_MIPMAP; ++k)
4020
-        {
4021
-                _Data[k].swap(other._Data[k]);
4022
-        }
4023
-}
4024
-
4025
-//-----------------------------------------------
4026
-void CBitmap::unattachPixels(CObjectVector<uint8> *mipmapDestArray, uint maxMipMapCount /*=MAX_MIPMAP*/)
4027
-{
4028
-        if (!mipmapDestArray) return;
4029
-        uint k;
4030
-        for(k = 0; k < std::min((uint) _MipMapCount, maxMipMapCount); ++k)
4031
-        {
4032
-                mipmapDestArray[k].swap(_Data[k]);
4033
-                _Data[k].clear();
4034
-        }
4035
-        for(; k < _MipMapCount; ++k)
4036
-        {
4037
-                _Data[k].clear();
4038
-        }
4039
-        #ifdef NL_DEBUG
4040
-                // check that remaining mipmaps are empty
4041
-                for(; k < _MipMapCount; ++k)
4042
-                {
4043
-                        nlassert(_Data[k].empty());
4044
-                }
4045
-        #endif
4046
-        _MipMapCount = 1;
4047
-        _Width = 0;
4048
-        _Height = 0;
4049
-        PixelFormat = RGBA;
4050
-        _LoadGrayscaleAsAlpha = true;
4051
-}
4052
-
4053
-
4054
-
4055
-
4056
-void CBitmap::getData(uint8*& extractData)
4057
-{
4058
-
4059
-        uint32 size=0;
4060
-        if(PixelFormat==RGBA)
4061
-                size=_Width*_Height*4;
4062
-        else if(PixelFormat==Alpha||PixelFormat==Luminance)
4063
-                size=_Width*_Height;
4064
-        else
4065
-        {
4066
-                nlstop;
4067
-        }
4068
-
4069
-        for(uint32 pix=0;pix<size;pix++)
4070
-                extractData[pix]=_Data[0][pix];
4071
-
4072
-}
4073
-
4074
-void CBitmap::getDibData(uint8*& extractData)
4075
-{
4076
-
4077
-        uint32 lineSize=0,size;
4078
-        uint8** buf;
4079
-        buf=new uint8*[_Height];
4080
-        if(PixelFormat==RGBA)
4081
-        {
4082
-                lineSize=_Width*4;
4083
-
4084
-
4085
-        }
4086
-        else if(PixelFormat==Alpha||PixelFormat==Luminance)
4087
-        {
4088
-                lineSize=_Width;
4089
-        }
4090
-        else
4091
-        {
4092
-                nlstop;
4093
-        }
4094
-
4095
-        for(sint32 i=_Height-1;i>=0;i--)
4096
-        {
4097
-                buf[_Height-1-i]=&_Data[0][i*lineSize];
4098
-        }
4099
-
4100
-        size=lineSize*_Height;
4101
-
4102
-        for(uint32 line=0;line<_Height;line++)
4103
-        {
4104
-                for(uint32 pix=0;pix<lineSize;pix++)
4105
-                        extractData[line*lineSize+pix]=_Data[0][size-(line+1)*lineSize+pix];
4106
-        }
4107
-        delete []buf;
4108
-
4109
-}
4110
-
4111
-} // NLMISC
4112
-
4113
+// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
4114
+// Copyright (C) 2010  Winch Gate Property Limited
4115
+//
4116
+// This program is free software: you can redistribute it and/or modify
4117
+// it under the terms of the GNU Affero General Public License as
4118
+// published by the Free Software Foundation, either version 3 of the
4119
+// License, or (at your option) any later version.
4120
+//
4121
+// This program is distributed in the hope that it will be useful,
4122
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
4123
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4124
+// GNU Affero General Public License for more details.
4125
+//
4126
+// You should have received a copy of the GNU Affero General Public License
4127
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
4128
+
4129
+#include "stdmisc.h"
4130
+
4131
+#include "nel/misc/bitmap.h"
4132
+#include "nel/misc/stream.h"
4133
+#include "nel/misc/file.h"
4134
+
4135
+// Define this to force all bitmap white (debug)
4136
+// #define NEL_ALL_BITMAP_WHITE
4137
+
4138
+
4139
+using namespace std;
4140
+
4141
+
4142
+namespace NLMISC
4143
+{
4144
+
4145
+struct EDDSBadHeader : public NLMISC::EStream
4146
+{
4147
+        EDDSBadHeader() : EStream( "Bad or unrecognized DDS file header" ) {}
4148
+};
4149
+
4150
+struct ESeekFailed : public NLMISC::EStream
4151
+{
4152
+        ESeekFailed() : EStream( "Seek failed" ) {}
4153
+};
4154
+
4155
+struct EAllocationFailure : public Exception
4156
+{
4157
+        EAllocationFailure() : Exception( "Can't allocate memory" ) {}
4158
+};
4159
+
4160
+void blendFromui(NLMISC::CRGBA &c0, NLMISC::CRGBA &c1, uint coef);
4161
+uint32 blend(uint32 &n0, uint32 &n1, uint32 coef0);
4162
+
4163
+const uint32 CBitmap::bitPerPixels[ModeCount]=
4164
+{
4165
+        32,                // RGBA
4166
+        8,                // Luminance
4167
+        8,                // Alpha
4168
+        16,                // AlphaLuminance
4169
+        4,                // DXTC1
4170
+        4,                // DXTC1Alpha
4171
+        8,                // DXTC3
4172
+        8,                // DXTC5
4173
+        16                // DsDt
4174
+};
4175
+
4176
+const uint32 CBitmap::DXTC1HEADER = NL_MAKEFOURCC('D','X', 'T', '1');
4177
+const uint32 CBitmap::DXTC3HEADER = NL_MAKEFOURCC('D','X', 'T', '3');
4178
+const uint32 CBitmap::DXTC5HEADER = NL_MAKEFOURCC('D','X', 'T', '5');
4179
+
4180
+
4181
+#ifdef NEL_ALL_BITMAP_WHITE
4182
+// Make all the textures white
4183
+void MakeWhite(CBitmap &bitmaps)
4184
+{
4185
+        for (uint i=0; i<bitmaps.getMipMapCount (); i++)
4186
+        {
4187
+                uint size = bitmaps.getPixels (i).size ();
4188
+                bitmaps.getPixels (i).resize (0);
4189
+                bitmaps.getPixels (i).resize (size);
4190
+                bitmaps.getPixels (i).fill (0xff);
4191
+        }
4192
+}
4193
+#endif // NEL_ALL_BITMAP_WHITE
4194
+
4195
+/*-------------------------------------------------------------------*\
4196
+                                                                load
4197
+\*-------------------------------------------------------------------*/
4198
+uint8 CBitmap::load(NLMISC::IStream &f, uint mipMapSkip)
4199
+{
4200
+        /* ***********************************************
4201
+         *        WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
4202
+         *        It can be loaded/called through CAsyncFileManager for instance
4203
+         * ***********************************************/
4204
+
4205
+        nlassert(f.isReading());
4206
+
4207
+        // testing if DDS
4208
+        uint32 fileType = 0;;
4209
+        f.serial(fileType);
4210
+        if(fileType == DDS_HEADER)
4211
+        {
4212
+#ifdef NEL_ALL_BITMAP_WHITE
4213
+                uint8 result = readDDS(f, mipMapSkip);
4214
+                MakeWhite (*this);
4215
+                return result;
4216
+#else // NEL_ALL_BITMAP_WHITE
4217
+                return readDDS(f, mipMapSkip);
4218
+#endif // NEL_ALL_BITMAP_WHITE
4219
+        }
4220
+
4221
+        if (fileType == PNG_HEADER)
4222
+        {
4223
+#ifdef NEL_ALL_BITMAP_WHITE
4224
+                uint8 result = readPNG(f);
4225
+                MakeWhite (*this);
4226
+                return result;
4227
+#else // NEL_ALL_BITMAP_WHITE
4228
+                return readPNG(f);
4229
+#endif // NEL_ALL_BITMAP_WHITE
4230
+        }
4231
+
4232
+#ifdef USE_JPEG
4233
+        if (fileType == JPG_HEADER)
4234
+        {
4235
+#ifdef NEL_ALL_BITMAP_WHITE
4236
+                uint8 result = readJPG(f);
4237
+                MakeWhite (*this);
4238
+                return result;
4239
+#else // NEL_ALL_BITMAP_WHITE
4240
+                return readJPG(f);
4241
+#endif // NEL_ALL_BITMAP_WHITE
4242
+        }
4243
+#endif // USE_JPEG
4244
+        
4245
+        // assuming it's TGA
4246
+        NLMISC::IStream::TSeekOrigin origin= f.begin;
4247
+        if(!f.seek (0, origin))
4248
+        {
4249
+                throw ESeekFailed();
4250
+        }
4251
+
4252
+        // Reading header,
4253
+        // To make sure that the bitmap is TGA, we check imageType and imageDepth.
4254
+        uint8        lengthID;
4255
+        uint8        cMapType;
4256
+        uint8        imageType;
4257
+        uint16        tgaOrigin;
4258
+        uint16        length;
4259
+        uint8        depth;
4260
+        uint16        xOrg;
4261
+        uint16        yOrg;
4262
+        uint16        width;
4263
+        uint16        height;
4264
+        uint8        imageDepth;
4265
+        uint8        desc;
4266
+
4267
+        f.serial(lengthID);
4268
+        f.serial(cMapType);
4269
+        f.serial(imageType);
4270
+        if(imageType!=2 && imageType!=3 && imageType!=10 && imageType!=11) return 0;
4271
+        f.serial(tgaOrigin);
4272
+        f.serial(length);
4273
+        f.serial(depth);
4274
+        f.serial(xOrg);
4275
+        f.serial(yOrg);
4276
+        f.serial(width);
4277
+        f.serial(height);
4278
+        f.serial(imageDepth);
4279
+        if(imageDepth!=8 && imageDepth!=16 && imageDepth!=24 && imageDepth!=32) return 0;
4280
+        f.serial(desc);
4281
+
4282
+        if(!f.seek (0, origin))
4283
+        {
4284
+                throw ESeekFailed();
4285
+        }
4286
+#ifdef NEL_ALL_BITMAP_WHITE
4287
+        uint8 result = readTGA(f);
4288
+        MakeWhite (*this);
4289
+        return result;
4290
+#else // NEL_ALL_BITMAP_WHITE
4291
+        return readTGA(f);
4292
+#endif // NEL_ALL_BITMAP_WHITE
4293
+}
4294
+
4295
+
4296
+/*-------------------------------------------------------------------*\
4297
+                                                                makeDummy
4298
+\*-------------------------------------------------------------------*/
4299
+void        CBitmap::makeDummy()
4300
+{
4301
+        static        const uint8        bitmap[1024]= {
4302
+                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4303
+                0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
4304
+                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
4305
+                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
4306
+                0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,
4307
+                0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,
4308
+                0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,
4309
+                0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,
4310
+                0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,
4311
+                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
4312
+                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
4313
+                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
4314
+                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
4315
+                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
4316
+                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
4317
+                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4318
+                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4319
+                0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
4320
+                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
4321
+                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
4322
+                0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,
4323
+                0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,
4324
+                0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,
4325
+                0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,
4326
+                0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,
4327
+                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
4328
+                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
4329
+                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
4330
+                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
4331
+                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
4332
+                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
4333
+                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4334
+        };
4335
+
4336
+        makeDummyFromBitField(bitmap);
4337
+}
4338
+
4339
+
4340
+/*-------------------------------------------------------------------*\
4341
+                                                                makeDummy
4342
+\*-------------------------------------------------------------------*/
4343
+void        CBitmap::makeNonPowerOf2Dummy()
4344
+{
4345
+        static        const uint8        bitmap[1024]= {
4346
+                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4347
+                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4348
+                0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,
4349
+                0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,
4350
+                0,0,0,0,1,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1,1,0,0,0,0,
4351
+                0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,
4352
+                0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,
4353
+                0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,
4354
+                0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,
4355
+                0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,
4356
+                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
4357
+                0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,
4358
+                0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,
4359
+                0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,
4360
+                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4361
+                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4362
+                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4363
+                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4364
+                0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,
4365
+                0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,
4366
+                0,0,0,0,1,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1,1,0,0,0,0,
4367
+                0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,
4368
+                0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,
4369
+                0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,
4370
+                0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,
4371
+                0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,
4372
+                0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,
4373
+                0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,
4374
+                0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,
4375
+                0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,
4376
+                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4377
+                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4378
+        };
4379
+
4380
+        makeDummyFromBitField(bitmap);
4381
+}
4382
+
4383
+
4384
+/*-------------------------------------------------------------------*\
4385
+                                                makeDummyFromBitField
4386
+\*-------------------------------------------------------------------*/
4387
+void        CBitmap::makeDummyFromBitField(const uint8        bitmap[1024])
4388
+{
4389
+        PixelFormat = RGBA;
4390
+        _MipMapCount = 1;
4391
+        _Width= 32;
4392
+        _Height= 32;
4393
+        _Data[0].resize(_Width*_Height*sizeof(NLMISC::CRGBA));
4394
+        for(sint m=1;m<MAX_MIPMAP;m++)
4395
+                _Data[m].clear();
4396
+        NLMISC::CRGBA        *pix= (NLMISC::CRGBA*)(_Data[0].getPtr());
4397
+
4398
+        for(sint i=0;i<(sint)(_Width*_Height);i++)
4399
+        {
4400
+                if(bitmap[i])
4401
+                        pix[i].set(255,255,255,255);
4402
+                else
4403
+                        pix[i].set(0x80,0x80,0x80,0x40);
4404
+        }
4405
+}
4406
+
4407
+
4408
+
4409
+
4410
+/*-------------------------------------------------------------------*\
4411
+                                                                readDDS
4412
+\*-------------------------------------------------------------------*/
4413
+uint8 CBitmap::readDDS(NLMISC::IStream &f, uint mipMapSkip)
4414
+{
4415
+        /* ***********************************************
4416
+         *        WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
4417
+         *        It can be loaded/called through CAsyncFileManager for instance
4418
+         * ***********************************************/
4419
+
4420
+        //------------------ Reading Header ------------------------
4421
+
4422
+        //-------------- reading entire header
4423
+
4424
+        uint32 size = 0;
4425
+        f.serial(size); // size in Bytes of header(without "DDS")
4426
+         uint32 * _DDSSurfaceDesc = new uint32[size];
4427
+        _DDSSurfaceDesc[0]= size;
4428
+
4429
+#ifdef NL_LITTLE_ENDIAN
4430
+        f.serialBuffer((uint8*)(_DDSSurfaceDesc+1), size-4);
4431
+#else
4432
+        for(uint i= 0; i<size/4 - 1; i++)
4433
+        {
4434
+                f.serial(_DDSSurfaceDesc[i+1]);
4435
+        }
4436
+#endif
4437
+
4438
+        // flags determines which members of the header structure contain valid data
4439
+        uint32 flags = _DDSSurfaceDesc[1];
4440
+
4441
+        //verify if file have linearsize set
4442
+        if(!(flags & DDSD_LINEARSIZE))
4443
+    {
4444
+                nlwarning("A DDS doesn't have the flag DDSD_LINEARSIZE");
4445
+                //delete [] _DDSSurfaceDesc;
4446
+                //throw EDDSBadHeader();
4447
+        }
4448
+
4449
+        //-------------- extracting and testing useful info
4450
+
4451
+        _Height = _DDSSurfaceDesc[2];
4452
+        _Width  = _DDSSurfaceDesc[3];
4453
+        _MipMapCount= (uint8) _DDSSurfaceDesc[6];
4454
+        // If no mipmap.
4455
+        if(_MipMapCount==0)
4456
+                _MipMapCount=1;
4457
+        switch (_DDSSurfaceDesc[20])
4458
+        {
4459
+        case DXTC1HEADER:
4460
+                PixelFormat=DXTC1;
4461
+                break;
4462
+        case DXTC3HEADER:
4463
+                PixelFormat=DXTC3;
4464
+                break;
4465
+        case DXTC5HEADER:
4466
+                PixelFormat=DXTC5;
4467
+                break;
4468
+        }
4469
+
4470
+        flags = _DDSSurfaceDesc[19]; //PixelFormat flags
4471
+
4472
+/*        ace: I changed this code because it's not a way to detect if DXTC1 has a alpha channel or not
4473
+                There's no easy way to detect if the DXTC1 has an alpha channel or not, so, for now, we'll suppose
4474
+                that all DXTC1 has alpha channel per default.
4475
+
4476
+                "There is no flag unfortunately, you need to read each block of DXT1 data, check if one of the colors
4477
+                contains alpha, and check if that color is used in the data.
4478
+                It's not that hard to write, but it IS a pain that it's the only way that I've found to check for alpha."
4479
+                http://www.gamedev.net/community/forums/topic.asp?topic_id=177475
4480
+
4481
+                UPDATE: worst... on linux/opengl, it generates random alpha values
4482
+                if we use alpha dxtc1 by default. So I only to that for windows
4483
+                and leave the old test on linux
4484
+
4485
+                kervala: some used textures don't have an alpha channel and they are
4486
+                (very) bad rendered with this fix        so we have to deactivate it the for moment
4487
+*/
4488
+
4489
+//#ifdef NL_OS_WINDOWS
4490
+//        if(PixelFormat==DXTC1) //AlphaBitDepth
4491
+//        {
4492
+//                PixelFormat = DXTC1Alpha;
4493
+//        }
4494
+//#else
4495
+        if(PixelFormat==DXTC1 && _DDSSurfaceDesc[21]>0) //AlphaBitDepth
4496
+        {
4497
+                PixelFormat = DXTC1Alpha;
4498
+        }
4499
+//#endif
4500
+
4501
+        if(PixelFormat!= DXTC1 && PixelFormat!= DXTC1Alpha && PixelFormat!= DXTC3 && PixelFormat!= DXTC5)
4502
+        {
4503
+                delete [] _DDSSurfaceDesc;
4504
+                throw EDDSBadHeader();
4505
+        }
4506
+
4507
+        // compute the min power of 2 between width and height
4508
+        uint        minSizeLevel= min(_Width, _Height);
4509
+        minSizeLevel= getPowerOf2(minSizeLevel);
4510
+
4511
+        //------------- manage mipMapSkip
4512
+        if(_MipMapCount>1 && mipMapSkip>0 && minSizeLevel>2)
4513
+        {
4514
+                // Keep at least the level where width and height are at least 4.
4515
+                mipMapSkip= min(mipMapSkip, minSizeLevel-2);
4516
+                // skip any mipmap
4517
+                uint        seekSize= 0;
4518
+                while(mipMapSkip>0 && _MipMapCount>1)
4519
+                {
4520
+                        // raise to next multiple of 4
4521
+                        uint32 wtmp= (_Width+3)&(~3);
4522
+                        uint32 htmp= (_Height+3)&(~3);
4523
+                        wtmp= max(wtmp, uint32(4));
4524
+                        htmp= max(htmp, uint32(4));
4525
+
4526
+                        uint32 mipMapSz;
4527
+                        if(PixelFormat==DXTC1 || PixelFormat==DXTC1Alpha)
4528
+                                mipMapSz = wtmp*htmp/2;
4529
+                        else
4530
+                                mipMapSz = wtmp*htmp;
4531
+
4532
+                        // add to how many to skip
4533
+                        seekSize+= mipMapSz;
4534
+
4535
+                        // Size of final bitmap is reduced.
4536
+                        _Width>>=1;
4537
+                        _Height>>=1;
4538
+                        _MipMapCount--;
4539
+                        mipMapSkip--;
4540
+                }
4541
+                // skip data in file
4542
+                if(seekSize>0)
4543
+                {
4544
+                        if(!f.seek(seekSize, IStream::current))
4545
+                        {
4546
+                                delete [] _DDSSurfaceDesc;
4547
+                                throw ESeekFailed();
4548
+                        }
4549
+                }
4550
+
4551
+        }
4552
+
4553
+        //------------- preload all the mipmaps (one serialBuffer() is faster)
4554
+        uint32 w = _Width;
4555
+        uint32 h = _Height;
4556
+        uint32        totalSize= 0;
4557
+
4558
+        uint8        m;
4559
+        for(m= 0; m<_MipMapCount; m++)
4560
+        {
4561
+                // raise to next multiple of 4
4562
+                uint32 wtmp= (w+3)&(~3);
4563
+                uint32 htmp= (h+3)&(~3);
4564
+                wtmp= max(wtmp, uint32(4));
4565
+                htmp= max(htmp, uint32(4));
4566
+
4567
+                uint32 mipMapSz;
4568
+                if(PixelFormat==DXTC1 || PixelFormat==DXTC1Alpha)
4569
+                        mipMapSz = wtmp*htmp/2;
4570
+                else
4571
+                        mipMapSz = wtmp*htmp;
4572
+
4573
+
4574
+                _Data[m].resize(mipMapSz);
4575
+                totalSize+= mipMapSz;
4576
+
4577
+                  w = (w+1)/2;
4578
+                h = (h+1)/2;
4579
+        }
4580
+
4581
+        // Read all the data in one block.
4582
+        vector<uint8>        pixData;
4583
+        pixData.resize(totalSize);
4584
+        f.serialBuffer(&(*pixData.begin()), totalSize);
4585
+
4586
+
4587
+        //------------- reading mipmap levels from pixData
4588
+
4589
+        uint32 pixIndex= 0;
4590
+
4591
+        for(m= 0; m<_MipMapCount; m++)
4592
+        {
4593
+                uint32        mipMapSz= _Data[m].size();
4594
+                memcpy(_Data[m].getPtr(), &(pixData[pixIndex]), mipMapSz);
4595
+                pixIndex+= mipMapSz;
4596
+        }
4597
+
4598
+        //------------- End
4599
+
4600
+        delete [] _DDSSurfaceDesc;
4601
+
4602
+        switch(PixelFormat)
4603
+        {
4604
+                case DXTC1  : return 24;
4605
+                case DXTC1Alpha : return 32;
4606
+                case DXTC3  : return 32;
4607
+                case DXTC5  : return 32;
4608
+                default  : break;
4609
+        }
4610
+
4611
+        return 0;
4612
+}
4613
+
4614
+
4615
+
4616
+
4617
+/*-------------------------------------------------------------------*\
4618
+                                                        convertToDXTC5
4619
+\*-------------------------------------------------------------------*/
4620
+bool CBitmap::convertToDXTC5()
4621
+{
4622
+        /* Yoyo: RGB encoding for DXTC1 and DXTC5/3 are actually different!!
4623
+                DXTC3/5 don't rely on sign of color0>color1 to setup special encoding (ie use a special compression for Black)
4624
+                Since this can arise if the src is DXTC1 , we can't simply compress it into DXTC5 without doing a
4625
+                heavy compression...
4626
+                (the inverse is false: DXTC5 to DXTC1 is possible, with maybe swap color0/color1 and bits).
4627
+        */
4628
+
4629
+        return false;
4630
+
4631
+/*        uint32 i,j;
4632
+
4633
+        if(PixelFormat!=DXTC1) return false;
4634
+
4635
+        for(uint8 m= 0; m<_MipMapCount; m++)
4636
+        {
4637
+                CObjectVector<uint8> dataTmp;
4638
+                dataTmp.resize(2*_Data[m].size());
4639
+                uint        dstId= 0;
4640
+
4641
+                for(i=0; i<_Data[m].size(); i+=8)
4642
+                {
4643
+                        //64 bits alpha
4644
+                        for(j=0; j<8; j++)
4645
+                        {
4646
+                                dataTmp[dstId++]= 255;
4647
+                        }
4648
+
4649
+                        //64 bits RGB
4650
+                        for(j=0; j<8; j++)
4651
+                        {
4652
+                                dataTmp[dstId++]= _Data[m][i+j];
4653
+                        }
4654
+                }
4655
+                _Data[m] = dataTmp;
4656
+        }
4657
+        PixelFormat = DXTC5;
4658
+        return true;
4659
+*/
4660
+}
4661
+
4662
+
4663
+
4664
+/*-------------------------------------------------------------------*\
4665
+                                                        luminanceToRGBA()
4666
+\*-------------------------------------------------------------------*/
4667
+bool CBitmap::luminanceToRGBA()
4668
+{
4669
+        uint32 i;
4670
+
4671
+        if(_Width*_Height == 0)  return false;
4672
+
4673
+        for(uint8 m= 0; m<_MipMapCount; m++)
4674
+        {
4675
+                CObjectVector<uint8> dataTmp;
4676
+                dataTmp.resize(_Data[m].size()*4);
4677
+                uint        dstId= 0;
4678
+
4679
+                for(i=0; i<_Data[m].size(); i++)
4680
+                {
4681
+                        dataTmp[dstId++]= _Data[m][i];
4682
+                        dataTmp[dstId++]= _Data[m][i];
4683
+                        dataTmp[dstId++]= _Data[m][i];
4684
+                        dataTmp[dstId++]= 255;
4685
+                }
4686
+                _Data[m] = dataTmp;
4687
+        }
4688
+        PixelFormat = RGBA;
4689
+        return true;
4690
+}
4691
+
4692
+/*-------------------------------------------------------------------*\
4693
+                                                        alphaToRGBA()
4694
+\*-------------------------------------------------------------------*/
4695
+bool CBitmap::alphaToRGBA()
4696
+{
4697
+        uint32 i;
4698
+
4699
+        if(_Width*_Height == 0)  return false;
4700
+
4701
+        for(uint8 m= 0; m<_MipMapCount; m++)
4702
+        {
4703
+                CObjectVector<uint8> dataTmp;
4704
+                dataTmp.resize(_Data[m].size()*4);
4705
+                uint        dstId= 0;
4706
+
4707
+                for(i=0; i<_Data[m].size(); i++)
4708
+                {
4709
+                        dataTmp[dstId++]= 255;
4710
+                        dataTmp[dstId++]= 255;
4711
+                        dataTmp[dstId++]= 255;
4712
+                        dataTmp[dstId++]= _Data[m][i];
4713
+                }
4714
+                _Data[m] = dataTmp;
4715
+        }
4716
+        PixelFormat = RGBA;
4717
+        return true;
4718
+}
4719
+
4720
+
4721
+/*-------------------------------------------------------------------*\
4722
+                                                        alphaLuminanceToRGBA()
4723
+\*-------------------------------------------------------------------*/
4724
+bool CBitmap::alphaLuminanceToRGBA()
4725
+{
4726
+        uint32 i;
4727
+
4728
+        if(_Width*_Height == 0)  return false;
4729
+
4730
+        for(uint8 m= 0; m<_MipMapCount; m++)
4731
+        {
4732
+                CObjectVector<uint8> dataTmp;
4733
+                dataTmp.resize(_Data[m].size()*2);
4734
+                uint        dstId= 0;
4735
+
4736
+                for(i=0; i<_Data[m].size(); i+=2)
4737
+                {
4738
+                        dataTmp[dstId++]= _Data[m][i];
4739
+                        dataTmp[dstId++]= _Data[m][i];
4740
+                        dataTmp[dstId++]= _Data[m][i];
4741
+                        dataTmp[dstId++]= _Data[m][i+1];
4742
+                }
4743
+                _Data[m] = dataTmp;
4744
+        }
4745
+        PixelFormat = RGBA;
4746
+        return true;
4747
+}
4748
+
4749
+
4750
+
4751
+
4752
+/*-------------------------------------------------------------------*\
4753
+                                                        rgbaToAlphaLuminance
4754
+\*-------------------------------------------------------------------*/
4755
+bool CBitmap::rgbaToAlphaLuminance()
4756
+{
4757
+        uint32 i;
4758
+
4759
+        if(_Width*_Height == 0)  return false;
4760
+
4761
+        for(uint8 m= 0; m<_MipMapCount; m++)
4762
+        {
4763
+                CObjectVector<uint8> dataTmp;
4764
+                dataTmp.resize(_Data[m].size()/2);
4765
+                uint        dstId= 0;
4766
+
4767
+                for(i=0; i<_Data[m].size(); i+=4)
4768
+                {
4769
+                        dataTmp[dstId++]= (_Data[m][i]*77 + _Data[m][i+1]*150 + _Data[m][i+2]*28)/255;
4770
+                        dataTmp[dstId++]= _Data[m][i+3];
4771
+                }
4772
+                NLMISC::contReset(_Data[m]);
4773
+                _Data[m].resize(0);
4774
+                _Data[m] = dataTmp;
4775
+        }
4776
+        PixelFormat = AlphaLuminance;
4777
+        return true;
4778
+}
4779
+
4780
+
4781
+/*-------------------------------------------------------------------*\
4782
+                                                        luminanceToAlphaLuminance
4783
+\*-------------------------------------------------------------------*/
4784
+bool CBitmap::luminanceToAlphaLuminance()
4785
+{
4786
+        uint32 i;
4787
+
4788
+        if(_Width*_Height == 0)  return false;
4789
+
4790
+        for(uint8 m= 0; m<_MipMapCount; m++)
4791
+        {
4792
+                CObjectVector<uint8> dataTmp;
4793
+                dataTmp.resize(_Data[m].size()*2);
4794
+                uint        dstId= 0;
4795
+
4796
+                for(i=0; i<_Data[m].size(); i++)
4797
+                {
4798
+                        dataTmp[dstId++]= _Data[m][i];
4799
+                        dataTmp[dstId++]= 255;
4800
+                }
4801
+                _Data[m] = dataTmp;
4802
+        }
4803
+        PixelFormat = AlphaLuminance;
4804
+        return true;
4805
+}
4806
+
4807
+
4808
+
4809
+/*-------------------------------------------------------------------*\
4810
+                                                        alphaToAlphaLuminance
4811
+\*-------------------------------------------------------------------*/
4812
+bool CBitmap::alphaToAlphaLuminance()
4813
+{
4814
+        uint32 i;
4815
+
4816
+        if(_Width*_Height == 0)  return false;
4817
+
4818
+        for(uint8 m= 0; m<_MipMapCount; m++)
4819
+        {
4820
+                CObjectVector<uint8> dataTmp;
4821
+                dataTmp.resize(_Data[m].size()*2);
4822
+                uint        dstId= 0;
4823
+
4824
+                for(i=0; i<_Data[m].size(); i++)
4825
+                {
4826
+                        dataTmp[dstId++]= 0;
4827
+                        dataTmp[dstId++]= _Data[m][i];
4828
+                }
4829
+                _Data[m] = dataTmp;
4830
+        }
4831
+        PixelFormat = AlphaLuminance;
4832
+        return true;
4833
+}
4834
+
4835
+
4836
+
4837
+/*-------------------------------------------------------------------*\
4838
+                                                        rgbaToLuminance
4839
+\*-------------------------------------------------------------------*/
4840
+bool CBitmap::rgbaToLuminance()
4841
+{
4842
+        uint32 i;
4843
+
4844
+        if(_Width*_Height == 0)  return false;
4845
+
4846
+        for(uint8 m= 0; m<_MipMapCount; m++)
4847
+        {
4848
+                CObjectVector<uint8> dataTmp;
4849
+                dataTmp.resize(_Data[m].size()/4);
4850
+                uint        dstId= 0;
4851
+
4852
+                for(i=0; i<_Data[m].size(); i+=4)
4853
+                {
4854
+                        dataTmp[dstId++]= (_Data[m][i]*77 + _Data[m][i+1]*150 + _Data[m][i+2]*28)/255;
4855
+                }
4856
+                NLMISC::contReset(_Data[m]);
4857
+                _Data[m].resize(0);
4858
+                _Data[m] = dataTmp;
4859
+        }
4860
+        PixelFormat = Luminance;
4861
+        return true;
4862
+}
4863
+
4864
+
4865
+
4866
+/*-------------------------------------------------------------------*\
4867
+                                                        alphaToLuminance
4868
+\*-------------------------------------------------------------------*/
4869
+bool CBitmap::alphaToLuminance()
4870
+{
4871
+        if(_Width*_Height == 0)  return false;
4872
+
4873
+        PixelFormat = Luminance;
4874
+        return true;
4875
+}
4876
+
4877
+
4878
+
4879
+/*-------------------------------------------------------------------*\
4880
+                                                        alphaLuminanceToLuminance
4881
+\*-------------------------------------------------------------------*/
4882
+bool CBitmap::alphaLuminanceToLuminance()
4883
+{
4884
+        uint32 i;
4885
+
4886
+        if(_Width*_Height == 0)  return false;
4887
+
4888
+        for(uint8 m= 0; m<_MipMapCount; m++)
4889
+        {
4890
+                CObjectVector<uint8> dataTmp;
4891
+                dataTmp.resize(_Data[m].size()/2);
4892
+                uint        dstId= 0;
4893
+
4894
+                for(i=0; i<_Data[m].size(); i+=2)
4895
+                {
4896
+                        dataTmp[dstId++]= 0;
4897
+                        dataTmp[dstId++]= 0;
4898
+                        dataTmp[dstId++]= 0;
4899
+                        dataTmp[dstId++]= _Data[m][i];
4900
+                }
4901
+                NLMISC::contReset(_Data[m]);
4902
+                _Data[m].resize(0);
4903
+                _Data[m] = dataTmp;
4904
+        }
4905
+        PixelFormat = Luminance;
4906
+        return true;
4907
+}
4908
+
4909
+
4910
+/*-------------------------------------------------------------------*\
4911
+                                                        rgbaToAlpha
4912
+\*-------------------------------------------------------------------*/
4913
+bool CBitmap::rgbaToAlpha()
4914
+{
4915
+        uint32 i;
4916
+
4917
+        if(_Width*_Height == 0)  return false;
4918
+
4919
+        for(uint8 m= 0; m<_MipMapCount; m++)
4920
+        {
4921
+                CObjectVector<uint8> dataTmp;
4922
+                dataTmp.resize(_Data[m].size()/4);
4923
+                uint        dstId= 0;
4924
+
4925
+                for(i=0; i<_Data[m].size(); i+=4)
4926
+                {
4927
+                        dataTmp[dstId++]= _Data[m][i+3];
4928
+                }
4929
+                NLMISC::contReset(_Data[m]);
4930
+                _Data[m].resize(0);
4931
+                _Data[m] = dataTmp;
4932
+        }
4933
+        PixelFormat = Alpha;
4934
+        return true;
4935
+}
4936
+
4937
+
4938
+/*-------------------------------------------------------------------*\
4939
+                                                        luminanceToAlpha
4940
+\*-------------------------------------------------------------------*/
4941
+bool CBitmap::luminanceToAlpha()
4942
+{
4943
+        uint32 i;
4944
+
4945
+        if(_Width*_Height == 0)  return false;
4946
+
4947
+        for(uint8 m= 0; m<_MipMapCount; m++)
4948
+        {
4949
+                CObjectVector<uint8> dataTmp;
4950
+                dataTmp.resize(_Data[m].size());
4951
+                uint        dstId= 0;
4952
+
4953
+                for(i=0; i<_Data[m].size(); i++)
4954
+                {
4955
+                        dataTmp[dstId++]= _Data[m][i];
4956
+                }
4957
+                _Data[m] = dataTmp;
4958
+        }
4959
+        PixelFormat = Alpha;
4960
+        return true;
4961
+}
4962
+
4963
+
4964
+/*-------------------------------------------------------------------*\
4965
+                                                        alphaLuminanceToAlpha
4966
+\*-------------------------------------------------------------------*/
4967
+bool CBitmap::alphaLuminanceToAlpha()
4968
+{
4969
+        uint32 i;
4970
+
4971
+        if(_Width*_Height == 0)  return false;
4972
+
4973
+        for(uint8 m= 0; m<_MipMapCount; m++)
4974
+        {
4975
+                CObjectVector<uint8> dataTmp;
4976
+                dataTmp.resize(_Data[m].size()/2);
4977
+                uint        dstId= 0;
4978
+
4979
+                for(i=0; i<_Data[m].size(); i+=2)
4980
+                {
4981
+                        dataTmp[dstId++]= _Data[m][i+1];
4982
+                }
4983
+                NLMISC::contReset(_Data[m]);
4984
+                _Data[m].resize(0);
4985
+                _Data[m] = dataTmp;
4986
+        }
4987
+        PixelFormat = Alpha;
4988
+        return true;
4989
+}
4990
+
4991
+
4992
+/*-------------------------------------------------------------------*\
4993
+                                                        convertToLuminance
4994
+\*-------------------------------------------------------------------*/
4995
+bool CBitmap::convertToLuminance()
4996
+{
4997
+        switch(PixelFormat)
4998
+        {
4999
+                case RGBA :
5000
+                        return rgbaToLuminance();
5001
+                        break;
5002
+
5003
+                case Luminance :
5004
+                        return true;
5005
+                        break;
5006
+
5007
+                case Alpha :
5008
+                        return alphaToLuminance();
5009
+                        break;
5010
+
5011
+                case AlphaLuminance :
5012
+                        return alphaLuminanceToLuminance();
5013
+                        break;
5014
+
5015
+                default:
5016
+                        break;
5017
+        }
5018
+        return false;
5019
+}
5020
+
5021
+
5022
+
5023
+/*-------------------------------------------------------------------*\
5024
+                                                        convertToAlpha
5025
+\*-------------------------------------------------------------------*/
5026
+bool CBitmap::convertToAlpha()
5027
+{
5028
+        switch(PixelFormat)
5029
+        {
5030
+                case RGBA :
5031
+                        return rgbaToAlpha();
5032
+                        break;
5033
+
5034
+                case Luminance :
5035
+                        return luminanceToAlpha();
5036
+                        break;
5037
+
5038
+                case Alpha :
5039
+                        return true;
5040
+                        break;
5041
+
5042
+                case AlphaLuminance :
5043
+                        return alphaLuminanceToAlpha();
5044
+                        break;
5045
+
5046
+                default:
5047
+                        break;
5048
+        }
5049
+        return false;
5050
+}
5051
+
5052
+
5053
+
5054
+/*-------------------------------------------------------------------*\
5055
+                                                        convertToAlphaLuminance
5056
+\*-------------------------------------------------------------------*/
5057
+bool CBitmap::convertToAlphaLuminance()
5058
+{
5059
+        switch(PixelFormat)
5060
+        {
5061
+                case RGBA :
5062
+                        return rgbaToAlphaLuminance();
5063
+                        break;
5064
+
5065
+                case Luminance :
5066
+                        return luminanceToAlphaLuminance();
5067
+                        break;
5068
+
5069
+                case Alpha :
5070
+                        return alphaToAlphaLuminance();
5071
+                        break;
5072
+
5073
+                case AlphaLuminance :
5074
+                        return true;
5075
+                        break;
5076
+
5077
+                default:
5078
+                        break;
5079
+        }
5080
+        return false;
5081
+}
5082
+
5083
+
5084
+/*-------------------------------------------------------------------*\
5085
+                                                        convertToRGBA
5086
+\*-------------------------------------------------------------------*/
5087
+bool CBitmap::convertToRGBA()
5088
+{
5089
+        switch(PixelFormat)
5090
+        {
5091
+                case DXTC1 :
5092
+                        return decompressDXT1(false);
5093
+                        break;
5094
+
5095
+                case DXTC1Alpha :
5096
+                        return decompressDXT1(true);
5097
+                        break;
5098
+
5099
+                case DXTC3 :
5100
+                        return decompressDXT3();
5101
+                        break;
5102
+
5103
+                case DXTC5 :
5104
+                        return decompressDXT5();
5105
+                        break;
5106
+
5107
+                case Luminance :
5108
+                        return luminanceToRGBA();
5109
+                        break;
5110
+
5111
+                case Alpha :
5112
+                        return alphaToRGBA();
5113
+                        break;
5114
+
5115
+                case AlphaLuminance :
5116
+                        return alphaLuminanceToRGBA();
5117
+                        break;
5118
+                case RGBA:
5119
+                        return true;
5120
+                break;
5121
+                default:
5122
+                        break;
5123
+        }
5124
+        return false;
5125
+}
5126
+
5127
+
5128
+/*-------------------------------------------------------------------*\
5129
+                                                        convertToType
5130
+\*-------------------------------------------------------------------*/
5131
+bool CBitmap::convertToType(CBitmap::TType type)
5132
+{
5133
+        if(PixelFormat==type) return true;
5134
+
5135
+        switch(type)
5136
+        {
5137
+                case RGBA :
5138
+                        return convertToRGBA();
5139
+                        break;
5140
+
5141
+                case DXTC5 :
5142
+                        return convertToDXTC5();
5143
+                        break;
5144
+
5145
+                case Luminance :
5146
+                        return convertToLuminance();
5147
+                        break;
5148
+
5149
+                case Alpha :
5150
+                        return convertToAlpha();
5151
+                        break;
5152
+
5153
+                case AlphaLuminance :
5154
+                        return convertToAlphaLuminance();
5155
+                        break;
5156
+
5157
+                default:
5158
+                        break;
5159
+        }
5160
+
5161
+        return false;
5162
+}
5163
+
5164
+
5165
+
5166
+
5167
+/*-------------------------------------------------------------------*\
5168
+                                                        decompressDXT1
5169
+\*-------------------------------------------------------------------*/
5170
+bool CBitmap::decompressDXT1(bool alpha)
5171
+{
5172
+        uint32 i,j,k;
5173
+        NLMISC::CRGBA        c[4];
5174
+        CObjectVector<uint8> dataTmp[MAX_MIPMAP];
5175
+
5176
+        uint32 width= _Width;
5177
+        uint32 height= _Height;
5178
+
5179
+        for(uint8 m= 0; m<_MipMapCount; m++)
5180
+        {
5181
+                uint32 wtmp, htmp;
5182
+                if(width<4)
5183
+                        wtmp = 4;
5184
+                else
5185
+                        wtmp = width;
5186
+                if(height < 4)
5187
+                        htmp = 4;
5188
+                else
5189
+                        htmp = height;
5190
+                uint32 mipMapSz = wtmp*htmp*4;
5191
+                dataTmp[m].resize(mipMapSz);
5192
+                if(dataTmp[m].size()<mipMapSz)
5193
+                {
5194
+                        throw EAllocationFailure();
5195
+                }
5196
+                uint32 wBlockCount= wtmp/4;
5197
+
5198
+
5199
+
5200
+                for(i=0; i < _Data[m].size(); i+=8)
5201
+                {
5202
+                        uint16 color0;
5203
+                        uint16 color1;
5204
+                        uint32 bits;
5205
+                        memcpy(&color0,&_Data[m][i],2);
5206
+                        memcpy(&color1,&_Data[m][i+2],2);
5207
+                        memcpy(&bits,&_Data[m][i+4],4);
5208
+
5209
+                        uncompress(color0,c[0]);
5210
+                        uncompress(color1,c[1]);
5211
+
5212
+                        if (alpha)
5213
+                        {
5214
+                                c[0].A= 0;
5215
+                                c[1].A= 0;
5216
+                                c[2].A= 0;
5217
+                                c[3].A= 0;
5218
+                        }
5219
+                        else
5220
+                        {
5221
+                                c[0].A= 255;
5222
+                                c[1].A= 255;
5223
+                                c[2].A= 255;
5224
+                                c[3].A= 255;
5225
+                        }
5226
+
5227
+                        if(color0>color1)
5228
+                        {
5229
+                                c[2].blendFromui(c[0],c[1],85);
5230
+                                if(alpha) c[2].A= 255;
5231
+
5232
+                                c[3].blendFromui(c[0],c[1],171);
5233
+                                if(alpha) c[3].A= 255;
5234
+                        }
5235
+                        else
5236
+                        {
5237
+                                c[2].blendFromui(c[0],c[1],128);
5238
+                                if(alpha) c[2].A= 255;
5239
+
5240
+                                c[3].set(0,0,0,0);
5241
+                        }
5242
+
5243
+                        // computing the 16 RGBA of the block
5244
+
5245
+                        uint32 blockNum= i/8; //(64 bits)
5246
+                        // <previous blocks in above lines> * 4 (rows) * _Width (columns) + 4pix*4rgba*<same line previous blocks>
5247
+                        uint32 pixelsCount= 4*(blockNum/wBlockCount)*wtmp*4 + 4*4*(blockNum%wBlockCount);
5248
+                        for(j=0; j<4; j++)
5249
+                        {
5250
+                                for(k=0; k<4; k++)
5251
+                                {
5252
+                                        dataTmp[m][pixelsCount + j*wtmp*4 + 4*k]= c[bits&3].R;
5253
+                                        dataTmp[m][pixelsCount + j*wtmp*4 + 4*k+1]= c[bits&3].G;
5254
+                                        dataTmp[m][pixelsCount + j*wtmp*4 + 4*k+2]= c[bits&3].B;
5255
+                                        dataTmp[m][pixelsCount + j*wtmp*4 + 4*k+3]= c[bits&3].A;
5256
+                                        bits>>=2;
5257
+                                }
5258
+                        }
5259
+                }
5260
+
5261
+                // Copy result into the mipmap level.
5262
+                if(wtmp==width && htmp==height)
5263
+                {
5264
+                        // For mipmaps level >4 pixels.
5265
+                        _Data[m]= dataTmp[m];
5266
+                }
5267
+                else
5268
+                {
5269
+                        // For last mipmaps, level <4 pixels.
5270
+                        _Data[m].resize(width*height*4);
5271
+                        CRGBA        *src= (CRGBA*)&dataTmp[m][0];
5272
+                        CRGBA        *dst= (CRGBA*)&_Data[m][0];
5273
+                        uint        x,y;
5274
+                        for(y=0;y<height;y++)
5275
+                        {
5276
+                                for(x=0;x<width;x++)
5277
+                                        dst[y*width+x]= src[y*wtmp+x];
5278
+                        }
5279
+                }
5280
+
5281
+                // Next mipmap size.
5282
+                width = (width+1)/2;
5283
+                height = (height+1)/2;
5284
+        }
5285
+        PixelFormat = RGBA;
5286
+        return true;
5287
+}
5288
+
5289
+
5290
+
5291
+
5292
+/*-------------------------------------------------------------------*\
5293
+                                                        decompressDXT3
5294
+\*-------------------------------------------------------------------*/
5295
+bool CBitmap::decompressDXT3()
5296
+{
5297
+        uint32 i,j,k;
5298
+        NLMISC::CRGBA        c[4];
5299
+        CObjectVector<uint8> dataTmp[MAX_MIPMAP];
5300
+
5301
+        uint32 width= _Width;
5302
+        uint32 height= _Height;
5303
+
5304
+        for(uint8 m= 0; m<_MipMapCount; m++)
5305
+        {
5306
+                uint32 wtmp, htmp;
5307
+                if(width<4)
5308
+                        wtmp = 4;
5309
+                else
5310
+                        wtmp = width;
5311
+                if(height < 4)
5312
+                        htmp = 4;
5313
+                else
5314
+                        htmp = height;
5315
+                uint32 mipMapSz = wtmp*htmp*4;
5316
+                dataTmp[m].resize(mipMapSz);
5317
+                if(dataTmp[m].size()<mipMapSz)
5318
+                {
5319
+                        throw EAllocationFailure();
5320
+                }
5321
+                uint32 wBlockCount= wtmp/4;
5322
+
5323
+
5324
+                for(i=0; i < _Data[m].size(); i+=16)
5325
+                {
5326
+                        uint8 alpha[16];
5327
+                        uint64 alphatmp;
5328
+                        memcpy(&alphatmp,&_Data[m][i],8);
5329
+
5330
+                        for(j=0; j<16; j++)
5331
+                        {
5332
+                                uint8        a= (uint8)(alphatmp&15);
5333
+                                // expand to 0-255.
5334
+                                alpha[j]= a+(a<<4);
5335
+                                alphatmp>>=4;
5336
+                        }
5337
+
5338
+
5339
+                        uint16 color0;
5340
+                        uint16 color1;
5341
+                        uint32 bits;
5342
+                        memcpy(&color0,&_Data[m][i+8],2);
5343
+                        memcpy(&color1,&_Data[m][i+10],2);
5344
+                        memcpy(&bits,&_Data[m][i+12],4);
5345
+
5346
+                        uncompress(color0,c[0]);
5347
+                        uncompress(color1,c[1]);
5348
+
5349
+                        // ignore color0>color1 for DXT3 and DXT5.
5350
+                        c[2].blendFromui(c[0],c[1],85);
5351
+                        c[3].blendFromui(c[0],c[1],171);
5352
+
5353
+                        // computing the 16 RGBA of the block
5354
+
5355
+                        uint32 blockNum= i/16; //(128 bits)
5356
+                        // <previous blocks in above lines> * 4 (rows) * wtmp (columns) + 4pix*4rgba*<same line previous blocks>
5357
+                        uint32 pixelsCount= 4*(blockNum/wBlockCount)*wtmp*4 + 4*4*(blockNum%wBlockCount);
5358
+                        for(j=0; j<4; j++)
5359
+                        {
5360
+                                for(k=0; k<4; k++)
5361
+                                {
5362
+                                        dataTmp[m][pixelsCount + j*wtmp*4 + 4*k]= c[bits&3].R;
5363
+                                        dataTmp[m][pixelsCount + j*wtmp*4 + 4*k+1]= c[bits&3].G;
5364
+                                        dataTmp[m][pixelsCount + j*wtmp*4 + 4*k+2]= c[bits&3].B;
5365
+                                        dataTmp[m][pixelsCount + j*wtmp*4 + 4*k+3]= alpha[4*j+k];
5366
+                                        bits>>=2;
5367
+                                }
5368
+                        }
5369
+                }
5370
+
5371
+                // Copy result into the mipmap level.
5372
+                if(wtmp==width && htmp==height)
5373
+                {
5374
+                        // For mipmaps level >4 pixels.
5375
+                        _Data[m]= dataTmp[m];
5376
+                }
5377
+                else
5378
+                {
5379
+                        // For last mipmaps, level <4 pixels.
5380
+                        _Data[m].resize(width*height*4);
5381
+                        CRGBA        *src= (CRGBA*)&dataTmp[m][0];
5382
+                        CRGBA        *dst= (CRGBA*)&_Data[m][0];
5383
+                        uint        x,y;
5384
+                        for(y=0;y<height;y++)
5385
+                        {
5386
+                                for(x=0;x<width;x++)
5387
+                                        dst[y*width+x]= src[y*wtmp+x];
5388
+                        }
5389
+                }
5390
+
5391
+                // Next mipmap size.
5392
+                width = (width+1)/2;
5393
+                height = (height+1)/2;
5394
+        }
5395
+        PixelFormat = RGBA;
5396
+        return true;
5397
+}
5398
+
5399
+
5400
+
5401
+
5402
+/*-------------------------------------------------------------------*\
5403
+                                                        decompressDXT5
5404
+\*-------------------------------------------------------------------*/
5405
+bool CBitmap::decompressDXT5()
5406
+{
5407
+        uint32 i,j,k;
5408
+        NLMISC::CRGBA        c[4];
5409
+        CObjectVector<uint8> dataTmp[MAX_MIPMAP];
5410
+
5411
+        uint32 width= _Width;
5412
+        uint32 height= _Height;
5413
+
5414
+        for(uint8 m= 0; m<_MipMapCount; m++)
5415
+        {
5416
+                uint32 wtmp, htmp;
5417
+                if(width<4)
5418
+                        wtmp = 4;
5419
+                else
5420
+                        wtmp = width;
5421
+                if(height < 4)
5422
+                        htmp = 4;
5423
+                else
5424
+                        htmp = height;
5425
+                uint32 mipMapSz = wtmp*htmp*4;
5426
+                dataTmp[m].resize(mipMapSz);
5427
+                if(dataTmp[m].size()<mipMapSz)
5428
+                {
5429
+                        throw EAllocationFailure();
5430
+                }
5431
+                uint32 wBlockCount= wtmp/4;
5432
+
5433
+
5434
+
5435
+                for(i=0; i < _Data[m].size(); i+=16)
5436
+                {
5437
+                        uint64 bitsAlpha;
5438
+                        memcpy(&bitsAlpha,&_Data[m][i],8);
5439
+                        bitsAlpha>>= 16;
5440
+
5441
+                        uint32 alpha[8];
5442
+                        alpha[0]= _Data[m][i+0];
5443
+                        alpha[1]= _Data[m][i+1];
5444
+
5445
+                        if(alpha[0]>alpha[1])
5446
+                        {
5447
+                                alpha[2]= blend(alpha[0], alpha[1], 219);
5448
+                                alpha[3]= blend(alpha[0], alpha[1], 183);
5449
+                                alpha[4]= blend(alpha[0], alpha[1], 146);
5450
+                                alpha[5]= blend(alpha[0], alpha[1], 110);
5451
+                                alpha[6]= blend(alpha[0], alpha[1], 73);
5452
+                                alpha[7]= blend(alpha[0], alpha[1], 37);
5453
+                        }
5454
+                        else
5455
+                        {
5456
+                                alpha[2]= blend(alpha[0], alpha[1], 204);
5457
+                                alpha[3]= blend(alpha[0], alpha[1], 154);
5458
+                                alpha[4]= blend(alpha[0], alpha[1], 102);
5459
+                                alpha[5]= blend(alpha[0], alpha[1], 51);
5460
+                                alpha[6]= 0;
5461
+                                alpha[7]= 255;
5462
+                        }
5463
+
5464
+                        uint8 codeAlpha[16];
5465
+                        for(j=0; j<16; j++)
5466
+                        {
5467
+                                codeAlpha[j] = (uint8)(bitsAlpha & 7);
5468
+                                bitsAlpha>>=3;
5469
+                        }
5470
+
5471
+
5472
+                        uint16 color0;
5473
+                        uint16 color1;
5474
+                        uint32 bits;
5475
+                        memcpy(&color0,&_Data[m][i+8],2);
5476
+                        memcpy(&color1,&_Data[m][i+10],2);
5477
+                        memcpy(&bits,&_Data[m][i+12],4);
5478
+
5479
+                        uncompress(color0,c[0]);
5480
+                        uncompress(color1,c[1]);
5481
+
5482
+                        // ignore color0>color1 for DXT3 and DXT5.
5483
+                        c[2].blendFromui(c[0],c[1],85);
5484
+                        c[3].blendFromui(c[0],c[1],171);
5485
+
5486
+                        // computing the 16 RGBA of the block
5487
+
5488
+                        uint32 blockNum= i/16; //(128 bits)
5489
+
5490
+                        // <previous blocks in above lines> * 4 (rows) * wtmp (columns) + 4pix*<same line previous blocks>
5491
+                        uint32 pixelsCount= (blockNum/wBlockCount)*wtmp*4 + 4*(blockNum%wBlockCount);
5492
+                        // *sizeof(RGBA)
5493
+                        pixelsCount*=4;
5494
+                        for(j=0; j<4; j++)
5495
+                        {
5496
+                                for(k=0; k<4; k++)
5497
+                                {
5498
+                                        dataTmp[m][pixelsCount + (j*wtmp+k)*4 +0]= c[bits&3].R;
5499
+                                        dataTmp[m][pixelsCount + (j*wtmp+k)*4 +1]= c[bits&3].G;
5500
+                                        dataTmp[m][pixelsCount + (j*wtmp+k)*4 +2]= c[bits&3].B;
5501
+                                        dataTmp[m][pixelsCount + (j*wtmp+k)*4 +3]= (uint8) alpha[codeAlpha[4*j+k]];
5502
+                                        bits>>=2;
5503
+                                }
5504
+                        }
5505
+
5506
+                }
5507
+
5508
+                // Copy result into the mipmap level.
5509
+                if(wtmp==width && htmp==height)
5510
+                {
5511
+                        // For mipmaps level >4 pixels.
5512
+                        _Data[m]= dataTmp[m];
5513
+                }
5514
+                else
5515
+                {
5516
+                        // For last mipmaps, level <4 pixels.
5517
+                        _Data[m].resize(width*height*4);
5518
+                        CRGBA        *src= (CRGBA*)&dataTmp[m][0];
5519
+                        CRGBA        *dst= (CRGBA*)&_Data[m][0];
5520
+                        uint        x,y;
5521
+                        for(y=0;y<height;y++)
5522
+                        {
5523
+                                for(x=0;x<width;x++)
5524
+                                        dst[y*width+x]= src[y*wtmp+x];
5525
+                        }
5526
+                }
5527
+
5528
+                // Next mipmap size.
5529
+                width = (width+1)/2;
5530
+                height = (height+1)/2;
5531
+        }
5532
+        PixelFormat = RGBA;
5533
+        return true;
5534
+
5535
+}
5536
+
5537
+
5538
+
5539
+
5540
+/*-------------------------------------------------------------------*\
5541
+                                                        blend
5542
+\*-------------------------------------------------------------------*/
5543
+uint32 CBitmap::blend(uint32 &n0, uint32 &n1, uint32 coef0)
5544
+{
5545
+        int        a0 = coef0;
5546
+        int        a1 = 256-a0;
5547
+        return ((n0*a0 + n1*a1) >>8);
5548
+}
5549
+
5550
+
5551
+
5552
+/*-------------------------------------------------------------------*\
5553
+                                                        uncompress
5554
+\*-------------------------------------------------------------------*/
5555
+inline void CBitmap::uncompress(uint16 color, NLMISC::CRGBA &r)
5556
+{
5557
+        r.A= 0;
5558
+        r.R= ((color>>11)&31) << 3; r.R+= r.R>>5;
5559
+        r.G= ((color>>5)&63) << 2;  r.G+= r.G>>6;
5560
+        r.B= ((color)&31) << 3;     r.B+= r.B>>5;
5561
+}
5562
+
5563
+
5564
+
5565
+/*-------------------------------------------------------------------*\
5566
+                                                        getWidth
5567
+\*-------------------------------------------------------------------*/
5568
+uint32 CBitmap::getWidth(uint32 mipMap) const
5569
+{
5570
+        if(mipMap==0) return _Width;
5571
+
5572
+        uint32 w = _Width;
5573
+        uint32 h = _Height;
5574
+        uint32 m = 0;
5575
+
5576
+        do
5577
+        {
5578
+                m++;
5579
+                w = (w+1)/2;
5580
+                h = (h+1)/2;
5581
+                if(m==mipMap) return w;
5582
+        }
5583
+        while(w!=1 || h!=1);
5584
+
5585
+        return 0;
5586
+}
5587
+
5588
+
5589
+
5590
+/*-------------------------------------------------------------------*\
5591
+                                                        getHeight
5592
+\*-------------------------------------------------------------------*/
5593
+uint32 CBitmap::getHeight(uint32 mipMap) const
5594
+{
5595
+        if(mipMap==0) return _Height;
5596
+
5597
+        uint32 w = _Width;
5598
+        uint32 h = _Height;
5599
+        uint32 m = 0;
5600
+
5601
+        do
5602
+        {
5603
+                m++;
5604
+                w = (w+1)/2;
5605
+                h = (h+1)/2;
5606
+                if(m==mipMap) return h;
5607
+        }
5608
+        while(w!=1 || h!=1);
5609
+
5610
+        return 0;
5611
+}
5612
+
5613
+
5614
+/*-------------------------------------------------------------------*\
5615
+                                                        getSize
5616
+\*-------------------------------------------------------------------*/
5617
+uint32 CBitmap::getSize(uint32 numMipMap) const
5618
+{
5619
+        return getHeight(numMipMap)*getWidth(numMipMap);
5620
+}
5621
+
5622
+
5623
+
5624
+/*-------------------------------------------------------------------*\
5625
+                                                        buildMipMaps
5626
+\*-------------------------------------------------------------------*/
5627
+void CBitmap::buildMipMaps()
5628
+{
5629
+        uint32 i,j;
5630
+
5631
+        if(PixelFormat!=RGBA) return;
5632
+        if(_MipMapCount!=1) return;
5633
+        if(!NLMISC::isPowerOf2(_Width)) return;
5634
+        if(!NLMISC::isPowerOf2(_Height)) return;
5635
+
5636
+        uint32 w = _Width;
5637
+        uint32 h = _Height;
5638
+
5639
+        while(w>1 || h>1)
5640
+        {
5641
+                uint32 precw = w;
5642
+                uint32 prech = h;
5643
+                w = (w+1)/2;
5644
+                h = (h+1)/2;
5645
+                uint32        mulw= precw/w;
5646
+                uint32        mulh= prech/h;
5647
+
5648
+                _Data[_MipMapCount].resize(w*h*4);
5649
+
5650
+                NLMISC::CRGBA *pRgba = (NLMISC::CRGBA*)&_Data[_MipMapCount][0];
5651
+                NLMISC::CRGBA *pRgbaPrev = (NLMISC::CRGBA*)&_Data[_MipMapCount-1][0];
5652
+                for(i=0; i<h; i++)
5653
+                {
5654
+                        sint        i0= mulh*i;
5655
+                        sint        i1= mulh*i+1;
5656
+                        if(mulh==1)
5657
+                                i1=i0;
5658
+                        i0*=precw;
5659
+                        i1*=precw;
5660
+                        for(j=0; j<w; j++)
5661
+                        {
5662
+                                sint        j0= mulw*j;
5663
+                                sint        j1= mulw*j+1;
5664
+                                if(mulw==1)
5665
+                                        j1=j0;
5666
+                                CRGBA        &c0= pRgbaPrev[i0+j0];
5667
+                                CRGBA        &c1= pRgbaPrev[i0+j1];
5668
+                                CRGBA        &c2= pRgbaPrev[i1+j0];
5669
+                                CRGBA        &c3= pRgbaPrev[i1+j1];
5670
+                                pRgba[i*w + j].R = (c0.R +
5671
+                                                                        c1.R +
5672
+                                                                        c2.R +
5673
+                                                                        c3.R + 2 ) /4;
5674
+                                pRgba[i*w + j].G = (c0.G +
5675
+                                                                        c1.G +
5676
+                                                                        c2.G +
5677
+                                                                        c3.G + 2 ) /4;
5678
+                                pRgba[i*w + j].B = (c0.B +
5679
+                                                                        c1.B +
5680
+                                                                        c2.B +
5681
+                                                                        c3.B + 2 ) /4;
5682
+                                pRgba[i*w + j].A = (c0.A +
5683
+                                                                        c1.A +
5684
+                                                                        c2.A +
5685
+                                                                        c3.A + 2 ) /4;
5686
+                        }
5687
+                }
5688
+
5689
+                _MipMapCount++;
5690
+        }
5691
+}
5692
+
5693
+/*-------------------------------------------------------------------*\
5694
+                                                        computeNeededMipMapCount
5695
+\*-------------------------------------------------------------------*/
5696
+uint32 CBitmap::computeNeededMipMapCount() const
5697
+{
5698
+        if(_MipMapCount == 0) return 0;
5699
+        if(!NLMISC::isPowerOf2(_Width)) return 1;
5700
+        if(!NLMISC::isPowerOf2(_Height)) return 1;
5701
+
5702
+        uint32 mipMapCount = 1;
5703
+        uint32 w = _Width;
5704
+        uint32 h = _Height;
5705
+
5706
+        while(w>1 || h>1)
5707
+        {
5708
+                w = (w+1)/2;
5709
+                h = (h+1)/2;
5710
+                ++mipMapCount;
5711
+        }
5712
+        return mipMapCount;
5713
+}
5714
+
5715
+/*-------------------------------------------------------------------*\
5716
+                                                        releaseMipMaps
5717
+\*-------------------------------------------------------------------*/
5718
+void CBitmap::releaseMipMaps()
5719
+{
5720
+        if(_MipMapCount<=1) return;
5721
+
5722
+        _MipMapCount=1;
5723
+        for(sint i=1;i<MAX_MIPMAP;i++)
5724
+        {
5725
+                NLMISC::contReset(_Data[i]);
5726
+        }
5727
+}
5728
+
5729
+/*-------------------------------------------------------------------*\
5730
+                                                        resample
5731
+\*-------------------------------------------------------------------*/
5732
+void CBitmap::resample(sint32 nNewWidth, sint32 nNewHeight)
5733
+{
5734
+        nlassert(PixelFormat == RGBA);
5735
+        bool needRebuild = false;
5736
+
5737
+        // Deleting mipmaps
5738
+        //logResample("Resample: 10");
5739
+        if(_MipMapCount>1)
5740
+                needRebuild = true;
5741
+        releaseMipMaps();
5742
+        //logResample("Resample: 20");
5743
+
5744
+        if(nNewWidth==0 || nNewHeight==0)
5745
+        {
5746
+                _Width = _Height = 0;
5747
+                //logResample("Resample: 25");
5748
+                return;
5749
+        }
5750
+
5751
+        //logResample("Resample: 30");
5752
+        CObjectVector<uint8> pDestui;
5753
+        pDestui.resize(nNewWidth*nNewHeight*4);
5754
+        //logResample("Resample: 40");
5755
+        NLMISC::CRGBA *pDestRgba = (NLMISC::CRGBA*)&pDestui[0];
5756
+        //logResample("Resample: 50");
5757
+
5758
+        resamplePicture32 ((NLMISC::CRGBA*)&_Data[0][0], pDestRgba, _Width, _Height, nNewWidth, nNewHeight);
5759
+        //logResample("Resample: 60");
5760
+
5761
+        NLMISC::contReset(_Data[0]); // free memory
5762
+        //logResample("Resample: 70");
5763
+
5764
+        _Data[0] =  pDestui;
5765
+        //logResample("Resample: 80");
5766
+        _Width= nNewWidth;
5767
+        _Height= nNewHeight;
5768
+
5769
+        // Rebuilding mipmaps
5770
+        //logResample("Resample: 90");
5771
+        if(needRebuild)
5772
+        {
5773
+                buildMipMaps();
5774
+                //logResample("Resample: 95");
5775
+        }
5776
+        //logResample("Resample: 100");
5777
+}
5778
+
5779
+
5780
+/*-------------------------------------------------------------------*\
5781
+                                                        resize
5782
+\*-------------------------------------------------------------------*/
5783
+void CBitmap::resize (sint32 nNewWidth, sint32 nNewHeight, TType newType, bool resetTo0)
5784
+{
5785
+        // Deleting mipmaps
5786
+        releaseMipMaps();
5787
+
5788
+        // Change type of bitmap ?
5789
+        if (newType!=DonTKnow)
5790
+                PixelFormat=newType;
5791
+
5792
+        _Width = nNewWidth;
5793
+        _Height = nNewHeight;
5794
+
5795
+        // resize the level 0 only.
5796
+        resizeMipMap(0, nNewWidth, nNewHeight, resetTo0);
5797
+}
5798
+
5799
+
5800
+/*-------------------------------------------------------------------*\
5801
+                                                        resizeMipMap
5802
+\*-------------------------------------------------------------------*/
5803
+void CBitmap::resizeMipMap (uint32 numMipMap, sint32 nNewWidth, sint32 nNewHeight, bool resetTo0)
5804
+{
5805
+        nlassert(numMipMap<MAX_MIPMAP);
5806
+
5807
+        // free memory
5808
+        NLMISC::contReset(_Data[numMipMap]);
5809
+
5810
+        // DXTC compressed??
5811
+        //bool        isDXTC= PixelFormat==DXTC1 || PixelFormat==DXTC1Alpha || PixelFormat==DXTC3 || PixelFormat==DXTC5;
5812
+        // if yes, must round up width and height to 4, for allocation
5813
+        nNewWidth= 4*((nNewWidth+3)/4);
5814
+        nNewHeight= 4*((nNewHeight+3)/4);
5815
+
5816
+        // resize the buffer
5817
+        _Data[numMipMap].resize (((uint32)(nNewWidth*nNewHeight)*bitPerPixels[PixelFormat])/8);
5818
+
5819
+        // Fill 0?
5820
+        if( resetTo0 )
5821
+                _Data[numMipMap].fill(0);
5822
+}
5823
+
5824
+
5825
+/*-------------------------------------------------------------------*\
5826
+                                                        reset
5827
+\*-------------------------------------------------------------------*/
5828
+void CBitmap::setMipMapCount(uint32 mmc)
5829
+{
5830
+        _MipMapCount= uint8(mmc);
5831
+}
5832
+
5833
+
5834
+/*-------------------------------------------------------------------*\
5835
+                                                        reset
5836
+\*-------------------------------------------------------------------*/
5837
+void CBitmap::reset(TType type)
5838
+{
5839
+        for(uint i=0; i<_MipMapCount; i++)
5840
+        {
5841
+                NLMISC::contReset(_Data[i]);
5842
+                _Data[i].resize(0);
5843
+        }
5844
+        _Width = _Height = 0;
5845
+        _MipMapCount= 1;
5846
+
5847
+        // Change pixel format
5848
+        PixelFormat=type;
5849
+}
5850
+
5851
+
5852
+
5853
+/*-------------------------------------------------------------------*\
5854
+                                                        resamplePicture32
5855
+\*-------------------------------------------------------------------*/
5856
+void CBitmap::resamplePicture32 (const NLMISC::CRGBA *pSrc, NLMISC::CRGBA *pDest,
5857
+                                                                 sint32 nSrcWidth, sint32 nSrcHeight,
5858
+                                                                 sint32 nDestWidth, sint32 nDestHeight)
5859
+{
5860
+        //logResample("RP32: 0 pSrc=%p pDest=%p, Src=%d x %d Dest=%d x %d", pSrc, pDest, nSrcWidth, nSrcHeight, nDestWidth, nDestHeight);
5861
+        if ((nSrcWidth<=0)||(nSrcHeight<=0)||(nDestHeight<=0)||(nDestHeight<=0))
5862
+                return;
5863
+
5864
+        // If we're reducing it by 2, call the fast resample
5865
+        if (((nSrcHeight / 2) == nDestHeight) && ((nSrcHeight % 2) == 0) &&
5866
+                ((nSrcWidth  / 2) == nDestWidth)  && ((nSrcWidth  % 2) == 0))
5867
+        {
5868
+                resamplePicture32Fast(pSrc, pDest, nSrcWidth, nSrcHeight, nDestWidth, nDestHeight);
5869
+                return;
5870
+        }
5871
+
5872
+        bool bXMag=(nDestWidth>=nSrcWidth);
5873
+        bool bYMag=(nDestHeight>=nSrcHeight);
5874
+        bool bXEq=(nDestWidth==nSrcWidth);
5875
+        bool bYEq=(nDestHeight==nSrcHeight);
5876
+        std::vector<NLMISC::CRGBAF> pIterm (nDestWidth*nSrcHeight);
5877
+
5878
+        if (bXMag)
5879
+        {
5880
+                float fXdelta=(float)(nSrcWidth)/(float)(nDestWidth);
5881
+                NLMISC::CRGBAF *pItermPtr=&*pIterm.begin();
5882
+                sint32 nY;
5883
+                for (nY=0; nY<nSrcHeight; nY++)
5884
+                {
5885
+                        const NLMISC::CRGBA *pSrcLine=pSrc;
5886
+                        float fX=0.f;
5887
+                        sint32 nX;
5888
+                        for (nX=0; nX<nDestWidth; nX++)
5889
+                        {
5890
+                                float fVirgule=fX-(float)floor(fX);
5891
+                                nlassert (fVirgule>=0.f);
5892
+                                NLMISC::CRGBAF vColor;
5893
+                                if (fVirgule>=0.5f)
5894
+                                {
5895
+                                        if (fX<(float)(nSrcWidth-1))
5896
+                                        {
5897
+                                                NLMISC::CRGBAF vColor1 (pSrcLine[(sint32)floor(fX)]);
5898
+                                                NLMISC::CRGBAF vColor2 (pSrcLine[(sint32)floor(fX)+1]);
5899
+                                                vColor=vColor1*(1.5f-fVirgule)+vColor2*(fVirgule-0.5f);
5900
+                                        }
5901
+                                        else
5902
+                                                vColor=NLMISC::CRGBAF (pSrcLine[(sint32)floor(fX)]);
5903
+                                }
5904
+                                else
5905
+                                {
5906
+                                        if (fX>=1.f)
5907
+                                        {
5908
+                                                NLMISC::CRGBAF vColor1 (pSrcLine[(sint32)floor(fX)]);
5909
+                                                NLMISC::CRGBAF vColor2 (pSrcLine[(sint32)floor(fX)-1]);
5910
+                                                vColor=vColor1*(0.5f+fVirgule)+vColor2*(0.5f-fVirgule);
5911
+                                        }
5912
+                                        else
5913
+                                                vColor=NLMISC::CRGBAF (pSrcLine[(sint32)floor(fX)]);
5914
+                                }
5915
+                                *(pItermPtr++)=vColor;
5916
+                                fX+=fXdelta;
5917
+                        }
5918
+                        pSrc+=nSrcWidth;
5919
+                }
5920
+        }
5921
+        else if (bXEq)
5922
+        {
5923
+                NLMISC::CRGBAF *pItermPtr=&*pIterm.begin();
5924
+                for (sint32 nY=0; nY<nSrcHeight; nY++)
5925
+                {
5926
+                        const NLMISC::CRGBA *pSrcLine=pSrc;
5927
+                        sint32 nX;
5928
+                        for (nX=0; nX<nDestWidth; nX++)
5929
+                                *(pItermPtr++)=NLMISC::CRGBAF (pSrcLine[nX]);
5930
+                        pSrc+=nSrcWidth;
5931
+                }
5932
+        }
5933
+        else
5934
+        {
5935
+                double fXdelta=(double)(nSrcWidth)/(double)(nDestWidth);
5936
+                nlassert (fXdelta>1.f);
5937
+                NLMISC::CRGBAF *pItermPtr=&*pIterm.begin();
5938
+                sint32 nY;
5939
+                for (nY=0; nY<nSrcHeight; nY++)
5940
+                {
5941
+                        const NLMISC::CRGBA *pSrcLine=pSrc;
5942
+                        double fX=0.f;
5943
+                        sint32 nX;
5944
+                        for (nX=0; nX<nDestWidth; nX++)
5945
+                        {
5946
+                                NLMISC::CRGBAF vColor (0.f, 0.f, 0.f, 0.f);
5947
+                                double fFinal=fX+fXdelta;
5948
+                                while ((fX<fFinal)&&((sint32)fX!=nSrcWidth))
5949
+                                {
5950
+                                        double fNext=(double)floor (fX)+1.f;
5951
+                                        if (fNext>fFinal)
5952
+                                                fNext=fFinal;
5953
+                                        vColor+=((float)(fNext-fX))*NLMISC::CRGBAF (pSrcLine[(sint32)floor(fX)]);
5954
+                                        fX=fNext;
5955
+                                }
5956
+                                fX = fFinal; // ensure fX == fFinal
5957
+                                vColor/=(float)fXdelta;
5958
+                                *(pItermPtr++)=vColor;
5959
+                        }
5960
+                        pSrc+=nSrcWidth;
5961
+                }
5962
+        }
5963
+
5964
+        if (bYMag)
5965
+        {
5966
+                double fYdelta=(double)(nSrcHeight)/(double)(nDestHeight);
5967
+                sint32 nX;
5968
+                for (nX=0; nX<nDestWidth; nX++)
5969
+                {
5970
+                        double fY=0.f;
5971
+                        sint32 nY;
5972
+                        for (nY=0; nY<nDestHeight; nY++)
5973
+                        {
5974
+                                double fVirgule=fY-(double)floor(fY);
5975
+                                nlassert (fVirgule>=0.f);
5976
+                                NLMISC::CRGBAF vColor;
5977
+                                if (fVirgule>=0.5f)
5978
+                                {
5979
+                                        if (fY<(double)(nSrcHeight-1))
5980
+                                        {
5981
+                                                NLMISC::CRGBAF vColor1=pIterm[((sint32)floor(fY))*nDestWidth+nX];
5982
+                                                NLMISC::CRGBAF vColor2=pIterm[(((sint32)floor(fY))+1)*nDestWidth+nX];
5983
+                                                vColor=vColor1*(1.5f-(float)fVirgule)+vColor2*((float)fVirgule-0.5f);
5984
+                                        }
5985
+                                        else
5986
+                                                vColor=pIterm[((sint32)floor(fY))*nDestWidth+nX];
5987
+                                }
5988
+                                else
5989
+                                {
5990
+                                        if (fY>=1.f)
5991
+                                        {
5992
+                                                NLMISC::CRGBAF vColor1=pIterm[((sint32)floor(fY))*nDestWidth+nX];
5993
+                                                NLMISC::CRGBAF vColor2=pIterm[(((sint32)floor(fY))-1)*nDestWidth+nX];
5994
+                                                vColor=vColor1*(0.5f+(float)fVirgule)+vColor2*(0.5f-(float)fVirgule);
5995
+                                        }
5996
+                                        else
5997
+                                                vColor=pIterm[((sint32)floor(fY))*nDestWidth+nX];
5998
+                                }
5999
+                                pDest[nX+nY*nDestWidth]=vColor;
6000
+                                fY+=fYdelta;
6001
+                        }
6002
+                }
6003
+        }
6004
+        else if (bYEq)
6005
+        {
6006
+                for (sint32 nX=0; nX<nDestWidth; nX++)
6007
+                {
6008
+                        sint32 nY;
6009
+                        for (nY=0; nY<nDestHeight; nY++)
6010
+                        {
6011
+                                pDest[nX+nY*nDestWidth]=pIterm[nY*nDestWidth+nX];
6012
+                        }
6013
+                }
6014
+        }
6015
+        else
6016
+        {
6017
+                double fYdelta=(double)(nSrcHeight)/(double)(nDestHeight);
6018
+                nlassert (fYdelta>1.f);
6019
+                sint32 nX;
6020
+                for (nX=0; nX<nDestWidth; nX++)
6021
+                {
6022
+                        double fY=0.f;
6023
+                        sint32 nY;
6024
+                        for (nY=0; nY<nDestHeight; nY++)
6025
+                        {
6026
+                                NLMISC::CRGBAF vColor (0.f, 0.f, 0.f, 0.f);
6027
+                                double fFinal=fY+fYdelta;
6028
+                                while ((fY<fFinal)&&((sint32)fY!=nSrcHeight))
6029
+                                {
6030
+                                        double fNext=(double)floor (fY)+1.f;
6031
+                                        if (fNext>fFinal)
6032
+                                                fNext=fFinal;
6033
+                                        vColor+=((float)(fNext-fY))*pIterm[((sint32)floor(fY))*nDestWidth+nX];
6034
+                                        fY=fNext;
6035
+                                }
6036
+                                vColor/=(float)fYdelta;
6037
+                                pDest[nX+nY*nDestWidth]=vColor;
6038
+                        }
6039
+                }
6040
+        }
6041
+}
6042
+
6043
+/*-------------------------------------------------------------------*\
6044
+                                                        resamplePicture32Fast
6045
+\*-------------------------------------------------------------------*/
6046
+void CBitmap::resamplePicture32Fast (const NLMISC::CRGBA *pSrc, NLMISC::CRGBA *pDest,
6047
+                                                                         sint32 nSrcWidth, sint32 nSrcHeight,
6048
+                                                                         sint32 nDestWidth, sint32 nDestHeight)
6049
+{
6050
+        // the image is divided by two : 1 pixel in dest = 4 pixels in src
6051
+        // the resulting pixel in dest is an average of the four pixels in src
6052
+
6053
+        nlassert(nSrcWidth  % 2 == 0);
6054
+        nlassert(nSrcHeight % 2 == 0);
6055
+        nlassert(nSrcWidth  / 2 == nDestWidth);
6056
+        nlassert(nSrcHeight / 2 == nDestHeight);
6057
+
6058
+        sint32 x, y, twoX, twoSrcWidthByY;
6059
+
6060
+        for (y=0 ; y<nDestHeight ; y++)
6061
+        {
6062
+                twoSrcWidthByY = 2*nSrcWidth*y;
6063
+                for (x=0 ; x<nDestWidth ; x++)
6064
+                {
6065
+                        twoX = 2*x;
6066
+                        pDest[x+y*nDestWidth].avg4( pSrc[twoX   + twoSrcWidthByY             ],
6067
+                                                                                pSrc[twoX   + twoSrcWidthByY + nSrcWidth ],
6068
+                                                                                pSrc[twoX+1 + twoSrcWidthByY             ],
6069
+                                                                                pSrc[twoX+1 + twoSrcWidthByY + nSrcWidth ]);
6070
+                }
6071
+        }
6072
+}
6073
+
6074
+
6075
+
6076
+/*-------------------------------------------------------------------*\
6077
+                                                        readTGA
6078
+\*-------------------------------------------------------------------*/
6079
+uint8 CBitmap::readTGA( NLMISC::IStream &f)
6080
+{
6081
+        /* ***********************************************
6082
+         *        WARNING: This Class/Method must be thread-safe (ctor/dtor/serial): no static access for instance
6083
+         *        It can be loaded/called through CAsyncFileManager for instance
6084
+         * ***********************************************/
6085
+
6086
+        if(!f.isReading()) return 0;
6087
+
6088
+        uint32                        size;
6089
+        uint32                        x,y;
6090
+        sint32                        slsize;
6091
+        uint8                        *scanline;
6092
+        uint8                        r,g,b;
6093
+        sint32                        i,j,k;
6094
+
6095
+        // TGA file header fields
6096
+        uint8        lengthID;
6097
+        uint8        cMapType;
6098
+        uint8        imageType;
6099
+        uint16        origin;
6100
+        uint16        length;
6101
+        uint8        depth;
6102
+        uint16        xOrg;
6103
+        uint16        yOrg;
6104
+        uint16        width;
6105
+        uint16        height;
6106
+        uint8        imageDepth;
6107
+        uint8        desc;
6108
+
6109
+
6110
+        // Determining whether file is in Original or New TGA format
6111
+
6112
+        bool newTgaFormat;
6113
+        uint32 extAreaOffset;
6114
+        uint32 devDirectoryOffset;
6115
+        char signature[16];
6116
+
6117
+        f.seek (0, f.end);
6118
+        newTgaFormat = false;
6119
+        if (f.getPos() >= 26)
6120
+        {
6121
+                f.seek (-26, f.end);
6122
+                f.serial(extAreaOffset);
6123
+                f.serial(devDirectoryOffset);
6124
+                for(i=0; i<16; i++)
6125
+                {
6126
+                        f.serial(signature[i]);
6127
+                }
6128
+                if(strncmp(signature,"TRUEVISION-XFILE",16)==0)
6129
+                        newTgaFormat = true;
6130
+        }
6131
+
6132
+
6133
+
6134
+        // Reading TGA file header
6135
+        f.seek (0, f.begin);
6136
+
6137
+        f.serial(lengthID);
6138
+        f.serial(cMapType);
6139
+        f.serial(imageType);
6140
+        f.serial(origin);
6141
+        f.serial(length);
6142
+        f.serial(depth);
6143
+        f.serial(xOrg);
6144
+        f.serial(yOrg);
6145
+        f.serial(width);
6146
+        f.serial(height);
6147
+        f.serial(imageDepth);
6148
+        f.serial(desc);
6149
+
6150
+        if(cMapType!=0)
6151
+        {
6152
+                nlinfo("readTga : color-map not supported");
6153
+        }
6154
+
6155
+        if(lengthID>0)
6156
+        {
6157
+                uint8        dummy;
6158
+                for(i=0; i<lengthID; i++)
6159
+                        f.serial(dummy);
6160
+        }
6161
+
6162
+
6163
+
6164
+        // Reading TGA image data
6165
+
6166
+        _Width = width;
6167
+        _Height = height;
6168
+        size = _Width * _Height * (imageDepth/8);
6169
+
6170
+        switch(imageType)
6171
+        {
6172
+                // Uncompressed RGB or RGBA
6173
+                case 2:
6174
+                {
6175
+                        _Data[0].resize(_Width*_Height*4);
6176
+                        uint8 upSideDown = ((desc & (1 << 5))==0);
6177
+                        slsize = _Width * imageDepth / 8;
6178
+
6179
+                        scanline = new uint8[slsize];
6180
+                        if(!scanline)
6181
+                        {
6182
+                                throw EAllocationFailure();
6183
+                        }
6184
+
6185
+                        for(y=0; y<_Height;y++)
6186
+                        {
6187
+                                // Serial buffer: more efficient way to load.
6188
+                                f.serialBuffer (scanline, slsize);
6189
+
6190
+                                if(imageDepth==24 || imageDepth==32)
6191
+                                {
6192
+                                        sint32 mult = 3;
6193
+                                        if(imageDepth==16)
6194
+                                        {
6195
+                                                mult = 2;
6196
+                                        }
6197
+                                        if(imageDepth==32)
6198
+                                        {
6199
+                                                mult = 4;
6200
+                                        }
6201
+                                        if(imageDepth!=16)
6202
+                                        {
6203
+                                                for(x=0; x<_Width; x++)
6204
+                                                {
6205
+                                                        // RGB(A)
6206
+                                                        r = scanline[x*mult+0];
6207
+                                                        g = scanline[x*mult+1];
6208
+                                                        b = scanline[x*mult+2];
6209
+                                                        // Switching to BGR(A)
6210
+                                                        scanline[x*mult+0] = b;
6211
+                                                        scanline[x*mult+1] = g;
6212
+                                                        scanline[x*mult+2] = r;
6213
+                                                }
6214
+                                        }
6215
+                                }
6216
+
6217
+                                k=0;
6218
+                                for(i=0; i<width; i++)
6219
+                                {
6220
+                                        if(upSideDown)
6221
+                                        {
6222
+                                                if(imageDepth==16)
6223
+                                                {
6224
+                                                        uint16 toto = (uint16)scanline[k++];
6225
+                                                        toto |= scanline[k++]<<8;
6226
+                                                        uint _r = toto>>10;
6227
+                                                        uint _g = (toto>>5)&0x1f;
6228
+                                                        uint _b = toto&0x1f;
6229
+                                                        _Data[0][(height-y-1)*width*4 + 4*i] = uint8((_r<<3) | (_r>>2));
6230
+                                                        _Data[0][(height-y-1)*width*4 + 4*i + 1] = uint8((_g<<3) | (_g>>2));
6231
+                                                        _Data[0][(height-y-1)*width*4 + 4*i + 2] = uint8((_b<<3) | (_b>>2));
6232
+                                                        _Data[0][(height-y-1)*width*4 + 4*i + 3] = 255;
6233
+                                                }
6234
+                                                else
6235
+                                                {
6236
+                                                        _Data[0][(height-y-1)*width*4 + 4*i] = scanline[k++];
6237
+                                                        _Data[0][(height-y-1)*width*4 + 4*i + 1] = scanline[k++];
6238
+                                                        _Data[0][(height-y-1)*width*4 + 4*i + 2] = scanline[k++];
6239
+                                                        if(imageDepth==32)
6240
+                                                                _Data[0][(height-y-1)*width*4 + 4*i + 3] = scanline[k++];
6241
+                                                        else
6242
+                                                                _Data[0][(height-y-1)*width*4 + 4*i + 3] = 255;
6243
+                                                }
6244
+                                        }
6245
+                                        else
6246
+                                        {
6247
+                                                if(imageDepth==16)
6248
+                                                {
6249
+                                                        uint16 toto = (uint16)scanline[k++];
6250
+                                                        toto |= scanline[k++]<<8;
6251
+                                                        int _r = toto>>10;
6252
+                                                        int _g = toto&(0x3e0)>>5;
6253
+                                                        int _b = toto&0x1f;
6254
+                                                        _Data[0][y*width*4 + 4*i] = uint8((_r<<3) | (_r>>2));
6255
+                                                        _Data[0][y*width*4 + 4*i + 1] = uint8((_g<<3) | (_g>>2));
6256
+                                                        _Data[0][y*width*4 + 4*i + 2] = uint8((_b<<3) | (_b>>2));
6257
+                                                        _Data[0][y*width*4 + 4*i + 3] = 255;
6258
+                                                }
6259
+                                                else
6260
+                                                {
6261
+                                                        _Data[0][y*width*4 + 4*i] = scanline[k++];
6262
+                                                        _Data[0][y*width*4 + 4*i + 1] = scanline[k++];
6263
+                                                        _Data[0][y*width*4 + 4*i + 2] = scanline[k++];
6264
+                                                        if(imageDepth==32)
6265
+                                                                _Data[0][y*width*4 + 4*i + 3] = scanline[k++];
6266
+                                                        else
6267
+                                                                _Data[0][y*width*4 + 4*i + 3] = 255;
6268
+                                                }
6269
+                                        }
6270
+                                }
6271
+                        }
6272
+
6273
+                        PixelFormat = RGBA;
6274
+                        delete []scanline;
6275
+                };
6276
+                break;
6277
+
6278
+                // Uncompressed Grayscale bitmap
6279
+                case 3:
6280
+                {
6281
+                        _Data[0].resize(_Width*_Height);
6282
+                        uint8 upSideDown = ((desc & (1 << 5))==0);
6283
+                        slsize = _Width;
6284
+
6285
+                        scanline = new uint8[slsize];
6286
+                        if(!scanline)
6287
+                        {
6288
+                                throw EAllocationFailure();
6289
+                        }
6290
+
6291
+                        for(y=0; y<_Height;y++)
6292
+                        {
6293
+                                // Serial buffer: more efficient way to load.
6294
+                                f.serialBuffer (scanline, slsize);
6295
+
6296
+                                k=0;
6297
+                                for(i=0; i<width; i++)
6298
+                                {
6299
+                                        if(upSideDown)
6300
+                                                _Data[0][(height-y-1)*width + i] = scanline[k++];
6301
+                                        else
6302
+                                                _Data[0][y*width + i] = scanline[k++];
6303
+                                }
6304
+                        }
6305
+
6306
+                        PixelFormat = _LoadGrayscaleAsAlpha?Alpha:Luminance;
6307
+                        delete []scanline;
6308
+                };
6309
+                break;
6310
+
6311
+                // Compressed RGB or RGBA
6312
+                case 10:
6313
+                {
6314
+                        uint8 packet;
6315
+                        uint8 pixel[4];
6316
+                        uint32 imageSize = width*height;
6317
+                        uint32 readSize = 0;
6318
+                        uint8 upSideDown = ((desc & (1 << 5))==0);
6319
+                        _Data[0].resize(_Width*_Height*4);
6320
+                        uint        dstId= 0;
6321
+
6322
+                        while(readSize < imageSize)
6323
+                        {
6324
+                                f.serial(packet);
6325
+                                if((packet & 0x80) > 0) // packet RLE
6326
+                                {
6327
+                                        for(i=0; i<imageDepth/8; i++)
6328
+                                        {
6329
+                                                f.serial(pixel[i]);
6330
+                                        }
6331
+                                        for (i=0; i < (packet & 0x7F) + 1; i++)
6332
+                                        {
6333
+                                                if(imageDepth==32)
6334
+                                                {
6335
+                                                        _Data[0][dstId++]= pixel[2];
6336
+                                                        _Data[0][dstId++]= pixel[1];
6337
+                                                        _Data[0][dstId++]= pixel[0];
6338
+                                                        _Data[0][dstId++]= pixel[3];
6339
+                                                }
6340
+                                                if(imageDepth==24)
6341
+                                                {
6342
+                                                        _Data[0][dstId++]= pixel[2];
6343
+                                                        _Data[0][dstId++]= pixel[1];
6344
+                                                        _Data[0][dstId++]= pixel[0];
6345
+                                                        _Data[0][dstId++]= 0;
6346
+                                                }
6347
+                                        }
6348
+                                }
6349
+                                else        // packet Raw
6350
+                                {
6351
+                                        for(i=0; i<((packet & 0x7F) + 1); i++)
6352
+                                        {
6353
+                                                for(j=0; j<imageDepth/8; j++)
6354
+                                                {
6355
+                                                        f.serial(pixel[j]);
6356
+                                                }
6357
+                                                if(imageDepth==32)
6358
+                                                {
6359
+                                                        _Data[0][dstId++]= pixel[2];
6360
+                                                        _Data[0][dstId++]= pixel[1];
6361
+                                                        _Data[0][dstId++]= pixel[0];
6362
+                                                        _Data[0][dstId++]= pixel[3];
6363
+                                                }
6364
+                                                if(imageDepth==24)
6365
+                                                {
6366
+                                                        _Data[0][dstId++]= pixel[2];
6367
+                                                        _Data[0][dstId++]= pixel[1];
6368
+                                                        _Data[0][dstId++]= pixel[0];
6369
+                                                        _Data[0][dstId++]= 0;
6370
+                                                }
6371
+                                        }
6372
+                                  }
6373
+                                readSize += (packet & 0x7F) + 1;
6374
+                        }
6375
+                        PixelFormat = RGBA;
6376
+
6377
+                        if (upSideDown) flipV();
6378
+                };
6379
+                break;
6380
+
6381
+                // Compressed Grayscale bitmap (not tested)
6382
+                case 11:
6383
+                {
6384
+                        uint8 packet;
6385
+                        uint8 pixel[4];
6386
+                        uint32 imageSize = width*height;
6387
+                        uint32 readSize = 0;
6388
+                        _Data[0].resize(_Width*_Height);
6389
+                        uint        dstId= 0;
6390
+
6391
+                        while(readSize < imageSize)
6392
+                        {
6393
+                                f.serial(packet);
6394
+                                if((packet & 0x80) > 0) // packet RLE
6395
+                                {
6396
+                                        f.serial(pixel[0]);
6397
+                                        for (i=0; i < (packet & 0x7F) + 1; i++)
6398
+                                        {
6399
+                                                _Data[0][dstId++]= pixel[0];
6400
+                                        }
6401
+                                }
6402
+                                else        // packet Raw
6403
+                                {
6404
+                                        for(i=0; i<((packet & 0x7F) + 1); i++)
6405
+                                        {
6406
+                                                f.serial(pixel[0]);
6407
+                                                _Data[0][dstId++]= pixel[0];
6408
+                                        }
6409
+                                  }
6410
+                                readSize += (packet & 0x7F) + 1;
6411
+                        }
6412
+                        PixelFormat = _LoadGrayscaleAsAlpha?Alpha:Luminance;
6413
+                };
6414
+                break;
6415
+
6416
+                default:
6417
+                        return 0;
6418
+        }
6419
+
6420
+        _MipMapCount = 1;
6421
+        return(imageDepth);
6422
+
6423
+}
6424
+
6425
+/*-------------------------------------------------------------------*\
6426
+                                                        writeTGA
6427
+\*-------------------------------------------------------------------*/
6428
+bool CBitmap::writeTGA( NLMISC::IStream &f, uint32 d, bool upsideDown)
6429
+{
6430
+        if(f.isReading()) return false;
6431
+        if (d==0)
6432
+        {
6433
+                switch (PixelFormat)
6434
+                {
6435
+                case RGBA:
6436
+                        d = 32;
6437
+                        break;
6438
+                case Luminance:
6439
+                        d = 8;
6440
+                        break;
6441
+                case Alpha:
6442
+                        d = 8;
6443
+                        break;
6444
+                default:
6445
+                        ;
6446
+                }
6447
+        }
6448
+        if(d!=24 && d!=32 && d!=16 && d!=8) return false;
6449
+        if ((PixelFormat != RGBA)&&(PixelFormat != Alpha)&&(PixelFormat != Luminance)) return false;
6450
+        if ((PixelFormat == Alpha) && (d != 8)) return false;
6451
+        if ((PixelFormat == Luminance) && (d != 8)) return false;
6452
+
6453
+        sint32        i,j,x,y;
6454
+        uint8        * scanline;
6455
+        uint8        r,g,b,a;
6456
+
6457
+        uint8        lengthID = 0;
6458
+        uint8        cMapType = 0;
6459
+        uint8        imageType = 2;
6460
+        uint16        origin = 0;
6461
+        uint16        length = 0;
6462
+        uint8        depth = 0;
6463
+        uint16        xOrg = 0;
6464
+        uint16        yOrg = 0;
6465
+        uint16        width = (uint16)_Width;
6466
+        uint16        height = (uint16)_Height;
6467
+        uint8        imageDepth = (uint8)d;
6468
+        uint8        desc = 0;
6469
+        if (upsideDown)
6470
+                desc |= 1<<5;
6471
+
6472
+        if ((PixelFormat == Alpha) || (PixelFormat == Luminance))
6473
+                imageType = 3; // Uncompressed grayscale
6474
+
6475
+        f.serial(lengthID);
6476
+        f.serial(cMapType);
6477
+        f.serial(imageType);
6478
+        f.serial(origin);
6479
+        f.serial(length);
6480
+        f.serial(depth);
6481
+        f.serial(xOrg);
6482
+        f.serial(yOrg);
6483
+        f.serial(width);
6484
+        f.serial(height);
6485
+        f.serial(imageDepth);
6486
+        f.serial(desc);
6487
+
6488
+        if ((PixelFormat == Alpha)||(PixelFormat == Luminance))
6489
+                scanline = new uint8[width];
6490
+        else
6491
+                scanline = new uint8[width*4];
6492
+        if(!scanline)
6493
+        {
6494
+                throw EAllocationFailure();
6495
+        }
6496
+
6497
+        for(y=0; y<(sint32)height; y++)
6498
+        {
6499
+
6500
+                uint32 k=0;
6501
+                if (PixelFormat == Alpha)
6502
+                {
6503
+                        for(i=0; i<width; ++i) // Alpha
6504
+                        {
6505
+                                scanline[k++] = _Data[0][(height-y-1)*width + i];
6506
+                        }
6507
+                }
6508
+                else if (PixelFormat == Luminance)
6509
+                {
6510
+                        for(i=0; i<width; ++i) // Luminance
6511
+                        {
6512
+                                scanline[k++] = _Data[0][(height-y-1)*width + i];
6513
+                        }
6514
+                }
6515
+                else
6516
+                {
6517
+                        for(i=0; i<width*4; i+=4) // 4:RGBA
6518
+                        {
6519
+                                if(d==16)
6520
+                                {
6521
+                                        for(j=0; j<(sint32)4; j++)
6522
+                                        {
6523
+                                                scanline[k++] = _Data[0][(height-y-1)*width*4 + i + j];
6524
+                                        }
6525
+                                }
6526
+                                else
6527
+                                {
6528
+                                        for(j=0; j<(sint32)d/8; j++)
6529
+                                        {
6530
+                                                scanline[k++] = _Data[0][(height-y-1)*width*4 + i + j];
6531
+                                        }
6532
+                                }
6533
+                        }
6534
+                }
6535
+
6536
+                if(d==16)
6537
+                {
6538
+                        for(x=0; x<(sint32)width; x++)
6539
+                        {
6540
+                                r = scanline[x*4+0];
6541
+                                g = scanline[x*4+1];
6542
+                                b = scanline[x*4+2];
6543
+                                int rr = r >>3;
6544
+                                int gg = g >>3;
6545
+                                int bb = b >>3;
6546
+                                uint16 c16 = uint16((rr<<10) | (gg<<5) | bb);
6547
+                                scanline[x*2+0] = c16&0xff;
6548
+                                scanline[x*2+1] = c16>>8;
6549
+                        }
6550
+                }
6551
+                if(d==24)
6552
+                {
6553
+                        for(x=0; x<(sint32)width; x++)
6554
+                        {
6555
+                                r = scanline[x*3+0];
6556
+                                g = scanline[x*3+1];
6557
+                                b = scanline[x*3+2];
6558
+                                scanline[x*3+0] = b;
6559
+                                scanline[x*3+1] = g;
6560
+                                scanline[x*3+2] = r;
6561
+                        }
6562
+                }
6563
+                if(d==32)
6564
+                {
6565
+                        for(x=0; x<(sint32)width; x++)
6566
+                        {
6567
+                                r = scanline[x*4+0];
6568
+                                g = scanline[x*4+1];
6569
+                                b = scanline[x*4+2];
6570
+                                a= scanline[x*4+3];
6571
+                                scanline[x*4+0] = b;
6572
+                                scanline[x*4+1] = g;
6573
+                                scanline[x*4+2] = r;
6574
+                                scanline[x*4+3] = a;
6575
+                        }
6576
+                }
6577
+
6578
+                int finaleSize=width*d/8;
6579
+                for(i=0; i<finaleSize; i++)
6580
+                {
6581
+                        f.serial(scanline[i]);
6582
+                }
6583
+        }
6584
+        delete []scanline;
6585
+        return true;
6586
+}
6587
+
6588
+
6589
+template<class T>
6590
+void rotateCCW (const T* src, T* dst, uint srcWidth, uint srcHeight)
6591
+{
6592
+        for (uint y=0; y<srcHeight; y++)
6593
+        for (uint x=0; x<srcWidth; x++)
6594
+        {
6595
+                uint dstX=y;
6596
+                uint dstY=srcWidth-x-1;
6597
+                dst[dstX+dstY*srcHeight]=src[x+y*srcWidth];
6598
+        }
6599
+}
6600
+
6601
+/*template<class T>
6602
+void rotateCCW (const vector<T>& src, vector<T>& dst, uint srcWidth, uint srcHeight)
6603
+{
6604
+        for (uint y=0; y<srcHeight; y++)
6605
+        for (uint x=0; x<srcWidth; x++)
6606
+        {
6607
+                uint dstX=y;
6608
+                uint dstY=srcWidth-x;
6609
+                dst[dstX+dstY*srcHeight]=src[x+y*srcWidth];
6610
+        }
6611
+}
6612
+*/
6613
+void CBitmap::rotateCCW()
6614
+{
6615
+        // Copy the array
6616
+        CObjectVector<uint8> copy=_Data[0];
6617
+
6618
+        switch (PixelFormat)
6619
+        {
6620
+        case RGBA:
6621
+                NLMISC::rotateCCW ((uint32*)&(_Data[0][0]), (uint32*)&(copy[0]), _Width, _Height);
6622
+                break;
6623
+        case Luminance:
6624
+        case Alpha:
6625
+                NLMISC::rotateCCW (&_Data[0][0], &copy[0], _Width, _Height);
6626
+                break;
6627
+        case AlphaLuminance:
6628
+                NLMISC::rotateCCW ((uint16*)&(_Data[0][0]), (uint16*)&(copy[0]), _Width, _Height);;
6629
+                break;
6630
+        default: break;
6631
+        }
6632
+
6633
+        uint32 tmp=_Width;
6634
+        _Width=_Height;
6635
+        _Height=tmp;
6636
+        _Data[0]=copy;
6637
+}
6638
+
6639
+void CBitmap::blit(const CBitmap &src, sint srcX, sint srcY, sint srcWidth, sint srcHeight, sint destX, sint destY)
6640
+{
6641
+        nlassert(PixelFormat == RGBA);
6642
+        nlassert(src.PixelFormat == RGBA);
6643
+        // clip x
6644
+        if (srcX < 0)
6645
+        {
6646
+                srcWidth += srcX;
6647
+                if (srcWidth <= 0) return;
6648
+                destX -= srcX;
6649
+                srcX = 0;
6650
+        }
6651
+        if (srcX + srcWidth > (sint) src.getWidth())
6652
+        {
6653
+                srcWidth = src.getWidth() - srcX;
6654
+                if (srcWidth <= 0) return;
6655
+        }
6656
+        if (destX < 0)
6657
+        {
6658
+                srcWidth += destX;
6659
+                if (srcWidth <= 0) return;
6660
+                srcX -= destX;
6661
+                destX = 0;
6662
+        }
6663
+        if (destX + srcWidth > (sint) getWidth())
6664
+        {
6665
+                srcWidth = getWidth() - destX;
6666
+                if (srcWidth <= 0) return;
6667
+        }
6668
+        // clip y
6669
+        if (srcY < 0)
6670
+        {
6671
+                srcHeight += srcY;
6672
+                if (srcHeight <= 0) return;
6673
+                destY -= srcY;
6674
+                srcY = 0;
6675
+        }
6676
+        if (srcY + srcHeight > (sint) src.getHeight())
6677
+        {
6678
+                srcHeight = src.getHeight() - srcY;
6679
+                if (srcHeight <= 0) return;
6680
+        }
6681
+        if (destY < 0)
6682
+        {
6683
+                srcHeight += destY;
6684
+                if (srcHeight <= 0) return;
6685
+                srcY -= destY;
6686
+                destY = 0;
6687
+        }
6688
+        if (destY + srcHeight > (sint) getHeight())
6689
+        {
6690
+                srcHeight = getHeight() - destY;
6691
+                if (srcHeight <= 0) return;
6692
+        }
6693
+        uint32 *srcPixels = (uint32 *) &src.getPixels()[0];
6694
+        uint32 *srcPtr = &(srcPixels[srcX + srcY * src.getWidth()]);
6695
+        uint32 *srcEndPtr = srcPtr + srcHeight * src.getWidth();
6696
+        uint32 *destPixels = (uint32 *) &getPixels()[0];
6697
+        uint32 *destPtr =         &(destPixels[destX + destY * getWidth()]);
6698
+        while (srcPtr != srcEndPtr)
6699
+        {
6700
+                memcpy(destPtr, srcPtr, sizeof(uint32) * srcWidth);
6701
+                srcPtr += src.getWidth();
6702
+                destPtr += getWidth();
6703
+        }
6704
+
6705
+}
6706
+
6707
+
6708
+bool CBitmap::blit(const CBitmap *src, sint32 x, sint32 y)
6709
+{
6710
+
6711
+        nlassert(this->PixelFormat == src->PixelFormat);
6712
+        if (this->PixelFormat != src->PixelFormat)
6713
+        {
6714
+                return false;
6715
+        }
6716
+
6717
+
6718
+        // check for dxtc use
6719
+
6720
+        const bool useDXTC   =  PixelFormat == DXTC1 || PixelFormat == DXTC1Alpha || PixelFormat == DXTC3 || PixelFormat ==        DXTC5;
6721
+
6722
+        // number of bits for a 4x4 pix block
6723
+        const uint dxtcNumBits  =  PixelFormat == DXTC1 || PixelFormat == DXTC1Alpha ? 64 : 128;
6724
+
6725
+
6726
+        if (useDXTC)
6727
+        {
6728
+                // blit pos must be multiple of 4
6729
+
6730
+                nlassert(! (x & 3 || y & 3) );
6731
+                if (x & 3 || y & 3) return false;
6732
+
6733
+        }
6734
+
6735
+        nlassert(PixelFormat != DonTKnow);
6736
+
6737
+        // the width to copy
6738
+        sint width = src->_Width;
6739
+        // the height to copy
6740
+        sint height = src->_Height;
6741
+
6742
+        uint destStartX, destStartY;
6743
+        uint srcStartX, srcStartY;
6744
+
6745
+
6746
+        // clip against left
6747
+        if (x < 0)
6748
+        {
6749
+                width += x;
6750
+                if (width <= 0) return true;
6751
+                destStartX = 0;
6752
+                srcStartX = -x;
6753
+        }
6754
+        else
6755
+        {
6756
+                destStartX = x;
6757
+                srcStartX = 0;
6758
+        }
6759
+
6760
+        // clip against top
6761
+        if (y < 0)
6762
+        {
6763
+                height += y;
6764
+                if (height <= 0) return true;
6765
+                srcStartY = -y;
6766
+                destStartY = 0;
6767
+        }
6768
+        else
6769
+        {
6770
+                destStartY = y;
6771
+                srcStartY = 0;
6772
+        }
6773
+
6774
+        // clip against right
6775
+        if ((destStartX + width - 1) >= _Width)
6776
+        {
6777
+                width = _Width - destStartX;
6778
+                if (width <= 0) return true;
6779
+        }
6780
+
6781
+        // clip against bottom
6782
+        if ((destStartY + height - 1) >= _Height)
6783
+        {
6784
+                height = _Height - destStartY;
6785
+                if (width <= 0) return true;
6786
+        }
6787
+
6788
+
6789
+        // divide all distance by 4 when using DXTC
6790
+        if (useDXTC)
6791
+        {
6792
+                destStartX >>= 2;
6793
+                destStartY >>= 2;
6794
+                srcStartX >>= 2;
6795
+                srcStartY >>= 2;
6796
+                width >>= 2;
6797
+                height >>= 2;
6798
+        }
6799
+
6800
+
6801
+        // bytes per pixs is for either one pixel or 16 (a 4x4 block in DXTC)
6802
+        const uint bytePerPixs = ( useDXTC ? dxtcNumBits : bitPerPixels[PixelFormat] ) >> 3 /* divide by 8 to get the number of bytes */;
6803
+
6804
+
6805
+        const uint destRealWidth = useDXTC ? (_Width >> 2) : _Width;
6806
+        const uint srcRealWidth = useDXTC ? (src->_Width >> 2) : src->_Width;
6807
+
6808
+
6809
+        // size to go to the next line in the destination
6810
+        const uint destStride = destRealWidth * bytePerPixs;
6811
+
6812
+        // size to go to the next line in the source
6813
+        const uint srcStride = srcRealWidth * bytePerPixs;
6814
+
6815
+        // length in bytes of a line to copy
6816
+        const uint lineLength = width * bytePerPixs;
6817
+
6818
+
6819
+        uint8  *destPos = &(_Data[0][0]) + destStride * destStartY + bytePerPixs * destStartX;
6820
+        const uint8 *srcPos = &(src->_Data[0][0]) + srcStride * srcStartY + bytePerPixs * srcStartX;
6821
+
6822
+        // copy each hline
6823
+        for (sint k = 0; k < height; ++k)
6824
+        {
6825
+                ::memcpy(destPos, srcPos, lineLength);
6826
+                destPos += destStride;
6827
+                srcPos += srcStride;
6828
+        }
6829
+
6830
+
6831
+        return true;
6832
+}
6833
+
6834
+// Private :
6835
+float CBitmap::getColorInterp (float x, float y, float colorInXY00, float colorInXY10, float colorInXY01, float colorInXY11) const
6836
+{
6837
+        float res =        colorInXY00*(1.0f-x)*(1.0f-y) +
6838
+                                colorInXY10*(     x)*(1.0f-y) +
6839
+                                colorInXY01*(1.0f-x)*(     y) +
6840
+                                colorInXY11*(     x)*(     y);
6841
+        clamp (res, 0.0f, 255.0f);
6842
+        return res;
6843
+}
6844
+
6845
+// Public:
6846
+CRGBAF CBitmap::getColor (float x, float y) const
6847
+{
6848
+                if (x < 0.0f) x = 0.0f;
6849
+        if (x > 1.0f) x = 1.0f;
6850
+        if (y < 0.0f) y = 0.0f;
6851
+        if (y > 1.0f) y = 1.0f;
6852
+
6853
+        sint32 nWidth = getWidth(0);
6854
+        sint32 nHeight = getHeight(0);
6855
+
6856
+        if (nWidth == 0 || nHeight == 0) return CRGBAF(0, 0, 0, 0);
6857
+
6858
+        const CObjectVector<uint8> &rBitmap = getPixels(0);
6859
+        sint32 nX[4], nY[4];
6860
+
6861
+        x *= nWidth-1;
6862
+        y *= nHeight-1;
6863
+
6864
+        // Integer part of (x,y)
6865
+        //nX[0] = ((sint32)floor(x-0.5f));
6866
+        //nY[0] = ((sint32)floor(y-0.5f));
6867
+        nX[0] = ((sint32)floor(x));
6868
+        nY[0] = ((sint32)floor(y));
6869
+
6870
+        nX[1] = (nX[0] < (nWidth-1) ? nX[0]+1 : nX[0]);
6871
+        nY[1] = nY[0];
6872
+
6873
+        nX[2] = nX[0];
6874
+        nY[2] = (nY[0] < (nHeight-1) ? nY[0]+1 : nY[0]);
6875
+
6876
+        nX[3] = nX[1];
6877
+        nY[3] = nY[2];
6878
+
6879
+        uint32 i;
6880
+
6881
+        for (i = 0; i < 4; ++i)
6882
+        {
6883
+                nlassert (nX[i] >= 0);
6884
+                nlassert (nY[i] >= 0 );
6885
+                nlassert (nX[i] < nWidth);
6886
+                nlassert (nY[i] < nHeight);
6887
+        }
6888
+
6889
+        // Decimal part of (x,y)
6890
+        x = x - (float)nX[0];
6891
+        y = y - (float)nY[0];
6892
+
6893
+        switch (this->PixelFormat)
6894
+        {
6895
+                case RGBA:
6896
+                case DXTC1:
6897
+                case DXTC1Alpha:
6898
+                case DXTC3:
6899
+                case DXTC5:
6900
+                {
6901
+                        CRGBAF finalVal;
6902
+                        CRGBA val[4];
6903
+
6904
+                        if (this->PixelFormat == RGBA)
6905
+                        {
6906
+                                for (i = 0; i < 4; ++i)
6907
+                                {
6908
+                                        val[i] = CRGBA (rBitmap[(nX[i]+nY[i]*nWidth)*4+0],
6909
+                                                                        rBitmap[(nX[i]+nY[i]*nWidth)*4+1],
6910
+                                                                        rBitmap[(nX[i]+nY[i]*nWidth)*4+2],
6911
+                                                                        rBitmap[(nX[i]+nY[i]*nWidth)*4+3]);
6912
+                                }
6913
+                        }
6914
+                        else
6915
+                        {
6916
+                                // slower version : get from DXT
6917
+                                for (i = 0; i < 4; ++i)
6918
+                                {
6919
+                                        val[i] = getPixelColor(nX[i], nY[i]);
6920
+                                }
6921
+                        }
6922
+
6923
+                        finalVal.R = getColorInterp (x, y, val[0].R, val[1].R, val[2].R, val[3].R);
6924
+                        finalVal.G = getColorInterp (x, y, val[0].G, val[1].G, val[2].G, val[3].G);
6925
+                        finalVal.B = getColorInterp (x, y, val[0].B, val[1].B, val[2].B, val[3].B);
6926
+                        finalVal.A = getColorInterp (x, y, val[0].A, val[1].A, val[2].A, val[3].A);
6927
+                        finalVal /= 255.f;
6928
+
6929
+                        return finalVal;
6930
+                }
6931
+                break;
6932
+                case Alpha:
6933
+                case Luminance:
6934
+                {
6935
+
6936
+                        float finalVal;
6937
+                        float val[4];
6938
+
6939
+                        for (i = 0; i < 4; ++i)
6940
+                                val[i] = rBitmap[(nX[i]+nY[i]*nWidth)];
6941
+
6942
+                        finalVal = getColorInterp (x, y, val[0], val[1], val[2], val[3]);
6943
+                        finalVal /= 255.f;
6944
+
6945
+                        if (this->PixelFormat == Alpha)
6946
+                                return CRGBAF (1.f, 1.f, 1.f, finalVal);
6947
+                        else // Luminance
6948
+                                return CRGBAF (finalVal, finalVal, finalVal, 1.f);
6949
+                }
6950
+                break;
6951
+                default: break;
6952
+        }
6953
+
6954
+        return CRGBAF (0.0f, 0.0f, 0.0f, 0.0f);
6955
+}
6956
+
6957
+// wrap a value inside the given range (for positive value it is like a modulo)
6958
+static inline uint32 wrap(sint32 value, uint32 range)
6959
+{
6960
+        return value >= 0 ? (value % range) : range - 1 - (- value - 1) % range;
6961
+}
6962
+
6963
+
6964
+CRGBAF CBitmap::getColor(float x, float y, bool tileU, bool tileV) const
6965
+{
6966
+        sint32 nWidth = getWidth(0);
6967
+        sint32 nHeight = getHeight(0);
6968
+        if (nWidth == 0 || nHeight == 0) return CRGBAF(0, 0, 0, 0);
6969
+
6970
+        sint32 nX[4], nY[4];
6971
+
6972
+        if (!tileU)
6973
+        {
6974
+                if (x < 0.0f) x = 0.0f;
6975
+                if (x > 1.0f) x = 1.0f;
6976
+                x *= nWidth-1;
6977
+                nX[0] = ((sint32)floor(x));
6978
+                nX[1] = (nX[0] < (nWidth-1) ? nX[0]+1 : nX[0]);
6979
+                nX[2] = nX[0];
6980
+                nX[3] = nX[1];
6981
+                uint32 i;
6982
+                for (i = 0; i < 4; ++i)
6983
+                {
6984
+                        nlassert (nX[i] >= 0);
6985
+                        nlassert (nX[i] < nWidth);
6986
+                }
6987
+        }
6988
+        else
6989
+        {
6990
+                x *= nWidth;
6991
+                nX[0] = wrap((sint32)floorf(x), nWidth);
6992
+                nX[1] = wrap(nX[0] + 1, nWidth);
6993
+                nX[2] = nX[0];
6994
+                nX[3] = nX[1];
6995
+        }
6996
+        //
6997
+        if (!tileV)
6998
+        {
6999
+                if (y < 0.0f) y = 0.0f;
7000
+                if (y > 1.0f) y = 1.0f;
7001
+                y *= nHeight-1;
7002
+                nY[0] = ((sint32)floor(y));
7003
+                nY[1] = nY[0];
7004
+                nY[2] = (nY[0] < (nHeight-1) ? nY[0]+1 : nY[0]);
7005
+                nY[3] = nY[2];
7006
+                uint32 i;
7007
+                for (i = 0; i < 4; ++i)
7008
+                {
7009
+                        nlassert (nY[i] >= 0 );
7010
+                        nlassert (nY[i] < nHeight);
7011
+                }
7012
+        }
7013
+        else
7014
+        {
7015
+                y *= nHeight;
7016
+                nY[0] = wrap((sint32)floorf(y), nHeight);
7017
+                nY[1] = nY[0];
7018
+                nY[2] = wrap(nY[0] + 1, nHeight);
7019
+                nY[3] = nY[2];
7020
+        }
7021
+        // Decimal part of (x,y)
7022
+        x = x - (float)nX[0];
7023
+        y = y - (float)nY[0];
7024
+        const CObjectVector<uint8> &rBitmap = getPixels(0);
7025
+        switch (this->PixelFormat)
7026
+        {
7027
+                case RGBA:
7028
+                case DXTC1:
7029
+                case DXTC1Alpha:
7030
+                case DXTC3:
7031
+                case DXTC5:
7032
+                {
7033
+                        CRGBAF finalVal;
7034
+                        CRGBA val[4];
7035
+
7036
+                        if (this->PixelFormat == RGBA)
7037
+                        {
7038
+                                for (uint32 i = 0; i < 4; ++i)
7039
+                                {
7040
+                                        val[i] = CRGBA (rBitmap[(nX[i]+nY[i]*nWidth)*4+0],
7041
+                                                                        rBitmap[(nX[i]+nY[i]*nWidth)*4+1],
7042
+                                                                        rBitmap[(nX[i]+nY[i]*nWidth)*4+2],
7043
+                                                                        rBitmap[(nX[i]+nY[i]*nWidth)*4+3]);
7044
+                                }
7045
+                        }
7046
+                        else
7047
+                        {
7048
+                                // slower version : get from DXT
7049
+                                for (uint32 i = 0; i < 4; ++i)
7050
+                                {
7051
+                                        val[i] = getPixelColor(nX[i], nY[i]);
7052
+                                }
7053
+                        }
7054
+
7055
+                        finalVal.R = getColorInterp (x, y, val[0].R, val[1].R, val[2].R, val[3].R);
7056
+                        finalVal.G = getColorInterp (x, y, val[0].G, val[1].G, val[2].G, val[3].G);
7057
+                        finalVal.B = getColorInterp (x, y, val[0].B, val[1].B, val[2].B, val[3].B);
7058
+                        finalVal.A = getColorInterp (x, y, val[0].A, val[1].A, val[2].A, val[3].A);
7059
+                        finalVal /= 255.f;
7060
+
7061
+                        return finalVal;
7062
+                }
7063
+                break;
7064
+                case Alpha:
7065
+                case Luminance:
7066
+                {
7067
+
7068
+                        float finalVal;
7069
+                        float val[4];
7070
+
7071
+                        for (uint32 i = 0; i < 4; ++i)
7072
+                                val[i] = rBitmap[(nX[i]+nY[i]*nWidth)];
7073
+
7074
+                        finalVal = getColorInterp (x, y, val[0], val[1], val[2], val[3]);
7075
+                        finalVal /= 255.f;
7076
+
7077
+                        if (this->PixelFormat == Alpha)
7078
+                                return CRGBAF (1.f, 1.f, 1.f, finalVal);
7079
+                        else // Luminance
7080
+                                return CRGBAF (finalVal, finalVal, finalVal, 1.f);
7081
+                }
7082
+                break;
7083
+                default: break;
7084
+        }
7085
+        return CRGBAF (0.0f, 0.0f, 0.0f, 0.0f);
7086
+}
7087
+
7088
+
7089
+
7090
+void        CBitmap::loadSize(NLMISC::IStream &f, uint32 &retWidth, uint32 &retHeight)
7091
+{
7092
+        retWidth= 0;
7093
+        retHeight= 0;
7094
+
7095
+        nlassert(f.isReading());
7096
+
7097
+        // testing if DDS
7098
+        uint32 fileType = 0;
7099
+        f.serial(fileType);
7100
+        if(fileType == DDS_HEADER)
7101
+        {
7102
+                // read entire DDS header.
7103
+                uint32 size = 0;
7104
+                f.serial(size); // size in Bytes of header(without "DDS")
7105
+                uint32 * _DDSSurfaceDesc = new uint32[size];
7106
+                _DDSSurfaceDesc[0]= size;
7107
+
7108
+                for(uint i= 0; i<size/4 - 1; i++)
7109
+                {
7110
+                        f.serial(_DDSSurfaceDesc[i+1]);
7111
+                }
7112
+
7113
+                // flags determines which members of the header structure contain valid data
7114
+                uint32 flags = _DDSSurfaceDesc[1];
7115
+
7116
+                //verify if file have linearsize set
7117
+                if(!(flags & DDSD_LINEARSIZE))
7118
+                {
7119
+                        nlwarning("A DDS doesn't have the flag DDSD_LINEARSIZE");
7120
+                        //delete [] _DDSSurfaceDesc;
7121
+                        //throw EDDSBadHeader();
7122
+                }
7123
+
7124
+                //-------------- extracting and testing useful info
7125
+                retHeight  = _DDSSurfaceDesc[2];
7126
+                retWidth = _DDSSurfaceDesc[3];
7127
+
7128
+                delete [] _DDSSurfaceDesc;
7129
+        }
7130
+        else if(fileType == PNG_HEADER)
7131
+        {
7132
+                // check second part of header
7133
+                f.serialCheck(0x0a1a0a0d);
7134
+
7135
+                uint32 chunkLength = 0;
7136
+                uint32 chunkName = 0;
7137
+                bool eof = false;
7138
+
7139
+                do
7140
+                {
7141
+                        try
7142
+                        {
7143
+                                // length of chunk data
7144
+                                f.serial(chunkLength);
7145
+                                NLMISC_BSWAP32(chunkLength);
7146
+
7147
+                                // name of chunk
7148
+                                f.serial(chunkName);
7149
+
7150
+                                // size of image is a part of IHDR chunk
7151
+                                if (chunkName == NL_MAKEFOURCC('I', 'H', 'D', 'R'))
7152
+                                {
7153
+                                        uint32 val;
7154
+                                        f.serial(val);
7155
+                                        NLMISC_BSWAP32(val);
7156
+                                        retWidth = val;
7157
+
7158
+                                        f.serial(val);
7159
+                                        NLMISC_BSWAP32(val);
7160
+                                        retHeight = val;
7161
+
7162
+                                        break;
7163
+                                }
7164
+                                // end of file chunk
7165
+                                else if (chunkName == NL_MAKEFOURCC('I', 'E', 'N', 'D'))
7166
+                                {
7167
+                                        break;
7168
+                                }
7169
+
7170
+                                // skip data of this chunk and CRC32
7171
+                                f.seek(chunkLength+4, IStream::current);
7172
+                        }
7173
+                        catch(...)
7174
+                        {
7175
+                                eof = true;
7176
+                        }
7177
+                }
7178
+                while(!eof);
7179
+        }
7180
+        else if(fileType == JPG_HEADER)
7181
+        {
7182
+                uint8 blockMarker1 = 0;
7183
+                uint8 blockMarker2 = 0;
7184
+                uint16 blockSize = 0;
7185
+                bool eof = false;
7186
+
7187
+                do
7188
+                {
7189
+                        try
7190
+                        {
7191
+                                // marker of a block
7192
+                                f.serial(blockMarker1);
7193
+
7194
+                                if (blockMarker1 == 0xff)
7195
+                                {
7196
+                                        // marker of a block
7197
+                                        f.serial(blockMarker2);
7198
+
7199
+                                        // 0xff00 is only found in image data
7200
+                                        if (blockMarker2 == 0x00)
7201
+                                        {
7202
+                                                // image data 0xff
7203
+                                        }
7204
+                                        // 0xffda is image data
7205
+                                        else if (blockMarker2 == 0xda)
7206
+                                        {
7207
+                                                // next data is image data which must end with 0xffd9
7208
+                                        }
7209
+                                        // 0xffd9 is the end of an image
7210
+                                        else if (blockMarker2 == 0xd9)
7211
+                                        {
7212
+                                                // real end of file
7213
+                                                break;
7214
+                                        }
7215
+                                        else if (blockMarker2 == 0xdd || blockMarker2 == 0xdc)
7216
+                                        {
7217
+                                                f.seek(4, IStream::current);
7218
+                                        }
7219
+                                        else if (blockMarker2 == 0xdf)
7220
+                                        {
7221
+                                                f.seek(3, IStream::current);
7222
+                                        }
7223
+                                        else if (blockMarker2 >= 0xd0 && blockMarker2 <= 0xd8)
7224
+                                        {
7225
+                                                // no content
7226
+                                        }
7227
+                                        else
7228
+                                        {
7229
+                                                // size of a block
7230
+                                                f.serial(blockSize);
7231
+                                                NLMISC_BSWAP16(blockSize);
7232
+
7233
+                                                // frame marker (which contains image width and height)
7234
+                                                if (blockMarker2 >= 0xc0 && blockMarker2 <= 0xc3)
7235
+                                                {
7236
+                                                        uint8 imagePrecision = 0; // sample precision
7237
+                                                        uint32 imageSize = 0; // width and height
7238
+                                                        f.serial(imagePrecision); 
7239
+                                                        f.serial(imageSize);
7240
+                                                         NLMISC_BSWAP32(imageSize); 
7241
+
7242
+                                                        retWidth = imageSize & 0xffff;
7243
+                                                        retHeight = (imageSize & 0xffff0000) >> 16;
7244
+
7245
+                                                        break;
7246
+                                                }
7247
+
7248
+                                                // skip the block
7249
+                                                f.seek(blockSize - 2, IStream::current);
7250
+                                        }
7251
+                                }
7252
+                        }
7253
+                        catch(...)
7254
+                        {
7255
+                                eof = true;
7256
+                        }
7257
+                }
7258
+                while(!eof);
7259
+        }
7260
+        // assuming it's TGA
7261
+        else
7262
+        {
7263
+                if(!f.seek (0, NLMISC::IStream::begin))
7264
+                {
7265
+                        throw ESeekFailed();
7266
+                }
7267
+
7268
+                // Reading header,
7269
+                // To make sure that the bitmap is TGA, we check imageType and imageDepth.
7270
+                uint8        lengthID;
7271
+                uint8        cMapType;
7272
+                uint8        imageType;
7273
+                uint16        tgaOrigin;
7274
+                uint16        length;
7275
+                uint8        depth;
7276
+                uint16        xOrg;
7277
+                uint16        yOrg;
7278
+                uint16        width;
7279
+                uint16        height;
7280
+                uint8        imageDepth;
7281
+                uint8        desc;
7282
+
7283
+                f.serial(lengthID);
7284
+                f.serial(cMapType);
7285
+                f.serial(imageType);
7286
+                if(imageType!=2 && imageType!=3 && imageType!=10 && imageType!=11)
7287
+                {
7288
+                        nlwarning("Invalid TGA format, type %u in not supported (must be 2,3,10 or 11)", imageType);
7289
+                        return;
7290
+                }
7291
+                f.serial(tgaOrigin);
7292
+                f.serial(length);
7293
+                f.serial(depth);
7294
+                f.serial(xOrg);
7295
+                f.serial(yOrg);
7296
+                f.serial(width);
7297
+                f.serial(height);
7298
+                f.serial(imageDepth);
7299
+                if(imageDepth!=8 && imageDepth!=16 && imageDepth!=24 && imageDepth!=32)
7300
+                {
7301
+                        nlwarning("Invalid TGA format, bit depth %u in not supported (must be 8,16,24 or 32)", imageDepth);
7302
+                        return;
7303
+                }
7304
+                f.serial(desc);
7305
+
7306
+                // Ok, we have width and height.
7307
+                retWidth= width;
7308
+                retHeight= height;
7309
+        }
7310
+
7311
+        // reset stream.
7312
+        if(!f.seek (0, NLMISC::IStream::begin))
7313
+        {
7314
+                throw ESeekFailed();
7315
+        }
7316
+}
7317
+
7318
+
7319
+void        CBitmap::loadSize(const std::string &path, uint32 &retWidth, uint32 &retHeight)
7320
+{
7321
+        retWidth= 0;
7322
+        retHeight= 0;
7323
+
7324
+        CIFile                f(path);
7325
+        if(f.open(path))
7326
+                loadSize(f, retWidth, retHeight);
7327
+}
7328
+
7329
+// ***************************************************************************
7330
+void        CBitmap::flipHDXTCBlockColor(uint8 *bitColor, uint32 w)
7331
+{
7332
+        // pack each line in a u32 (NB: the following works either in Little and Big Endian)
7333
+        uint32        bits= *(uint32*)bitColor;
7334
+
7335
+        // swap in X for each line
7336
+        uint32        res;
7337
+        if(w!=2)
7338
+        {
7339
+                res = (bits & 0xC0C0C0C0) >> 6;
7340
+                res+= (bits & 0x30303030) >> 2;
7341
+                res+= (bits & 0x0C0C0C0C) << 2;
7342
+                res+= (bits & 0x03030303) << 6;
7343
+        }
7344
+        // special case where w==2
7345
+        else
7346
+        {
7347
+                res = (bits & 0x0C0C0C0C) >> 2;
7348
+                res+= (bits & 0x03030303) << 2;
7349
+        }
7350
+
7351
+        // copy
7352
+        *((uint32*)bitColor)= res;
7353
+}
7354
+
7355
+// ***************************************************************************
7356
+void        CBitmap::flipVDXTCBlockColor(uint8 *bitColor, uint32 h)
7357
+{
7358
+        // swap just bytes (work either in Little and Big Endian)
7359
+        if(h!=2)
7360
+        {
7361
+                std::swap(bitColor[0], bitColor[3]);
7362
+                std::swap(bitColor[1], bitColor[2]);
7363
+        }
7364
+        // special case where h==2)
7365
+        else
7366
+        {
7367
+                // whatever Little or Big endian, the first byte is the first line, and the second byte is the second line
7368
+                std::swap(bitColor[0], bitColor[1]);
7369
+        }
7370
+}
7371
+
7372
+// ***************************************************************************
7373
+void        CBitmap::flipHDXTCBlockAlpha3(uint8 *blockAlpha, uint32 w)
7374
+{
7375
+#ifdef NL_LITTLE_ENDIAN
7376
+        uint64        bits= *(uint64*)blockAlpha;
7377
+#else
7378
+        uint64        bits= (uint64)blockAlpha[0] + ((uint64)blockAlpha[1]<<8) +
7379
+                ((uint64)blockAlpha[2]<<16) + ((uint64)blockAlpha[3]<<24) +
7380
+                ((uint64)blockAlpha[4]<<32) + ((uint64)blockAlpha[5]<<40) +
7381
+                ((uint64)blockAlpha[6]<<48) + ((uint64)blockAlpha[7]<<56);
7382
+#endif
7383
+
7384
+        // swap in X for each line
7385
+        uint64        res;
7386
+        if(w!=2)
7387
+        {
7388
+                res = (bits & INT64_CONSTANT(0xF000F000F000F000)) >> 12;
7389
+                res+= (bits & INT64_CONSTANT(0x0F000F000F000F00)) >> 4;
7390
+                res+= (bits & INT64_CONSTANT(0x00F000F000F000F0)) << 4;
7391
+                res+= (bits & INT64_CONSTANT(0x000F000F000F000F)) << 12;
7392
+        }
7393
+        // special case where w==2
7394
+        else
7395
+        {
7396
+                res = (bits & INT64_CONSTANT(0x00F000F000F000F0)) >> 4;
7397
+                res+= (bits & INT64_CONSTANT(0x000F000F000F000F)) << 4;
7398
+        }
7399
+
7400
+        // copy
7401
+#ifdef NL_LITTLE_ENDIAN
7402
+        *((uint64*)blockAlpha)= res;
7403
+#else
7404
+        blockAlpha[0]= res & 255;
7405
+        blockAlpha[1]= (res>>8) & 255;
7406
+        blockAlpha[2]= (res>>16) & 255;
7407
+        blockAlpha[3]= (res>>24) & 255;
7408
+        blockAlpha[4]= (res>>32) & 255;
7409
+        blockAlpha[5]= (res>>40) & 255;
7410
+        blockAlpha[6]= (res>>48) & 255;
7411
+        blockAlpha[7]= (res>>56) & 255;
7412
+#endif
7413
+}
7414
+
7415
+// ***************************************************************************
7416
+void        CBitmap::flipVDXTCBlockAlpha3(uint8 *blockAlpha, uint32 h)
7417
+{
7418
+        uint16        *wAlpha= (uint16*)blockAlpha;
7419
+
7420
+        // swap just words (work either in Little and Big Endian)
7421
+        if(h!=2)
7422
+        {
7423
+                std::swap(wAlpha[0], wAlpha[3]);
7424
+                std::swap(wAlpha[1], wAlpha[2]);
7425
+        }
7426
+        // special case where h==2)
7427
+        else
7428
+        {
7429
+                // whatever Little or Big endian, the first byte is the first line, and the second byte is the second line
7430
+                std::swap(wAlpha[0], wAlpha[1]);
7431
+        }
7432
+}
7433
+
7434
+// ***************************************************************************
7435
+void        CBitmap::flipHDXTCBlockAlpha5(uint8 *bitAlpha, uint32 w)
7436
+{
7437
+        // pack into bits. Little Indian in all cases
7438
+        uint64        bits= (uint64)bitAlpha[0] + ((uint64)bitAlpha[1]<<8) +
7439
+                ((uint64)bitAlpha[2]<<16) + ((uint64)bitAlpha[3]<<24) +
7440
+                ((uint64)bitAlpha[4]<<32) + ((uint64)bitAlpha[5]<<40);
7441
+
7442
+        // swap in X for each line
7443
+        uint64        res;
7444
+        if(w!=2)
7445
+        {
7446
+                res = (bits & INT64_CONSTANT(0xE00E00E00E00)) >> 9;
7447
+                res+= (bits & INT64_CONSTANT(0x1C01C01C01C0)) >> 3;
7448
+                res+= (bits & INT64_CONSTANT(0x038038038038)) << 3;
7449
+                res+= (bits & INT64_CONSTANT(0x007007007007)) << 9;
7450
+        }
7451
+        // special case where w==2
7452
+        else
7453
+        {
7454
+                res = (bits & INT64_CONSTANT(0x038038038038)) >> 3;
7455
+                res+= (bits & INT64_CONSTANT(0x007007007007)) << 3;
7456
+        }
7457
+
7458
+        // copy. Little Indian in all cases
7459
+        bitAlpha[0]= uint8(res & 255);
7460
+        bitAlpha[1]= uint8((res>>8) & 255);
7461
+        bitAlpha[2]= uint8((res>>16) & 255);
7462
+        bitAlpha[3]= uint8((res>>24) & 255);
7463
+        bitAlpha[4]= uint8((res>>32) & 255);
7464
+        bitAlpha[5]= uint8((res>>40) & 255);
7465
+}
7466
+
7467
+// ***************************************************************************
7468
+void        CBitmap::flipVDXTCBlockAlpha5(uint8 *bitAlpha, uint32 h)
7469
+{
7470
+        // pack into bits. Little Indian in all cases
7471
+        uint64        bits= (uint64)bitAlpha[0] + ((uint64)bitAlpha[1]<<8) +
7472
+                ((uint64)bitAlpha[2]<<16) + ((uint64)bitAlpha[3]<<24) +
7473
+                ((uint64)bitAlpha[4]<<32) + ((uint64)bitAlpha[5]<<40);
7474
+
7475
+        // swap in Y
7476
+        uint64        res;
7477
+        if(h!=2)
7478
+        {
7479
+                res = (bits & INT64_CONSTANT(0xFFF000000000)) >> 36;
7480
+                res+= (bits & INT64_CONSTANT(0x000FFF000000)) >> 12;
7481
+                res+= (bits & INT64_CONSTANT(0x000000FFF000)) << 12;
7482
+                res+= (bits & INT64_CONSTANT(0x000000000FFF)) << 36;
7483
+        }
7484
+        // special case where h==2
7485
+        else
7486
+        {
7487
+                res = (bits & INT64_CONSTANT(0x000000FFF000)) >> 12;
7488
+                res+= (bits & INT64_CONSTANT(0x000000000FFF)) << 12;
7489
+        }
7490
+
7491
+        // copy. Little Indian in all cases
7492
+        bitAlpha[0]= uint8(res & 255);
7493
+        bitAlpha[1]= uint8((res>>8) & 255);
7494
+        bitAlpha[2]= uint8((res>>16) & 255);
7495
+        bitAlpha[3]= uint8((res>>24) & 255);
7496
+        bitAlpha[4]= uint8((res>>32) & 255);
7497
+        bitAlpha[5]= uint8((res>>40) & 255);
7498
+}
7499
+
7500
+// ***************************************************************************
7501
+void        CBitmap::flipDXTCMipMap(bool vertical, uint mm, uint type)
7502
+{
7503
+        nlassert(mm<MAX_MIPMAP);
7504
+        // size of a DXTC block. 64 bits (2 U32) for DXTC1, else 128 bits (4*U32)
7505
+        uint        blockSizeU32= type==1? 2 : 4;
7506
+        // get size in block
7507
+        sint32        width = getWidth(mm);
7508
+        sint32        height = getHeight(mm);
7509
+        if(width==0 || height==0)
7510
+                return;
7511
+        uint32        wBlock= (width+3)/4;
7512
+        uint32        hBlock= (height+3)/4;
7513
+        // get data ptr and check size.
7514
+        uint32        *data= (uint32*)(&_Data[mm][0]);
7515
+        nlassert(_Data[mm].size()==wBlock*hBlock*blockSizeU32*4);
7516
+
7517
+        // get the offset (in bytes) to the start of color pixels bits
7518
+        uint32        offsetColorBits= type==1? 4 : 12;
7519
+
7520
+        // abort if swap is nonsense
7521
+        if(vertical && height==1)
7522
+                return;
7523
+        if(!vertical && width==1)
7524
+                return;
7525
+
7526
+        // *** First reverse Blocks
7527
+        if(vertical)
7528
+        {
7529
+                // reverse vertical
7530
+                for(uint yBlock=0;yBlock<hBlock/2;yBlock++)
7531
+                {
7532
+                        uint32        *src0= data + (yBlock*wBlock)*blockSizeU32;
7533
+                        uint32        *src1= data + ((hBlock-yBlock-1)*wBlock)*blockSizeU32;
7534
+                        for(uint xBlock=0;xBlock<wBlock;xBlock++, src0+=blockSizeU32, src1+=blockSizeU32)
7535
+                        {
7536
+                                uint32        *block0= src0;
7537
+                                uint32        *block1= src1;
7538
+                                // swap the blocks
7539
+                                for(uint i=0;i<blockSizeU32;i++, block0++, block1++)
7540
+                                {
7541
+                                        std::swap(*block0, *block1);
7542
+                                }
7543
+                        }
7544
+                }
7545
+        }
7546
+        else
7547
+        {
7548
+                // reverse horizontal
7549
+                for(uint yBlock=0;yBlock<hBlock;yBlock++)
7550
+                {
7551
+                        uint32        *src0= data + (yBlock*wBlock)*blockSizeU32;
7552
+                        uint32        *src1= data + (yBlock*wBlock + wBlock-1)*blockSizeU32;
7553
+                        for(uint xBlock=0;xBlock<wBlock/2;xBlock++, src0+=blockSizeU32, src1-=blockSizeU32)
7554
+                        {
7555
+                                uint32        *block0= src0;
7556
+                                uint32        *block1= src1;
7557
+                                // swap the blocks
7558
+                                for(uint i=0;i<blockSizeU32;i++, block0++, block1++)
7559
+                                {
7560
+                                        std::swap(*block0, *block1);
7561
+                                }
7562
+                        }
7563
+                }
7564
+        }
7565
+
7566
+        // *** Then reverse Bits
7567
+        for(uint yBlock=0;yBlock<hBlock;yBlock++)
7568
+        {
7569
+                uint32        *src= data + (yBlock*wBlock)*blockSizeU32;
7570
+                for(uint xBlock=0;xBlock<wBlock;xBlock++, src+=blockSizeU32)
7571
+                {
7572
+                        uint8        *block= (uint8*)src;
7573
+
7574
+                        // flip color bits
7575
+                        if(vertical)        flipVDXTCBlockColor(block+offsetColorBits, height);
7576
+                        else                        flipHDXTCBlockColor(block+offsetColorBits, width);
7577
+
7578
+                        // flip alpha bits if any
7579
+                        if(type==3)
7580
+                        {
7581
+                                // point to the alpha part (16*4 bits)
7582
+                                if(vertical)        flipVDXTCBlockAlpha3(block, height);
7583
+                                else                        flipHDXTCBlockAlpha3(block, width);
7584
+                        }
7585
+                        else if(type==5)
7586
+                        {
7587
+                                // point to the bit alpha part (16*3 bits)
7588
+                                if(vertical)        flipVDXTCBlockAlpha5(block+2, height);
7589
+                                else                        flipHDXTCBlockAlpha5(block+2, width);
7590
+                        }
7591
+                }
7592
+        }
7593
+
7594
+}
7595
+
7596
+
7597
+// ***************************************************************************
7598
+void        CBitmap::flipDXTC(bool vertical)
7599
+{
7600
+        // get type
7601
+        uint        type;
7602
+        if(PixelFormat == DXTC1 || PixelFormat == DXTC1Alpha )
7603
+                type=1;
7604
+        else if(PixelFormat == DXTC3)
7605
+                type=3;
7606
+        else if(PixelFormat == DXTC5)
7607
+                type=5;
7608
+        else
7609
+                return;
7610
+
7611
+        // correct width/height?
7612
+        sint32 nWidth = getWidth(0);
7613
+        sint32 nHeight = getHeight(0);
7614
+        if(!isPowerOf2(nWidth) || !isPowerOf2(nHeight))
7615
+                return;
7616
+
7617
+        // flip all mipmaps
7618
+        for(uint mm=0;mm<_MipMapCount;mm++)
7619
+        {
7620
+                flipDXTCMipMap(vertical, mm, type);
7621
+        }
7622
+}
7623
+
7624
+
7625
+// ***************************************************************************
7626
+void        CBitmap::flipH()
7627
+{
7628
+        if (PixelFormat != RGBA)
7629
+        {
7630
+                // try for DXTC
7631
+                flipDXTC(false);
7632
+
7633
+                // then quit (whether it worked or not)
7634
+                return;
7635
+        }
7636
+
7637
+        sint32 nWidth = getWidth(0);
7638
+        sint32 nHeight = getHeight(0);
7639
+        sint32 i, j;
7640
+        NLMISC::CRGBA *pBitmap = (NLMISC::CRGBA*)&_Data[0][0];
7641
+        bool needRebuild = false;
7642
+        CRGBA temp;
7643
+
7644
+        if(_MipMapCount>1)
7645
+                needRebuild = true;
7646
+        releaseMipMaps();
7647
+
7648
+        for( i = 0; i < nHeight; ++i )
7649
+                for( j = 0; j < nWidth/2; ++j )
7650
+                {
7651
+                        temp = pBitmap[i*nWidth+j];
7652
+                        pBitmap[i*nWidth+j] = pBitmap[i*nWidth+nWidth-j-1];
7653
+                        pBitmap[i*nWidth+nWidth-j-1] = temp;
7654
+                }
7655
+
7656
+        // Rebuilding mipmaps
7657
+        if(needRebuild)
7658
+        {
7659
+                buildMipMaps();
7660
+        }
7661
+}
7662
+
7663
+
7664
+// ***************************************************************************
7665
+void        CBitmap::flipV()
7666
+{
7667
+        if (PixelFormat != RGBA)
7668
+        {
7669
+                // try for DXTC
7670
+                flipDXTC(true);
7671
+
7672
+                // then quit (whether it worked or not)
7673
+                return;
7674
+        }
7675
+
7676
+        sint32 nWidth = getWidth(0);
7677
+        sint32 nHeight = getHeight(0);
7678
+        sint32 i, j;
7679
+        NLMISC::CRGBA *pBitmap = (NLMISC::CRGBA*)&_Data[0][0];
7680
+        bool needRebuild = false;
7681
+        CRGBA temp;
7682
+
7683
+        if(_MipMapCount>1)
7684
+                needRebuild = true;
7685
+        releaseMipMaps();
7686
+
7687
+        for( j = 0; j < nHeight/2; ++j )
7688
+                for( i = 0; i < nWidth; ++i )
7689
+                {
7690
+                        temp = pBitmap[j*nWidth+i];
7691
+                        pBitmap[j*nWidth+i] = pBitmap[(nHeight-j-1)*nWidth+i];
7692
+                        pBitmap[(nHeight-j-1)*nWidth+i] = temp;
7693
+                }
7694
+
7695
+        // Rebuilding mipmaps
7696
+        if(needRebuild)
7697
+        {
7698
+                buildMipMaps();
7699
+        }
7700
+}
7701
+
7702
+
7703
+void        CBitmap::rot90CW()
7704
+{
7705
+        if (PixelFormat != RGBA)
7706
+                return;
7707
+        sint32 nWidth = getWidth(0);
7708
+        sint32 nHeight = getHeight(0);
7709
+        sint32 i, j;
7710
+        NLMISC::CRGBA *pSrcRgba = (NLMISC::CRGBA*)&_Data[0][0];
7711
+        bool needRebuild = false;
7712
+
7713
+        if(_MipMapCount>1)
7714
+                needRebuild = true;
7715
+        releaseMipMaps();
7716
+
7717
+        CObjectVector<uint8> pDestui;
7718
+        pDestui.resize(nWidth*nHeight*4);
7719
+        NLMISC::CRGBA *pDestRgba = (NLMISC::CRGBA*)&pDestui[0];
7720
+
7721
+        for( j = 0; j < nHeight; ++j )
7722
+        for( i = 0; i < nWidth;  ++i )
7723
+                pDestRgba[j+i*nHeight] = pSrcRgba[i+(nHeight-1-j)*nWidth];
7724
+
7725
+        uint32 nTemp = _Width;
7726
+        _Width = _Height;
7727
+        _Height = nTemp;
7728
+
7729
+        NLMISC::contReset(_Data[0]); // free memory
7730
+        _Data[0] =  pDestui;
7731
+        // Rebuilding mipmaps
7732
+        if(needRebuild)
7733
+        {
7734
+                buildMipMaps();
7735
+        }
7736
+}
7737
+
7738
+void        CBitmap::rot90CCW()
7739
+{
7740
+        if (PixelFormat != RGBA)
7741
+                return;
7742
+        sint32 nWidth = getWidth(0);
7743
+        sint32 nHeight = getHeight(0);
7744
+        sint32 i, j;
7745
+        NLMISC::CRGBA *pSrcRgba = (NLMISC::CRGBA*)&_Data[0][0];
7746
+        bool needRebuild = false;
7747
+
7748
+        if(_MipMapCount>1)
7749
+                needRebuild = true;
7750
+        releaseMipMaps();
7751
+
7752
+        CObjectVector<uint8> pDestui;
7753
+        pDestui.resize(nWidth*nHeight*4);
7754
+        NLMISC::CRGBA *pDestRgba = (NLMISC::CRGBA*)&pDestui[0];
7755
+
7756
+        for( j = 0; j < nHeight; ++j )
7757
+        for( i = 0; i < nWidth;  ++i )
7758
+                pDestRgba[j+i*nHeight] = pSrcRgba[nWidth-1-i+j*nWidth];
7759
+
7760
+        uint32 nTemp = _Width;
7761
+        _Width = _Height;
7762
+        _Height = nTemp;
7763
+
7764
+        NLMISC::contReset(_Data[0]); // free memory
7765
+        _Data[0] =  pDestui;
7766
+        // Rebuilding mipmaps
7767
+        if(needRebuild)
7768
+        {
7769
+                buildMipMaps();
7770
+        }
7771
+}
7772
+
7773
+//===========================================================================
7774
+void CBitmap::blend(CBitmap &Bm0, CBitmap &Bm1, uint16 factor, bool inputBitmapIsMutable /*= false*/)
7775
+{
7776
+        nlassert(factor <= 256);
7777
+
7778
+        nlassert(Bm0._Width != 0 && Bm0._Height != 0
7779
+                         && Bm1._Width != 0 && Bm1._Height != 0);
7780
+
7781
+        nlassert(Bm0._Width  == Bm1._Width);        // the bitmap should have the same size
7782
+        nlassert(Bm0._Height == Bm1._Height);
7783
+
7784
+        const CBitmap *nBm0, *nBm1; // pointer to the bitmap that is used for blending, or to a copy is a conversion wa required
7785
+
7786
+        CBitmap cp0, cp1; // these bitmap are copies of Bm1 and Bm0 if a conversion was needed
7787
+
7788
+        if (Bm0.PixelFormat != RGBA)
7789
+        {
7790
+                if (inputBitmapIsMutable)
7791
+                {
7792
+                        Bm0.convertToRGBA();
7793
+                        nBm0 = &Bm0;
7794
+                }
7795
+                else
7796
+                {
7797
+                        cp0 = Bm0;
7798
+                        cp0.convertToRGBA();
7799
+                        nBm0 = &cp0;
7800
+                }
7801
+        }
7802
+        else
7803
+        {
7804
+                nBm0 = &Bm0;
7805
+        }
7806
+
7807
+
7808
+        if (Bm1.PixelFormat != RGBA)
7809
+        {
7810
+                if (inputBitmapIsMutable)
7811
+                {
7812
+                        Bm1.convertToRGBA();
7813
+                        nBm1 = &Bm1;
7814
+                }
7815
+                else
7816
+                {
7817
+                        cp1 = Bm1;
7818
+                        cp1.convertToRGBA();
7819
+                        nBm1 = &cp1;
7820
+                }
7821
+        }
7822
+        else
7823
+        {
7824
+                nBm1 = &Bm1;
7825
+        }
7826
+
7827
+        if (this != nBm0 && this != nBm1)
7828
+        {
7829
+                // if source is the same than the dets, don't resize because this clear the bitmap
7830
+                this->resize(Bm0._Width, Bm0._Height, RGBA);
7831
+        }
7832
+
7833
+        uint numPix = _Width * _Height; // 4 component per pixels
7834
+
7835
+
7836
+        const uint8 *src0                = &(nBm0->_Data[0][0]);
7837
+        const uint8 *src1                = &(nBm1->_Data[0][0]);
7838
+        uint8 *dest                                = &(this->_Data[0][0]);
7839
+
7840
+
7841
+        #if defined(NL_OS_WINDOWS) && !defined(NL_NO_ASM)
7842
+        if (CSystemInfo::hasMMX())
7843
+        {
7844
+                // On a P4 2GHz, with a 256x256 texture, I got the following results :
7845
+                // without mmx : 5.2 ms
7846
+        // with mmx    : 1.7 ms
7847
+                // I'm sure this can be further optimized..
7848
+
7849
+                uint numPixLeft = numPix & 1; // process 2 pixels at once, so special case for odd number
7850
+                numPix = numPix & ~1;
7851
+                // do fast blend with mmx
7852
+                uint64 blendFactor0;
7853
+                uint64 blendFactor1;
7854
+                uint16 *bf0 = (uint16 *) &blendFactor0;
7855
+                uint16 *bf1 = (uint16 *) &blendFactor1;
7856
+                bf0[0] = bf0[1] = bf0[2] = bf0[3] = (1 << 6) * (factor);
7857
+                bf1[0] = bf1[1] = bf1[2] = bf1[3] = (1 << 6) * (256 - factor);
7858
+                __asm
7859
+                {
7860
+                        mov esi, src0
7861
+                        mov eax, src1
7862
+                        mov edi, dest
7863
+                        mov ebx, -8
7864
+                        mov ecx, numPix
7865
+                        shr ecx, 1 // process pixels 2 by 2
7866
+                        movq mm1, blendFactor0
7867
+                        movq mm0, blendFactor1
7868
+
7869
+                myLoop:
7870
+                        pxor mm6, mm6
7871
+                        lea  ebx, [ebx + 8] // points next location
7872
+                        pxor mm7, mm7
7873
+                        movq mm2, [esi + ebx]
7874
+                        movq mm3, [eax + ebx]
7875
+                        // do blend
7876
+                        punpckhbw mm7, mm2  // mm7 contains src0 color 0 in high bytes
7877
+                        punpckhbw mm6, mm3  // mm6 contains src1 color 0 in high bytes
7878
+                        psrl          mm7, 1
7879
+                        pxor mm4, mm4       // mm4 = 0
7880
+                        psrl          mm6, 1
7881
+                        pmulhw mm7, mm0     // src0 = src0 * blendFactor
7882
+                        pxor mm5, mm5       // mm5 = 0
7883
+                        pmulhw mm6, mm1     // src1 = src1 * (1 - blendfactor)
7884
+                        punpcklbw mm4, mm2  // mm4 contains src0 color 1 in high bytes
7885
+                        paddusw mm6, mm7    // mm6 = src0[0] blended with src1[0]
7886
+                        psrl      mm4, 1
7887
+                        psrlw     mm6, 5
7888
+                        punpcklbw mm5, mm3  // mm4 contains src1 color 1 in high bytes
7889
+                        psrl      mm5, 1
7890
+                        pmulhw    mm4, mm0     // src0 = src0 * blendFactor
7891
+                        pmulhw    mm5, mm1     // src1 = src1 * (1 - blendfactor)
7892
+                        paddusw   mm4, mm5    // mm6 = src0[1] blended with src1[1]
7893
+                        psrlw     mm4, 5
7894
+                        // pack result
7895
+                        packuswb  mm4, mm6
7896
+                        dec                  ecx
7897
+                        movq      [edi + ebx], mm4  // store result
7898
+                        jne myLoop
7899
+                        emms
7900
+                }
7901
+                if (numPixLeft)
7902
+                {
7903
+                        // case of odd number of pixels
7904
+                        src0 += 4 * numPix;
7905
+                        src1 += 4 * numPix;
7906
+                        dest += 4 * numPix;
7907
+                        uint blendFact    = (uint) factor;
7908
+                        uint invblendFact = 256 - blendFact;
7909
+                        *dest = (uint8) (((blendFact * *src1)                + (invblendFact * *src0)) >> 8);
7910
+                        *(dest + 1) = (uint8) (((blendFact * *(src1 + 1)) + (invblendFact * *(src0 + 1))) >> 8);
7911
+                        *(dest + 2) = (uint8) (((blendFact * *(src1 + 2)) + (invblendFact * *(src0 + 2))) >> 8);
7912
+                        *(dest + 3)  = (uint8) (((blendFact * *(src1 + 3)) + (invblendFact * *(src0 + 3))) >> 8);
7913
+                }
7914
+        }
7915
+        else
7916
+        #endif //#ifdef NL_OS_WINDOWS
7917
+        {
7918
+                uint8 *endPix                        = dest + (numPix << 2);
7919
+                // no mmx version
7920
+                uint blendFact    = (uint) factor;
7921
+                uint invblendFact = 256 - blendFact;
7922
+                do
7923
+                {
7924
+                        /// blend 4 component at each pass
7925
+                        *dest = (uint8) (((blendFact * *src1)                + (invblendFact * *src0)) >> 8);
7926
+                        *(dest + 1) = (uint8) (((blendFact * *(src1 + 1)) + (invblendFact * *(src0 + 1))) >> 8);
7927
+                        *(dest + 2) = (uint8) (((blendFact * *(src1 + 2)) + (invblendFact * *(src0 + 2))) >> 8);
7928
+                        *(dest + 3)  = (uint8) (((blendFact * *(src1 + 3)) + (invblendFact * *(src0 + 3))) >> 8);
7929
+
7930
+                        src0 = src0 + 4;
7931
+                        src1 = src1 + 4;
7932
+                        dest = dest + 4;
7933
+                }
7934
+                while (dest != endPix);
7935
+        }
7936
+}
7937
+
7938
+
7939
+
7940
+//-----------------------------------------------
7941
+CRGBA CBitmap::getRGBAPixel(sint x, sint y, uint32 numMipMap /*=0*/) const
7942
+{
7943
+        uint w = getWidth(numMipMap);
7944
+        uint h = getHeight(numMipMap);
7945
+        if (w == 0 || (uint) x >= w || (uint) y >= h) return CRGBA::Black; // include negative cases
7946
+        const uint8 *pix = &getPixels(numMipMap)[(x + y * w) << 2];
7947
+        return CRGBA(pix[0], pix[1], pix[2], pix[3]);
7948
+}
7949
+
7950
+//-----------------------------------------------
7951
+CRGBA CBitmap::getDXTCColorFromBlock(const uint8 *block, sint x, sint y)
7952
+{
7953
+        uint16  col0;
7954
+        uint16  col1;
7955
+        memcpy(&col0, block, sizeof(uint16));
7956
+        memcpy(&col1, block + 2, sizeof(uint16));
7957
+        uint        colIndex = (block[4 + (y & 3)] >> ((x & 3) << 1)) & 3;
7958
+        CRGBA   result, c0, c1;
7959
+        if (col0 > col1)
7960
+        {
7961
+                switch(colIndex)
7962
+                {
7963
+                        case 0:
7964
+                                uncompress(col0, result);
7965
+                        break;
7966
+                        case 1:
7967
+                                uncompress(col1, result);
7968
+                        break;
7969
+                        case 2:
7970
+                                uncompress(col0, c0);
7971
+                                uncompress(col1, c1);
7972
+                                result.blendFromui(c0, c1, 85);
7973
+                        break;
7974
+                        case 3:
7975
+                                uncompress(col0, c0);
7976
+                                uncompress(col1, c1);
7977
+                                result.blendFromui(c0, c1, 171);
7978
+                        break;
7979
+                default:
7980
+                        ;
7981
+                }
7982
+                result.A = 255;
7983
+        }
7984
+        else
7985
+        {
7986
+                switch(colIndex)
7987
+                {
7988
+                        case 0:
7989
+                                uncompress(col0, result);
7990
+                                result.A = 255;
7991
+                        break;
7992
+                        case 1:
7993
+                                uncompress(col1, result);
7994
+                                result.A = 255;
7995
+                        break;
7996
+                        case 2:
7997
+                                uncompress(col0, c0);
7998
+                                uncompress(col1, c1);
7999
+                                result.blendFromui(c0, c1, 128);
8000
+                                result.A = 255;
8001
+                        break;
8002
+                        case 3:
8003
+                                result.set(0, 0, 0, 0);
8004
+                        break;
8005
+                }
8006
+        }
8007
+        return result;
8008
+}
8009
+
8010
+//-----------------------------------------------
8011
+CRGBA CBitmap::getDXTC1Texel(sint x, sint y, uint32 numMipMap) const
8012
+{
8013
+        uint w = getWidth(numMipMap);
8014
+        uint h = getHeight(numMipMap);
8015
+        if (w == 0 || h == 0 || (uint) x >= w || (uint) y >= h) return CRGBA::Black; // include negative cases
8016
+        uint numRowBlocks   = std::max((w + 3) >> 2, 1u);
8017
+        const uint8 *pix    = &getPixels(numMipMap)[0];
8018
+        const uint8 *block  = pix + ((y >> 2) * (numRowBlocks << 3) + ((x >> 2) << 3));
8019
+        return getDXTCColorFromBlock(block, x, y);
8020
+}
8021
+
8022
+
8023
+//-----------------------------------------------
8024
+CRGBA CBitmap::getDXTC3Texel(sint x, sint y, uint32 numMipMap) const
8025
+{
8026
+        uint w = getWidth(numMipMap);
8027
+        uint h = getHeight(numMipMap);
8028
+        if (w == 0 || h == 0 || (uint) x >= w || (uint) y >= h) return CRGBA::Black; // include negative cases
8029
+        uint numRowBlocks   = std::max((w + 3) >> 2, 1u);
8030
+        const uint8 *pix    = &getPixels(numMipMap)[0];
8031
+        const uint8 *block  = pix + ((y >> 2) * (numRowBlocks << 4) + ((x >> 2) << 4));
8032
+        CRGBA result = getDXTCColorFromBlock(block + 8, x, y);
8033
+        // get alpha part
8034
+        uint8 alphaByte = block[((y & 3) << 1) + ((x & 2) >> 1)];
8035
+        result.A = (x & 1) ?  (alphaByte & 0xf0) : ((alphaByte & 0x0f) << 4);
8036
+        return result;
8037
+}
8038
+
8039
+//-----------------------------------------------
8040
+CRGBA CBitmap::getDXTC5Texel(sint x, sint y, uint32 numMipMap) const
8041
+{
8042
+        uint w = getWidth(numMipMap);
8043
+        uint h = getHeight(numMipMap);
8044
+        if (w == 0 || h == 0 || (uint) x >= w || (uint) y >= h) return CRGBA::Black; // include negative cases
8045
+        uint numRowBlocks   = std::max((w + 3) >> 2, 1u);
8046
+        const uint8 *pix    = &getPixels(numMipMap)[0];
8047
+        const uint8 *block  = pix + ((y >> 2) * (numRowBlocks << 4) + ((x >> 2) << 4));
8048
+        CRGBA result = getDXTCColorFromBlock(block + 8, x, y);
8049
+        // get alpha part
8050
+        uint8 alpha0 = block[0];
8051
+        uint8 alpha1 = block[1];
8052
+
8053
+        uint alphaIndex;
8054
+        uint tripletIndex = (x & 3) + ((y & 3) << 2);
8055
+        if (tripletIndex < 8)
8056
+        {
8057
+                alphaIndex = (((uint32 &) block[2]) >> (tripletIndex * 3)) & 7;
8058
+        }
8059
+        else
8060
+        {
8061
+                alphaIndex = (((uint32 &) block[5]) >> ((tripletIndex - 8) * 3)) & 7; // we can read a dword there because there are color datas following he alpha datas
8062
+        }
8063
+
8064
+        if (alpha0 > alpha1)
8065
+        {
8066
+                switch (alphaIndex)
8067
+                {
8068
+                        case 0: result.A = alpha0; break;
8069
+                        case 1: result.A = alpha1; break;
8070
+                        case 2: result.A = (uint8) ((6 * (uint) alpha0 + (uint) alpha1) / 7); break;
8071
+                        case 3: result.A = (uint8) ((5 * (uint) alpha0 + 2 * (uint) alpha1) / 7); break;
8072
+                        case 4: result.A = (uint8) ((4 * (uint) alpha0 + 3 * (uint) alpha1) / 7); break;
8073
+                        case 5: result.A = (uint8) ((3 * (uint) alpha0 + 4 * (uint) alpha1) / 7); break;
8074
+                        case 6: result.A = (uint8) ((2 * (uint) alpha0 + 5 * (uint) alpha1) / 7); break;
8075
+                        case 7: result.A = (uint8) (((uint) alpha0 + (uint) 6 * alpha1) / 7); break;
8076
+                }
8077
+        }
8078
+        else
8079
+        {
8080
+                switch (alphaIndex)
8081
+                {
8082
+                        case 0: result.A = alpha0; break;
8083
+                        case 1: result.A = alpha1; break;
8084
+                        case 2: result.A = (uint8) ((4 * (uint) alpha0 + (uint) alpha1) / 5); break;
8085
+                        case 3: result.A = (uint8) ((3 * (uint) alpha0 + 2 * (uint) alpha1) / 5); break;
8086
+                        case 4: result.A = (uint8) ((2 * (uint) alpha0 + 3 * (uint) alpha1) / 5); break;
8087
+                        case 5: result.A = (uint8) (((uint) alpha0 + 4 * (uint) alpha1) / 5); break;
8088
+                        case 6: result.A = 0;        break;
8089
+                        case 7: result.A = 255; break;
8090
+                }
8091
+        }
8092
+        return result;
8093
+}
8094
+
8095
+
8096
+//-----------------------------------------------
8097
+CRGBA CBitmap::getPixelColor(sint x, sint y, uint32 numMipMap /*=0*/) const
8098
+{
8099
+
8100
+        switch (PixelFormat)
8101
+        {
8102
+                case RGBA:
8103
+                        return getRGBAPixel(x, y, numMipMap);
8104
+                case DXTC1:
8105
+                case DXTC1Alpha:
8106
+                        return getDXTC1Texel(x, y, numMipMap);
8107
+                case DXTC3:
8108
+                        return getDXTC3Texel(x, y, numMipMap);
8109
+                case DXTC5:
8110
+                        return getDXTC5Texel(x, y, numMipMap);
8111
+                default:
8112
+                        nlstop;
8113
+                break;
8114
+        }
8115
+        return CRGBA::Black;
8116
+}
8117
+
8118
+
8119
+//-----------------------------------------------
8120
+void CBitmap::swap(CBitmap &other)
8121
+{
8122
+        std::swap(PixelFormat, other.PixelFormat);
8123
+        std::swap(_MipMapCount, other._MipMapCount);
8124
+        std::swap(_LoadGrayscaleAsAlpha, other._LoadGrayscaleAsAlpha);
8125
+        std::swap(_Width, other._Width);
8126
+        std::swap(_Height, other._Height);
8127
+        for(uint k = 0; k < MAX_MIPMAP; ++k)
8128
+        {
8129
+                _Data[k].swap(other._Data[k]);
8130
+        }
8131
+}
8132
+
8133
+//-----------------------------------------------
8134
+void CBitmap::unattachPixels(CObjectVector<uint8> *mipmapDestArray, uint maxMipMapCount /*=MAX_MIPMAP*/)
8135
+{
8136
+        if (!mipmapDestArray) return;
8137
+        uint k;
8138
+        for(k = 0; k < std::min((uint) _MipMapCount, maxMipMapCount); ++k)
8139
+        {
8140
+                mipmapDestArray[k].swap(_Data[k]);
8141
+                _Data[k].clear();
8142
+        }
8143
+        for(; k < _MipMapCount; ++k)
8144
+        {
8145
+                _Data[k].clear();
8146
+        }
8147
+        #ifdef NL_DEBUG
8148
+                // check that remaining mipmaps are empty
8149
+                for(; k < _MipMapCount; ++k)
8150
+                {
8151
+                        nlassert(_Data[k].empty());
8152
+                }
8153
+        #endif
8154
+        _MipMapCount = 1;
8155
+        _Width = 0;
8156
+        _Height = 0;
8157
+        PixelFormat = RGBA;
8158
+        _LoadGrayscaleAsAlpha = true;
8159
+}
8160
+
8161
+
8162
+
8163
+
8164
+void CBitmap::getData(uint8*& extractData)
8165
+{
8166
+
8167
+        uint32 size=0;
8168
+        if(PixelFormat==RGBA)
8169
+                size=_Width*_Height*4;
8170
+        else if(PixelFormat==Alpha||PixelFormat==Luminance)
8171
+                size=_Width*_Height;
8172
+        else
8173
+        {
8174
+                nlstop;
8175
+        }
8176
+
8177
+        for(uint32 pix=0;pix<size;pix++)
8178
+                extractData[pix]=_Data[0][pix];
8179
+
8180
+}
8181
+
8182
+void CBitmap::getDibData(uint8*& extractData)
8183
+{
8184
+
8185
+        uint32 lineSize=0,size;
8186
+        uint8** buf;
8187
+        buf=new uint8*[_Height];
8188
+        if(PixelFormat==RGBA)
8189
+        {
8190
+                lineSize=_Width*4;
8191
+
8192
+
8193
+        }
8194
+        else if(PixelFormat==Alpha||PixelFormat==Luminance)
8195
+        {
8196
+                lineSize=_Width;
8197
+        }
8198
+        else
8199
+        {
8200
+                nlstop;
8201
+        }
8202
+
8203
+        for(sint32 i=_Height-1;i>=0;i--)
8204
+        {
8205
+                buf[_Height-1-i]=&_Data[0][i*lineSize];
8206
+        }
8207
+
8208
+        size=lineSize*_Height;
8209
+
8210
+        for(uint32 line=0;line<_Height;line++)
8211
+        {
8212
+                for(uint32 pix=0;pix<lineSize;pix++)
8213
+                        extractData[line*lineSize+pix]=_Data[0][size-(line+1)*lineSize+pix];
8214
+        }
8215
+        delete []buf;
8216
+
8217
+}
8218
+
8219
+} // NLMISC
8220
+