~hikiko/nux/arb-srgba-shader

« back to all changes in this revision

Viewing changes to NuxImage/Tga.cpp

  • Committer: Neil Jagdish Patel
  • Date: 2010-09-02 03:28:11 UTC
  • Revision ID: neil.patel@canonical.com-20100902032811-i2m18tfb6pkasnvt
Remove Win EOL chars

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
 */
21
21
 
22
22
 
23
 
#include <sys/stat.h>
24
 
#include <iostream>
25
 
#include <fstream>
26
 
 
27
 
#include "NuxCore/NKernel.h"
28
 
#include "NuxCore/NStreamBuffer.h"
29
 
 
30
 
#include "Tga.h"
31
 
#include "BitmapFormats.h"
32
 
 
33
 
NAMESPACE_BEGIN
34
 
/* Load up a TGA file 
35
 
36
 
*Only recognizes the following types of Targas: 
37
 
*               Type 02 - Uncompressed RGB, 16, 24 or 32 bits 
38
 
*               Type 03 - Uncompressed grayscale, 8 bits
39
 
*               Type 10 - RLE-compressed RGB, 16, 24 or 32 bits
40
 
*               Type 11 - RLE-compressed grayscale, 8 bits  
41
 
* There are several other Targa formats unsupported by this function
42
 
*/
43
 
 
44
 
 
45
 
NBitmapData* read_tga_file(const TCHAR* file_name)
46
 
{
47
 
    std::ifstream fileStream;
48
 
    BYTE *tga_buffer, *tga_data_pointer;
49
 
    t_u32 datasize;
50
 
 
51
 
    tga_header header;
52
 
    tga_footer footer;
53
 
    t_u32 rle, footer_present; 
54
 
    
55
 
    if(!GFileManager.FileExist(file_name))
56
 
    {
57
 
        //nuxAssertMsg(0, TEXT("[read_tga_file] File not found: %s"), file_name);
58
 
        return 0;
59
 
    }
60
 
 
61
 
//    NUnZip UZ(TEXT("..\\inalogic.pak"));
62
 
//    NStreamBuffer *Stream = UZ.UnzipFileToStream(file_name);
63
 
//    std::istream fileStream(Stream);
64
 
 
65
 
    fileStream.open(file_name, std::ifstream::binary);        // open as binary
66
 
    if(!fileStream.is_open())
67
 
    {
68
 
        //nuxAssertMsg(0, TEXT("[read_tga_file] Can't open file: %s"), file_name);
69
 
        return 0;
70
 
    }
71
 
 
72
 
    fileStream.seekg( 0, std::ios::end);
73
 
    t_u32 filesize = fileStream.tellg();
74
 
    fileStream.seekg( 0, std::ios::beg);
75
 
 
76
 
 
77
 
    // Read the footer first 
78
 
    fileStream.seekg(-(TGA_FOOTER_SIZE), std::ios::end);
79
 
    fileStream.read((char*)(&footer.extensionAreaOffset), 4);
80
 
    fileStream.read((char*)(&footer.developerDirectoryOffset), 4);
81
 
    fileStream.read((char*)(&footer.signature), 16);
82
 
    fileStream.read((char*)(&footer.dot), 1);
83
 
    fileStream.read((char*)(&footer.null), 1);
84
 
    if(!fileStream.good())
85
 
    {
86
 
        fileStream.close();
87
 
        //nuxAssertMsg(0, TEXT("[read_tga_file] Error while reading the TGA footer: %s"), file_name);
88
 
        return 0;
89
 
    }
90
 
 
91
 
    // Check the footer to see if we have a v2.0 TGA file 
92
 
    footer_present = 0; 
93
 
    if(Memcmp(footer.signature, TGA_SIGNATURE, TGA_SIGNATURE_SIZE) == 0)
94
 
        footer_present = 1; 
95
 
 
96
 
    if(!footer_present)
97
 
    {
98
 
        // The footer is not present in TGA format version 1. this FILE supports only TGA format version 2.0
99
 
        // Here we also eliminate every file that is not really a tga format.
100
 
        //nuxAssertMsg(0, TEXT("[read_tga_file] This is not a TGA 2.0 file: %s"), file_name);
101
 
        fileStream.close();
102
 
        return 0;
103
 
    }
104
 
 
105
 
    // Read the header
106
 
    fileStream.seekg(0, std::ios::beg);
107
 
    fileStream.read((char*)(&header.id_length), 1);
108
 
    fileStream.read((char*)(&header.colormap_type), 1);
109
 
    fileStream.read((char*)(&header.image_type), 1);
110
 
    fileStream.read((char*)(&header.colormap_index_lo), 1);
111
 
    fileStream.read((char*)(&header.colormap_index_hi), 1);
112
 
    fileStream.read((char*)(&header.colormap_length_lo), 1);
113
 
    fileStream.read((char*)(&header.colormap_length_hi), 1);
114
 
    fileStream.read((char*)(&header.colormap_size), 1);
115
 
    fileStream.read((char*)(&header.x_origin_lo), 1);
116
 
    fileStream.read((char*)(&header.x_origin_hi), 1);
117
 
    fileStream.read((char*)(&header.y_origin_lo), 1);
118
 
    fileStream.read((char*)(&header.y_origin_hi), 1);
119
 
    fileStream.read((char*)(&header.width_lo), 1);
120
 
    fileStream.read((char*)(&header.width_hi), 1);
121
 
    fileStream.read((char*)(&header.height_lo), 1);
122
 
    fileStream.read((char*)(&header.height_hi), 1);
123
 
    fileStream.read((char*)(&header.bpp), 1);
124
 
    fileStream.read((char*)(&header.descriptor), 1);
125
 
    if(!fileStream.good())
126
 
    {
127
 
        fileStream.close();
128
 
        //nuxAssertMsg(0, TEXT("[read_tga_file] Error while reading the TGA header: %s"), file_name);
129
 
        return 0;
130
 
    }
131
 
 
132
 
    switch(header.image_type)
133
 
    {
134
 
    case TGA_COLORMAP:
135
 
    case TGA_COLOR:
136
 
    case TGA_GRAYSCALE:
137
 
        rle = 0;
138
 
        break;
139
 
 
140
 
    case TGA_RLE_COLORMAP:
141
 
    case TGA_RLE_COLOR:
142
 
    case TGA_RLE_GRAYSCALE:
143
 
        rle = 1;
144
 
        break;
145
 
 
146
 
    default:
147
 
        fileStream.close();
148
 
        //nuxAssertMsg(0, TEXT("[read_tga_file] Couldn't find the image type: %s"), file_name);
149
 
        return 0;
150
 
    }
151
 
 
152
 
 
153
 
    if(((header.image_type == TGA_COLORMAP) || (header.image_type == TGA_RLE_COLORMAP)) && header.colormap_type == 0)
154
 
    {
155
 
        // the image is pseudo color but there is no colormap
156
 
        // problem in file
157
 
        fileStream.close();
158
 
        //nuxAssertMsg(0, TEXT("[read_tga_file] Couldn't find the colormap: %s"), file_name);
159
 
        return 0;
160
 
    }
161
 
 
162
 
    if(header.image_type == TGA_COLORMAP || header.image_type == TGA_RLE_COLORMAP)
163
 
    {
164
 
        // Not supported
165
 
        fileStream.close();
166
 
        //nuxAssertMsg(0, TEXT("[read_tga_file] TGA colormap image is not supported: %s"), file_name);
167
 
        return 0;
168
 
    }
169
 
 
170
 
    t_u32 width, height;
171
 
    width  = header.width_hi << 8 |  header.width_lo;
172
 
    height = header.height_hi << 8 | header.height_lo;
173
 
 
174
 
    // Size of image data = file size - header size - id length - colormap size
175
 
    datasize = filesize - (TGA_HEADER_SIZE + header.id_length + 
176
 
        (header.colormap_length_hi << 8) + header.colormap_length_lo + (footer_present ? TGA_FOOTER_SIZE : 0));
177
 
 
178
 
    // Prepare the finale image
179
 
    BitmapFormat bitmap_format;
180
 
    if(header.bpp == 8)
181
 
        bitmap_format = BITFMT_A8;
182
 
    if(header.bpp == 16)
183
 
        bitmap_format = BITFMT_R5G6B5;
184
 
    if(header.bpp == 24)
185
 
        bitmap_format = BITFMT_R8G8B8;
186
 
    if(header.bpp == 32)
187
 
        bitmap_format = BITFMT_R8G8B8A8;
188
 
 
189
 
    NTextureData* TextureObjectData = new NTextureData(bitmap_format, (header.width_hi << 8) | (header.width_lo), (header.height_hi << 8) | (header.height_lo), 1);
190
 
 
191
 
    // Allocate memory for a temporary buffer
192
 
    tga_buffer = new BYTE[datasize];
193
 
    //memset(tga_buffer, 0, datasize);
194
 
 
195
 
    // Set the position to read image data
196
 
    fileStream.seekg(long(TGA_HEADER_SIZE + header.id_length + (header.colormap_length_hi << 8) + header.colormap_length_lo),
197
 
        std::ios::beg);
198
 
 
199
 
    // Read image data 
200
 
    fileStream.read((char*)tga_buffer, datasize);
201
 
    if(!fileStream.good())
202
 
    {
203
 
        fileStream.close();
204
 
        delete tga_buffer;
205
 
        //nuxAssertMsg(0, TEXT("[read_tga_file] Error while reading the TGA data: %s"), file_name);
206
 
        INL_SAFE_DELETE(TextureObjectData);
207
 
        return 0;
208
 
    }
209
 
 
210
 
    tga_data_pointer = tga_buffer;
211
 
    t_u32 position = 0;
212
 
 
213
 
    t_u32 image_width = TextureObjectData->GetSurface(0).GetWidth();
214
 
    t_u32 image_height = TextureObjectData->GetSurface(0).GetHeight();
215
 
 
216
 
    if(rle == 0)
217
 
    {
218
 
        t_u32 j, i;
219
 
        t_u32 position = 0;
220
 
        t_u32 value;
221
 
        for(j=0; j < image_height; j++)
222
 
        {
223
 
            for(i=0; i < image_width; i++)
224
 
            {
225
 
                // In TGA the MSB is RED and the LSB is BLUE
226
 
                switch(bitmap_format)
227
 
                {
228
 
                    // 32 bits RGBA pixels
229
 
                case BITFMT_R8G8B8A8: 
230
 
                    position = (j*image_width + i);
231
 
                    // store ARGB
232
 
                    value = (*((BYTE*)tga_data_pointer + 3) << 24) |    // a
233
 
                        (*((BYTE*)tga_data_pointer + 0) << 16) |                // b
234
 
                        (*((BYTE*)tga_data_pointer + 1) << 8) |             // g
235
 
                        *((BYTE*)tga_data_pointer + 2);                             // r
236
 
 
237
 
                    TextureObjectData->GetSurface(0).Write32b(i, j, value);
238
 
                    tga_data_pointer += 4;
239
 
                    break;      
240
 
 
241
 
                    // 24 bits RGB pixels
242
 
                case BITFMT_R8G8B8:
243
 
                    position = (j*image_width + i);
244
 
                    // store 0xff_RGB
245
 
                    value = (*((BYTE*)tga_data_pointer + 0) << 16) |    // b
246
 
                        (*((BYTE*)tga_data_pointer + 1) << 8) |             // g
247
 
                        *((BYTE*)tga_data_pointer + 2);                             // r
248
 
 
249
 
                    TextureObjectData->GetSurface(0).Write24b(i, j, value);
250
 
                    tga_data_pointer += 3;
251
 
                    break;      
252
 
 
253
 
                    // 16 bits RGB pixels
254
 
                case BITFMT_R5G6B5:
255
 
                    // FIXME: it seem the format is R5G5B5 and not R5G6B5
256
 
                    position = (j*image_width + i);
257
 
 
258
 
                    BYTE r, g, b;
259
 
                    value = ((BYTE)*((BYTE*)(tga_data_pointer+1)) << 8) | ((BYTE)*((BYTE*)(tga_data_pointer+0)));
260
 
 
261
 
                    // Photoshop saves a 16 bits BMP with 5 bits for each red, green and blue.
262
 
                    // We need to expand the green component to 6 bits.
263
 
                    b = (BYTE)(value & 0x1f);
264
 
                    g = (BYTE)( float((value & 0x3e0) >> 5) * 63.0f / 31.0f);  // expand green component from 5 bits to 6 bits
265
 
                    r = (BYTE)((value & 0x7c00) >> 10);
266
 
 
267
 
                    value = (r << 11) | (g << 5) | b;
268
 
 
269
 
                    TextureObjectData->GetSurface(0).Write16b(i, j, value);
270
 
                    tga_data_pointer += 2;
271
 
                    break;      
272
 
 
273
 
                    // 8 bits black & white (grayscale)
274
 
                case BITFMT_A8: 
275
 
                    position = (j*image_width + i);
276
 
                    value = *((BYTE*)tga_data_pointer+0);
277
 
                    TextureObjectData->GetSurface(0).Write8b(i, j, value);
278
 
                    tga_data_pointer += 1;
279
 
                    break;                      
280
 
                }
281
 
            }
282
 
        }
283
 
    }  
284
 
    else
285
 
    {
286
 
        UINT rep;
287
 
        UINT i = 0;
288
 
        UINT j = 0;
289
 
        UINT position = 0;
290
 
        UINT value;
291
 
        //unsigned BYTE *last_byte = buf_dest + 4*image->height*image->width; // last byte of destination image
292
 
 
293
 
        t_u32 size = TextureObjectData->GetSurface(0).GetWidth()*TextureObjectData->GetSurface(0).GetHeight();
294
 
        while(position < size)
295
 
        {
296
 
            t_u32 repetition_count = (*tga_data_pointer & 0x7f) + 1;
297
 
 
298
 
            if(*tga_data_pointer & 0x80)  // RLE Packet
299
 
            {
300
 
                tga_data_pointer++;  // tga_data_pointer point the pixel value
301
 
 
302
 
                // In TGA the MSB is RED and the LSB is BLUE
303
 
                switch(bitmap_format)
304
 
                {
305
 
                    // 32 bits RGBA pixels
306
 
                case BITFMT_R8G8B8A8:
307
 
                    for(rep=0; rep<repetition_count; rep++)
308
 
                    {
309
 
                        // store ARGB
310
 
                        value = (*((BYTE*)tga_data_pointer + 3) << 24) |        // a
311
 
                            (*((BYTE*)tga_data_pointer + 0) << 16) |            // b
312
 
                            (*((BYTE*)tga_data_pointer + 1) << 8) |                 // g
313
 
                            *((BYTE*)tga_data_pointer + 2);                                 // r
314
 
                        TextureObjectData->GetSurface(0).Write32b(i, j, value);
315
 
                        i++;if(i >= image_width) {j++;i = 0;}
316
 
                        position++;
317
 
                    }
318
 
                    tga_data_pointer += 4;
319
 
                    break;
320
 
 
321
 
                    // 24 bits RGB pixels
322
 
                case BITFMT_R8G8B8:
323
 
                    for(rep=0; rep<repetition_count; rep++)
324
 
                    {
325
 
                        value = (0xff << 24) |
326
 
                            (*((BYTE*)tga_data_pointer + 0) << 16) |        // b
327
 
                            (*((BYTE*)tga_data_pointer + 1) << 8) |                 // g
328
 
                            *((BYTE*)tga_data_pointer + 2);                                 // r
329
 
                        TextureObjectData->GetSurface(0).Write24b(i, j, value);
330
 
                        i++;if(i >= image_width) {j++;i = 0;}
331
 
                        position++;
332
 
                    }
333
 
                    tga_data_pointer += 3;
334
 
                    break;                        
335
 
 
336
 
                    // 16 bits RGB pixels
337
 
                case BITFMT_R5G6B5:
338
 
                    for(rep=0; rep<repetition_count; rep++)
339
 
                    {
340
 
                        // FIXME: it seem the format is R5G5B5 and not R5G6B5
341
 
                        BYTE r, g, b;
342
 
                        value = (*(tga_data_pointer+1) << 8) | (*(tga_data_pointer+0));
343
 
 
344
 
                        // Photoshop saves a 16 bits BMP with 5 bits for each red, green and blue.
345
 
                        // We need to expand the green component to 6 bits.
346
 
                        b = (BYTE)(value & 0x1f);
347
 
                        g = (BYTE)( float((value & 0x3e0) >> 5) * 63.0f / 31.0f);  // expand green component from 5 bits to 6 bits
348
 
                        r = (BYTE)((value & 0x7c00) >> 10);
349
 
                        value = (r << 11) | (g << 5) | b;
350
 
 
351
 
                        TextureObjectData->GetSurface(0).Write16b(i, j, value);
352
 
                        i++;if(i >= image_width) {j++;i = 0;}
353
 
                        position++;
354
 
                    }
355
 
                    tga_data_pointer += 2;
356
 
                    break;                                        
357
 
 
358
 
                    // 8 bits grayscale pixels
359
 
                case BITFMT_A8:
360
 
                    for(rep=0; rep<repetition_count; rep++)
361
 
                    {
362
 
                        value = *((BYTE*)tga_data_pointer + 0);
363
 
                        TextureObjectData->GetSurface(0).Write8b(i, j, value);
364
 
                        i++;if(i >= image_width) {j++;i = 0;}
365
 
                        position++;
366
 
                    }
367
 
                    tga_data_pointer += 1;
368
 
                    break;
369
 
                }
370
 
            }
371
 
            else  // raw packet
372
 
            {
373
 
                tga_data_pointer++;     // tga_data_pointer point the pixel value
374
 
 
375
 
                for(rep=0; rep<repetition_count; rep++)
376
 
                {
377
 
                    switch(bitmap_format)
378
 
                    {
379
 
                        // 32 bits RGBA pixels
380
 
                    case BITFMT_R8G8B8A8:
381
 
                        value = (*((BYTE*)tga_data_pointer + 3) << 24) |                //a
382
 
                            (*((BYTE*)tga_data_pointer + 0) << 16) |                    //r
383
 
                            (*((BYTE*)tga_data_pointer + 1) << 8) |                     //g
384
 
                            *((BYTE*)tga_data_pointer + 2);                                     //b
385
 
                        TextureObjectData->GetSurface(0).Write32b(i, j, value);
386
 
                        i++;if(i >= image_width) {j++;i = 0;}
387
 
                        position++;
388
 
                        tga_data_pointer += 4;
389
 
                        break;                            
390
 
 
391
 
                        // 24 bits RGB pixels
392
 
                    case BITFMT_R8G8B8:
393
 
                        value = (*((BYTE*)tga_data_pointer + 0) << 16) |        //r
394
 
                            (*((BYTE*)tga_data_pointer + 1) << 8) |             //g
395
 
                            *((BYTE*)tga_data_pointer + 2);                             //b
396
 
                        TextureObjectData->GetSurface(0).Write24b(i, j, value);
397
 
                        i++;if(i >= image_width) {j++;i = 0;}
398
 
                        position++;
399
 
                        tga_data_pointer += 3;
400
 
                        break;
401
 
 
402
 
                        // 16 bits RGB pixels
403
 
                    case BITFMT_R5G6B5:
404
 
                        // FIXME: it seem the format is R5G5B5 and not R5G6B5
405
 
                        BYTE r, g, b;
406
 
                        value = (*(tga_data_pointer+1) << 8) | (*(tga_data_pointer+0));
407
 
 
408
 
                        // Photoshop saves a 16 bits BMP with 5 bits for each red, green and blue.
409
 
                        // We need to expand the green component to 6 bits.
410
 
                        b = (BYTE)(value & 0x1f);
411
 
                        g = (BYTE)( float((value & 0x3e0) >> 5) * 63.0f / 31.0f);  // expand green component from 5 bits to 6 bits
412
 
                        r = (BYTE)((value & 0x7c00) >> 10);
413
 
                        value = (r << 11) | (g << 5) | b;
414
 
 
415
 
                        TextureObjectData->GetSurface(0).Write16b(i, j, value);
416
 
                        i++;if(i >= image_width) {j++;i = 0;}
417
 
                        position++;
418
 
                        tga_data_pointer += 2;
419
 
                        break;                                    
420
 
 
421
 
                        // 8 bits grayscale pixels
422
 
                    case BITFMT_A8:
423
 
                        value = *((BYTE*)tga_data_pointer + 0);
424
 
                        TextureObjectData->GetSurface(0).Write8b(i, j, value);
425
 
                        i++;if(i >= image_width) {j++;i = 0;}
426
 
                        position++;
427
 
                        tga_data_pointer += 1;
428
 
                        break;
429
 
                    }
430
 
                }
431
 
            }
432
 
        }
433
 
    }
434
 
 
435
 
    unsigned char flip = (header.descriptor & 0x30);
436
 
    switch(flip)
437
 
    {
438
 
    case 0x00:  // bottom left
439
 
        TextureObjectData->GetSurface(0).FlipVertical();
440
 
        break;
441
 
    case 0x10:  // bottom right
442
 
        TextureObjectData->GetSurface(0).FlipHorizontal();
443
 
        TextureObjectData->GetSurface(0).FlipVertical();
444
 
        break;
445
 
    case 0x20:  // top left
446
 
        // Ok
447
 
        break;
448
 
    case 0x30:  // top right
449
 
        TextureObjectData->GetSurface(0).FlipHorizontal();
450
 
        break;
451
 
    }
452
 
 
453
 
    delete [] tga_buffer;
454
 
    fileStream.close();
455
 
 
456
 
    return TextureObjectData;
457
 
}
458
 
 
459
 
HReport write_tga_file(const TCHAR* file_name, NBitmapData *image)
460
 
{
461
 
    std::fstream fileStream;
462
 
 
463
 
    t_u32 datasize;
464
 
    tga_header header;
465
 
    tga_footer footer;
466
 
 
467
 
    if(file_name == 0)
468
 
    {
469
 
        nuxAssertMsg(0, TEXT("[write_tga_file] Incorrect file name."));
470
 
        return HR_INVALID_ARG;
471
 
    }
472
 
    /*if(image->get_format() != BITFMT_R8G8B8)
473
 
    {
474
 
        DEBUG_WARNING("Unsupported format");
475
 
        return HR_INVALID_ARG;
476
 
    }*/
477
 
 
478
 
        fileStream.open(file_name, std::fstream::out | std::fstream::binary);                  // open as binary
479
 
    if(!fileStream.is_open())
480
 
    {
481
 
        fprintf(stderr, "Open file %s failed", file_name);
482
 
        DEBUG_WARNING("cannot open file");
483
 
        return HR_FILE_IO_FAIL;
484
 
    }
485
 
 
486
 
    t_u32 BPP = 3;
487
 
    if(image->GetSurface(0).GetFormat() == BITFMT_R8G8B8 ||
488
 
        image->GetSurface(0).GetFormat() == BITFMT_B8G8R8)
489
 
    {
490
 
        datasize = image->GetSurface(0).GetWidth() * image->GetSurface(0).GetHeight() * 3;
491
 
        BPP = 3;
492
 
    }
493
 
 
494
 
    if(image->GetSurface(0).GetFormat() == BITFMT_A8R8G8B8 ||
495
 
        image->GetSurface(0).GetFormat() == BITFMT_B8G8R8A8 ||
496
 
        image->GetSurface(0).GetFormat() == BITFMT_R8G8B8A8 ||
497
 
        image->GetSurface(0).GetFormat() == BITFMT_A8B8G8R8)
498
 
    {
499
 
        datasize = image->GetSurface(0).GetWidth() * image->GetSurface(0).GetHeight() * 4;
500
 
        BPP = 4;
501
 
    }
502
 
 
503
 
 
504
 
    header.id_length = 0;
505
 
    header.colormap_type = 0;
506
 
    header.image_type = 2;                  // uncompressed True-Color
507
 
    header.colormap_index_lo = 0;
508
 
    header.colormap_index_hi = 0;
509
 
    header.colormap_length_lo = 0;
510
 
    header.colormap_length_hi = 0;
511
 
    header.colormap_size = 0;
512
 
    header.x_origin_lo = 0;
513
 
    header.x_origin_hi = 0;
514
 
    header.y_origin_lo = 0;
515
 
    header.y_origin_hi = 0;
516
 
    header.width_lo = image->GetSurface(0).GetWidth() & 0xff;
517
 
    header.width_hi = (image->GetSurface(0).GetWidth() & 0xff00) >> 8;
518
 
    header.height_lo = image->GetSurface(0).GetHeight() & 0xff;;
519
 
    header.height_hi = (image->GetSurface(0).GetHeight() & 0xff00) >> 8;
520
 
    header.bpp = BPP * 8;                          // 16, 24 or 32 bpp
521
 
    header.descriptor = 2 << 4;               // top left
522
 
 
523
 
 
524
 
    footer.extensionAreaOffset = 0;
525
 
    footer.developerDirectoryOffset = 0;
526
 
    footer.signature[0]  = 'T';
527
 
    footer.signature[1]  = 'R';
528
 
    footer.signature[2]  = 'U';
529
 
    footer.signature[3]  = 'E';
530
 
    footer.signature[4]  = 'V';
531
 
    footer.signature[5]  = 'I';
532
 
    footer.signature[6]  = 'S';
533
 
    footer.signature[7]  = 'I';
534
 
    footer.signature[8]  = 'O';
535
 
    footer.signature[9]  = 'N';
536
 
    footer.signature[10] = '-';
537
 
    footer.signature[11] = 'X';
538
 
    footer.signature[12] = 'F';
539
 
    footer.signature[13] = 'I';
540
 
    footer.signature[14] = 'L';
541
 
    footer.signature[15] = 'E';
542
 
    footer.dot = '.';
543
 
    footer.null = 0;
544
 
 
545
 
    fileStream.seekg(0, std::ios::beg);
546
 
    fileStream.write((char*) &header.id_length,           sizeof(header.id_length));        
547
 
    fileStream.write((char*) &header.colormap_type,       sizeof(header.colormap_type));
548
 
    fileStream.write((char*) &header.image_type,          sizeof(header.image_type));
549
 
    fileStream.write((char*) &header.colormap_index_lo,   sizeof(header.colormap_index_lo));
550
 
    fileStream.write((char*) &header.colormap_index_hi,   sizeof(header.colormap_index_hi));
551
 
    fileStream.write((char*) &header.colormap_length_lo,  sizeof(header.colormap_length_lo));
552
 
    fileStream.write((char*) &header.colormap_length_hi,  sizeof(header.colormap_length_hi));
553
 
    fileStream.write((char*) &header.colormap_size,       sizeof(header.colormap_size));
554
 
    fileStream.write((char*) &header.x_origin_lo,         sizeof(header.x_origin_lo));
555
 
    fileStream.write((char*) &header.x_origin_hi,         sizeof(header.x_origin_hi));
556
 
    fileStream.write((char*) &header.y_origin_lo,         sizeof(header.y_origin_lo));
557
 
    fileStream.write((char*) &header.y_origin_hi,         sizeof(header.y_origin_hi));
558
 
    fileStream.write((char*) &header.width_lo,            sizeof(header.width_lo));
559
 
    fileStream.write((char*) &header.width_hi,            sizeof(header.width_hi));
560
 
    fileStream.write((char*) &header.height_lo,           sizeof(header.height_lo));
561
 
    fileStream.write((char*) &header.height_hi,           sizeof(header.height_hi));
562
 
    fileStream.write((char*) &header.bpp,                 sizeof(header.bpp));
563
 
    fileStream.write((char*) &header.descriptor,          sizeof(header.descriptor));
564
 
 
565
 
    t_u32 i, j;
566
 
    for(j = 0; j < image->GetSurface(0).GetHeight(); j++)
567
 
    {
568
 
        for(i = 0; i < image->GetSurface(0).GetWidth(); i++)
569
 
        {
570
 
            t_u32 gba = image->GetSurface(0).Read(i, j);
571
 
            fileStream.write((char*) &gba, BPP);
572
 
        }
573
 
    }
574
 
 
575
 
    if(!fileStream.good())
576
 
    {
577
 
        fileStream.close();
578
 
        DEBUG_WARNING("error while writing TGA file");
579
 
        return HR_FILE_IO_FAIL;
580
 
    }
581
 
 
582
 
    fileStream.write((char*) &footer.extensionAreaOffset,         sizeof(footer.extensionAreaOffset));
583
 
    fileStream.write((char*) &footer.developerDirectoryOffset,    sizeof(footer.developerDirectoryOffset));
584
 
    fileStream.write((char*) &footer.signature,                   sizeof(footer.signature));
585
 
    fileStream.write((char*) &footer.dot,                         sizeof(footer.dot));
586
 
    fileStream.write((char*) &footer.null,                        sizeof(footer.null));
587
 
 
588
 
 
589
 
    fileStream.close();
590
 
    return HR_SUCCESS;
591
 
}
592
 
 
593
 
 
594
 
NAMESPACE_END
595
 
 
596
 
 
 
23
#include <sys/stat.h>
 
24
#include <iostream>
 
25
#include <fstream>
 
26
 
 
27
#include "NuxCore/NKernel.h"
 
28
#include "NuxCore/NStreamBuffer.h"
 
29
 
 
30
#include "Tga.h"
 
31
#include "BitmapFormats.h"
 
32
 
 
33
NAMESPACE_BEGIN
 
34
/* Load up a TGA file 
 
35
 
36
*Only recognizes the following types of Targas: 
 
37
*               Type 02 - Uncompressed RGB, 16, 24 or 32 bits 
 
38
*               Type 03 - Uncompressed grayscale, 8 bits
 
39
*               Type 10 - RLE-compressed RGB, 16, 24 or 32 bits
 
40
*               Type 11 - RLE-compressed grayscale, 8 bits  
 
41
* There are several other Targa formats unsupported by this function
 
42
*/
 
43
 
 
44
 
 
45
NBitmapData* read_tga_file(const TCHAR* file_name)
 
46
{
 
47
    std::ifstream fileStream;
 
48
    BYTE *tga_buffer, *tga_data_pointer;
 
49
    t_u32 datasize;
 
50
 
 
51
    tga_header header;
 
52
    tga_footer footer;
 
53
    t_u32 rle, footer_present; 
 
54
    
 
55
    if(!GFileManager.FileExist(file_name))
 
56
    {
 
57
        //nuxAssertMsg(0, TEXT("[read_tga_file] File not found: %s"), file_name);
 
58
        return 0;
 
59
    }
 
60
 
 
61
//    NUnZip UZ(TEXT("..\\inalogic.pak"));
 
62
//    NStreamBuffer *Stream = UZ.UnzipFileToStream(file_name);
 
63
//    std::istream fileStream(Stream);
 
64
 
 
65
    fileStream.open(file_name, std::ifstream::binary);        // open as binary
 
66
    if(!fileStream.is_open())
 
67
    {
 
68
        //nuxAssertMsg(0, TEXT("[read_tga_file] Can't open file: %s"), file_name);
 
69
        return 0;
 
70
    }
 
71
 
 
72
    fileStream.seekg( 0, std::ios::end);
 
73
    t_u32 filesize = fileStream.tellg();
 
74
    fileStream.seekg( 0, std::ios::beg);
 
75
 
 
76
 
 
77
    // Read the footer first 
 
78
    fileStream.seekg(-(TGA_FOOTER_SIZE), std::ios::end);
 
79
    fileStream.read((char*)(&footer.extensionAreaOffset), 4);
 
80
    fileStream.read((char*)(&footer.developerDirectoryOffset), 4);
 
81
    fileStream.read((char*)(&footer.signature), 16);
 
82
    fileStream.read((char*)(&footer.dot), 1);
 
83
    fileStream.read((char*)(&footer.null), 1);
 
84
    if(!fileStream.good())
 
85
    {
 
86
        fileStream.close();
 
87
        //nuxAssertMsg(0, TEXT("[read_tga_file] Error while reading the TGA footer: %s"), file_name);
 
88
        return 0;
 
89
    }
 
90
 
 
91
    // Check the footer to see if we have a v2.0 TGA file 
 
92
    footer_present = 0; 
 
93
    if(Memcmp(footer.signature, TGA_SIGNATURE, TGA_SIGNATURE_SIZE) == 0)
 
94
        footer_present = 1; 
 
95
 
 
96
    if(!footer_present)
 
97
    {
 
98
        // The footer is not present in TGA format version 1. this FILE supports only TGA format version 2.0
 
99
        // Here we also eliminate every file that is not really a tga format.
 
100
        //nuxAssertMsg(0, TEXT("[read_tga_file] This is not a TGA 2.0 file: %s"), file_name);
 
101
        fileStream.close();
 
102
        return 0;
 
103
    }
 
104
 
 
105
    // Read the header
 
106
    fileStream.seekg(0, std::ios::beg);
 
107
    fileStream.read((char*)(&header.id_length), 1);
 
108
    fileStream.read((char*)(&header.colormap_type), 1);
 
109
    fileStream.read((char*)(&header.image_type), 1);
 
110
    fileStream.read((char*)(&header.colormap_index_lo), 1);
 
111
    fileStream.read((char*)(&header.colormap_index_hi), 1);
 
112
    fileStream.read((char*)(&header.colormap_length_lo), 1);
 
113
    fileStream.read((char*)(&header.colormap_length_hi), 1);
 
114
    fileStream.read((char*)(&header.colormap_size), 1);
 
115
    fileStream.read((char*)(&header.x_origin_lo), 1);
 
116
    fileStream.read((char*)(&header.x_origin_hi), 1);
 
117
    fileStream.read((char*)(&header.y_origin_lo), 1);
 
118
    fileStream.read((char*)(&header.y_origin_hi), 1);
 
119
    fileStream.read((char*)(&header.width_lo), 1);
 
120
    fileStream.read((char*)(&header.width_hi), 1);
 
121
    fileStream.read((char*)(&header.height_lo), 1);
 
122
    fileStream.read((char*)(&header.height_hi), 1);
 
123
    fileStream.read((char*)(&header.bpp), 1);
 
124
    fileStream.read((char*)(&header.descriptor), 1);
 
125
    if(!fileStream.good())
 
126
    {
 
127
        fileStream.close();
 
128
        //nuxAssertMsg(0, TEXT("[read_tga_file] Error while reading the TGA header: %s"), file_name);
 
129
        return 0;
 
130
    }
 
131
 
 
132
    switch(header.image_type)
 
133
    {
 
134
    case TGA_COLORMAP:
 
135
    case TGA_COLOR:
 
136
    case TGA_GRAYSCALE:
 
137
        rle = 0;
 
138
        break;
 
139
 
 
140
    case TGA_RLE_COLORMAP:
 
141
    case TGA_RLE_COLOR:
 
142
    case TGA_RLE_GRAYSCALE:
 
143
        rle = 1;
 
144
        break;
 
145
 
 
146
    default:
 
147
        fileStream.close();
 
148
        //nuxAssertMsg(0, TEXT("[read_tga_file] Couldn't find the image type: %s"), file_name);
 
149
        return 0;
 
150
    }
 
151
 
 
152
 
 
153
    if(((header.image_type == TGA_COLORMAP) || (header.image_type == TGA_RLE_COLORMAP)) && header.colormap_type == 0)
 
154
    {
 
155
        // the image is pseudo color but there is no colormap
 
156
        // problem in file
 
157
        fileStream.close();
 
158
        //nuxAssertMsg(0, TEXT("[read_tga_file] Couldn't find the colormap: %s"), file_name);
 
159
        return 0;
 
160
    }
 
161
 
 
162
    if(header.image_type == TGA_COLORMAP || header.image_type == TGA_RLE_COLORMAP)
 
163
    {
 
164
        // Not supported
 
165
        fileStream.close();
 
166
        //nuxAssertMsg(0, TEXT("[read_tga_file] TGA colormap image is not supported: %s"), file_name);
 
167
        return 0;
 
168
    }
 
169
 
 
170
    t_u32 width, height;
 
171
    width  = header.width_hi << 8 |  header.width_lo;
 
172
    height = header.height_hi << 8 | header.height_lo;
 
173
 
 
174
    // Size of image data = file size - header size - id length - colormap size
 
175
    datasize = filesize - (TGA_HEADER_SIZE + header.id_length + 
 
176
        (header.colormap_length_hi << 8) + header.colormap_length_lo + (footer_present ? TGA_FOOTER_SIZE : 0));
 
177
 
 
178
    // Prepare the finale image
 
179
    BitmapFormat bitmap_format;
 
180
    if(header.bpp == 8)
 
181
        bitmap_format = BITFMT_A8;
 
182
    if(header.bpp == 16)
 
183
        bitmap_format = BITFMT_R5G6B5;
 
184
    if(header.bpp == 24)
 
185
        bitmap_format = BITFMT_R8G8B8;
 
186
    if(header.bpp == 32)
 
187
        bitmap_format = BITFMT_R8G8B8A8;
 
188
 
 
189
    NTextureData* TextureObjectData = new NTextureData(bitmap_format, (header.width_hi << 8) | (header.width_lo), (header.height_hi << 8) | (header.height_lo), 1);
 
190
 
 
191
    // Allocate memory for a temporary buffer
 
192
    tga_buffer = new BYTE[datasize];
 
193
    //memset(tga_buffer, 0, datasize);
 
194
 
 
195
    // Set the position to read image data
 
196
    fileStream.seekg(long(TGA_HEADER_SIZE + header.id_length + (header.colormap_length_hi << 8) + header.colormap_length_lo),
 
197
        std::ios::beg);
 
198
 
 
199
    // Read image data 
 
200
    fileStream.read((char*)tga_buffer, datasize);
 
201
    if(!fileStream.good())
 
202
    {
 
203
        fileStream.close();
 
204
        delete tga_buffer;
 
205
        //nuxAssertMsg(0, TEXT("[read_tga_file] Error while reading the TGA data: %s"), file_name);
 
206
        INL_SAFE_DELETE(TextureObjectData);
 
207
        return 0;
 
208
    }
 
209
 
 
210
    tga_data_pointer = tga_buffer;
 
211
    t_u32 position = 0;
 
212
 
 
213
    t_u32 image_width = TextureObjectData->GetSurface(0).GetWidth();
 
214
    t_u32 image_height = TextureObjectData->GetSurface(0).GetHeight();
 
215
 
 
216
    if(rle == 0)
 
217
    {
 
218
        t_u32 j, i;
 
219
        t_u32 position = 0;
 
220
        t_u32 value;
 
221
        for(j=0; j < image_height; j++)
 
222
        {
 
223
            for(i=0; i < image_width; i++)
 
224
            {
 
225
                // In TGA the MSB is RED and the LSB is BLUE
 
226
                switch(bitmap_format)
 
227
                {
 
228
                    // 32 bits RGBA pixels
 
229
                case BITFMT_R8G8B8A8: 
 
230
                    position = (j*image_width + i);
 
231
                    // store ARGB
 
232
                    value = (*((BYTE*)tga_data_pointer + 3) << 24) |    // a
 
233
                        (*((BYTE*)tga_data_pointer + 0) << 16) |                // b
 
234
                        (*((BYTE*)tga_data_pointer + 1) << 8) |             // g
 
235
                        *((BYTE*)tga_data_pointer + 2);                             // r
 
236
 
 
237
                    TextureObjectData->GetSurface(0).Write32b(i, j, value);
 
238
                    tga_data_pointer += 4;
 
239
                    break;      
 
240
 
 
241
                    // 24 bits RGB pixels
 
242
                case BITFMT_R8G8B8:
 
243
                    position = (j*image_width + i);
 
244
                    // store 0xff_RGB
 
245
                    value = (*((BYTE*)tga_data_pointer + 0) << 16) |    // b
 
246
                        (*((BYTE*)tga_data_pointer + 1) << 8) |             // g
 
247
                        *((BYTE*)tga_data_pointer + 2);                             // r
 
248
 
 
249
                    TextureObjectData->GetSurface(0).Write24b(i, j, value);
 
250
                    tga_data_pointer += 3;
 
251
                    break;      
 
252
 
 
253
                    // 16 bits RGB pixels
 
254
                case BITFMT_R5G6B5:
 
255
                    // FIXME: it seem the format is R5G5B5 and not R5G6B5
 
256
                    position = (j*image_width + i);
 
257
 
 
258
                    BYTE r, g, b;
 
259
                    value = ((BYTE)*((BYTE*)(tga_data_pointer+1)) << 8) | ((BYTE)*((BYTE*)(tga_data_pointer+0)));
 
260
 
 
261
                    // Photoshop saves a 16 bits BMP with 5 bits for each red, green and blue.
 
262
                    // We need to expand the green component to 6 bits.
 
263
                    b = (BYTE)(value & 0x1f);
 
264
                    g = (BYTE)( float((value & 0x3e0) >> 5) * 63.0f / 31.0f);  // expand green component from 5 bits to 6 bits
 
265
                    r = (BYTE)((value & 0x7c00) >> 10);
 
266
 
 
267
                    value = (r << 11) | (g << 5) | b;
 
268
 
 
269
                    TextureObjectData->GetSurface(0).Write16b(i, j, value);
 
270
                    tga_data_pointer += 2;
 
271
                    break;      
 
272
 
 
273
                    // 8 bits black & white (grayscale)
 
274
                case BITFMT_A8: 
 
275
                    position = (j*image_width + i);
 
276
                    value = *((BYTE*)tga_data_pointer+0);
 
277
                    TextureObjectData->GetSurface(0).Write8b(i, j, value);
 
278
                    tga_data_pointer += 1;
 
279
                    break;                      
 
280
                }
 
281
            }
 
282
        }
 
283
    }  
 
284
    else
 
285
    {
 
286
        UINT rep;
 
287
        UINT i = 0;
 
288
        UINT j = 0;
 
289
        UINT position = 0;
 
290
        UINT value;
 
291
        //unsigned BYTE *last_byte = buf_dest + 4*image->height*image->width; // last byte of destination image
 
292
 
 
293
        t_u32 size = TextureObjectData->GetSurface(0).GetWidth()*TextureObjectData->GetSurface(0).GetHeight();
 
294
        while(position < size)
 
295
        {
 
296
            t_u32 repetition_count = (*tga_data_pointer & 0x7f) + 1;
 
297
 
 
298
            if(*tga_data_pointer & 0x80)  // RLE Packet
 
299
            {
 
300
                tga_data_pointer++;  // tga_data_pointer point the pixel value
 
301
 
 
302
                // In TGA the MSB is RED and the LSB is BLUE
 
303
                switch(bitmap_format)
 
304
                {
 
305
                    // 32 bits RGBA pixels
 
306
                case BITFMT_R8G8B8A8:
 
307
                    for(rep=0; rep<repetition_count; rep++)
 
308
                    {
 
309
                        // store ARGB
 
310
                        value = (*((BYTE*)tga_data_pointer + 3) << 24) |        // a
 
311
                            (*((BYTE*)tga_data_pointer + 0) << 16) |            // b
 
312
                            (*((BYTE*)tga_data_pointer + 1) << 8) |                 // g
 
313
                            *((BYTE*)tga_data_pointer + 2);                                 // r
 
314
                        TextureObjectData->GetSurface(0).Write32b(i, j, value);
 
315
                        i++;if(i >= image_width) {j++;i = 0;}
 
316
                        position++;
 
317
                    }
 
318
                    tga_data_pointer += 4;
 
319
                    break;
 
320
 
 
321
                    // 24 bits RGB pixels
 
322
                case BITFMT_R8G8B8:
 
323
                    for(rep=0; rep<repetition_count; rep++)
 
324
                    {
 
325
                        value = (0xff << 24) |
 
326
                            (*((BYTE*)tga_data_pointer + 0) << 16) |        // b
 
327
                            (*((BYTE*)tga_data_pointer + 1) << 8) |                 // g
 
328
                            *((BYTE*)tga_data_pointer + 2);                                 // r
 
329
                        TextureObjectData->GetSurface(0).Write24b(i, j, value);
 
330
                        i++;if(i >= image_width) {j++;i = 0;}
 
331
                        position++;
 
332
                    }
 
333
                    tga_data_pointer += 3;
 
334
                    break;                        
 
335
 
 
336
                    // 16 bits RGB pixels
 
337
                case BITFMT_R5G6B5:
 
338
                    for(rep=0; rep<repetition_count; rep++)
 
339
                    {
 
340
                        // FIXME: it seem the format is R5G5B5 and not R5G6B5
 
341
                        BYTE r, g, b;
 
342
                        value = (*(tga_data_pointer+1) << 8) | (*(tga_data_pointer+0));
 
343
 
 
344
                        // Photoshop saves a 16 bits BMP with 5 bits for each red, green and blue.
 
345
                        // We need to expand the green component to 6 bits.
 
346
                        b = (BYTE)(value & 0x1f);
 
347
                        g = (BYTE)( float((value & 0x3e0) >> 5) * 63.0f / 31.0f);  // expand green component from 5 bits to 6 bits
 
348
                        r = (BYTE)((value & 0x7c00) >> 10);
 
349
                        value = (r << 11) | (g << 5) | b;
 
350
 
 
351
                        TextureObjectData->GetSurface(0).Write16b(i, j, value);
 
352
                        i++;if(i >= image_width) {j++;i = 0;}
 
353
                        position++;
 
354
                    }
 
355
                    tga_data_pointer += 2;
 
356
                    break;                                        
 
357
 
 
358
                    // 8 bits grayscale pixels
 
359
                case BITFMT_A8:
 
360
                    for(rep=0; rep<repetition_count; rep++)
 
361
                    {
 
362
                        value = *((BYTE*)tga_data_pointer + 0);
 
363
                        TextureObjectData->GetSurface(0).Write8b(i, j, value);
 
364
                        i++;if(i >= image_width) {j++;i = 0;}
 
365
                        position++;
 
366
                    }
 
367
                    tga_data_pointer += 1;
 
368
                    break;
 
369
                }
 
370
            }
 
371
            else  // raw packet
 
372
            {
 
373
                tga_data_pointer++;     // tga_data_pointer point the pixel value
 
374
 
 
375
                for(rep=0; rep<repetition_count; rep++)
 
376
                {
 
377
                    switch(bitmap_format)
 
378
                    {
 
379
                        // 32 bits RGBA pixels
 
380
                    case BITFMT_R8G8B8A8:
 
381
                        value = (*((BYTE*)tga_data_pointer + 3) << 24) |                //a
 
382
                            (*((BYTE*)tga_data_pointer + 0) << 16) |                    //r
 
383
                            (*((BYTE*)tga_data_pointer + 1) << 8) |                     //g
 
384
                            *((BYTE*)tga_data_pointer + 2);                                     //b
 
385
                        TextureObjectData->GetSurface(0).Write32b(i, j, value);
 
386
                        i++;if(i >= image_width) {j++;i = 0;}
 
387
                        position++;
 
388
                        tga_data_pointer += 4;
 
389
                        break;                            
 
390
 
 
391
                        // 24 bits RGB pixels
 
392
                    case BITFMT_R8G8B8:
 
393
                        value = (*((BYTE*)tga_data_pointer + 0) << 16) |        //r
 
394
                            (*((BYTE*)tga_data_pointer + 1) << 8) |             //g
 
395
                            *((BYTE*)tga_data_pointer + 2);                             //b
 
396
                        TextureObjectData->GetSurface(0).Write24b(i, j, value);
 
397
                        i++;if(i >= image_width) {j++;i = 0;}
 
398
                        position++;
 
399
                        tga_data_pointer += 3;
 
400
                        break;
 
401
 
 
402
                        // 16 bits RGB pixels
 
403
                    case BITFMT_R5G6B5:
 
404
                        // FIXME: it seem the format is R5G5B5 and not R5G6B5
 
405
                        BYTE r, g, b;
 
406
                        value = (*(tga_data_pointer+1) << 8) | (*(tga_data_pointer+0));
 
407
 
 
408
                        // Photoshop saves a 16 bits BMP with 5 bits for each red, green and blue.
 
409
                        // We need to expand the green component to 6 bits.
 
410
                        b = (BYTE)(value & 0x1f);
 
411
                        g = (BYTE)( float((value & 0x3e0) >> 5) * 63.0f / 31.0f);  // expand green component from 5 bits to 6 bits
 
412
                        r = (BYTE)((value & 0x7c00) >> 10);
 
413
                        value = (r << 11) | (g << 5) | b;
 
414
 
 
415
                        TextureObjectData->GetSurface(0).Write16b(i, j, value);
 
416
                        i++;if(i >= image_width) {j++;i = 0;}
 
417
                        position++;
 
418
                        tga_data_pointer += 2;
 
419
                        break;                                    
 
420
 
 
421
                        // 8 bits grayscale pixels
 
422
                    case BITFMT_A8:
 
423
                        value = *((BYTE*)tga_data_pointer + 0);
 
424
                        TextureObjectData->GetSurface(0).Write8b(i, j, value);
 
425
                        i++;if(i >= image_width) {j++;i = 0;}
 
426
                        position++;
 
427
                        tga_data_pointer += 1;
 
428
                        break;
 
429
                    }
 
430
                }
 
431
            }
 
432
        }
 
433
    }
 
434
 
 
435
    unsigned char flip = (header.descriptor & 0x30);
 
436
    switch(flip)
 
437
    {
 
438
    case 0x00:  // bottom left
 
439
        TextureObjectData->GetSurface(0).FlipVertical();
 
440
        break;
 
441
    case 0x10:  // bottom right
 
442
        TextureObjectData->GetSurface(0).FlipHorizontal();
 
443
        TextureObjectData->GetSurface(0).FlipVertical();
 
444
        break;
 
445
    case 0x20:  // top left
 
446
        // Ok
 
447
        break;
 
448
    case 0x30:  // top right
 
449
        TextureObjectData->GetSurface(0).FlipHorizontal();
 
450
        break;
 
451
    }
 
452
 
 
453
    delete [] tga_buffer;
 
454
    fileStream.close();
 
455
 
 
456
    return TextureObjectData;
 
457
}
 
458
 
 
459
HReport write_tga_file(const TCHAR* file_name, NBitmapData *image)
 
460
{
 
461
    std::fstream fileStream;
 
462
 
 
463
    t_u32 datasize;
 
464
    tga_header header;
 
465
    tga_footer footer;
 
466
 
 
467
    if(file_name == 0)
 
468
    {
 
469
        nuxAssertMsg(0, TEXT("[write_tga_file] Incorrect file name."));
 
470
        return HR_INVALID_ARG;
 
471
    }
 
472
    /*if(image->get_format() != BITFMT_R8G8B8)
 
473
    {
 
474
        DEBUG_WARNING("Unsupported format");
 
475
        return HR_INVALID_ARG;
 
476
    }*/
 
477
 
 
478
        fileStream.open(file_name, std::fstream::out | std::fstream::binary);                  // open as binary
 
479
    if(!fileStream.is_open())
 
480
    {
 
481
        fprintf(stderr, "Open file %s failed", file_name);
 
482
        DEBUG_WARNING("cannot open file");
 
483
        return HR_FILE_IO_FAIL;
 
484
    }
 
485
 
 
486
    t_u32 BPP = 3;
 
487
    if(image->GetSurface(0).GetFormat() == BITFMT_R8G8B8 ||
 
488
        image->GetSurface(0).GetFormat() == BITFMT_B8G8R8)
 
489
    {
 
490
        datasize = image->GetSurface(0).GetWidth() * image->GetSurface(0).GetHeight() * 3;
 
491
        BPP = 3;
 
492
    }
 
493
 
 
494
    if(image->GetSurface(0).GetFormat() == BITFMT_A8R8G8B8 ||
 
495
        image->GetSurface(0).GetFormat() == BITFMT_B8G8R8A8 ||
 
496
        image->GetSurface(0).GetFormat() == BITFMT_R8G8B8A8 ||
 
497
        image->GetSurface(0).GetFormat() == BITFMT_A8B8G8R8)
 
498
    {
 
499
        datasize = image->GetSurface(0).GetWidth() * image->GetSurface(0).GetHeight() * 4;
 
500
        BPP = 4;
 
501
    }
 
502
 
 
503
 
 
504
    header.id_length = 0;
 
505
    header.colormap_type = 0;
 
506
    header.image_type = 2;                  // uncompressed True-Color
 
507
    header.colormap_index_lo = 0;
 
508
    header.colormap_index_hi = 0;
 
509
    header.colormap_length_lo = 0;
 
510
    header.colormap_length_hi = 0;
 
511
    header.colormap_size = 0;
 
512
    header.x_origin_lo = 0;
 
513
    header.x_origin_hi = 0;
 
514
    header.y_origin_lo = 0;
 
515
    header.y_origin_hi = 0;
 
516
    header.width_lo = image->GetSurface(0).GetWidth() & 0xff;
 
517
    header.width_hi = (image->GetSurface(0).GetWidth() & 0xff00) >> 8;
 
518
    header.height_lo = image->GetSurface(0).GetHeight() & 0xff;;
 
519
    header.height_hi = (image->GetSurface(0).GetHeight() & 0xff00) >> 8;
 
520
    header.bpp = BPP * 8;                          // 16, 24 or 32 bpp
 
521
    header.descriptor = 2 << 4;               // top left
 
522
 
 
523
 
 
524
    footer.extensionAreaOffset = 0;
 
525
    footer.developerDirectoryOffset = 0;
 
526
    footer.signature[0]  = 'T';
 
527
    footer.signature[1]  = 'R';
 
528
    footer.signature[2]  = 'U';
 
529
    footer.signature[3]  = 'E';
 
530
    footer.signature[4]  = 'V';
 
531
    footer.signature[5]  = 'I';
 
532
    footer.signature[6]  = 'S';
 
533
    footer.signature[7]  = 'I';
 
534
    footer.signature[8]  = 'O';
 
535
    footer.signature[9]  = 'N';
 
536
    footer.signature[10] = '-';
 
537
    footer.signature[11] = 'X';
 
538
    footer.signature[12] = 'F';
 
539
    footer.signature[13] = 'I';
 
540
    footer.signature[14] = 'L';
 
541
    footer.signature[15] = 'E';
 
542
    footer.dot = '.';
 
543
    footer.null = 0;
 
544
 
 
545
    fileStream.seekg(0, std::ios::beg);
 
546
    fileStream.write((char*) &header.id_length,           sizeof(header.id_length));        
 
547
    fileStream.write((char*) &header.colormap_type,       sizeof(header.colormap_type));
 
548
    fileStream.write((char*) &header.image_type,          sizeof(header.image_type));
 
549
    fileStream.write((char*) &header.colormap_index_lo,   sizeof(header.colormap_index_lo));
 
550
    fileStream.write((char*) &header.colormap_index_hi,   sizeof(header.colormap_index_hi));
 
551
    fileStream.write((char*) &header.colormap_length_lo,  sizeof(header.colormap_length_lo));
 
552
    fileStream.write((char*) &header.colormap_length_hi,  sizeof(header.colormap_length_hi));
 
553
    fileStream.write((char*) &header.colormap_size,       sizeof(header.colormap_size));
 
554
    fileStream.write((char*) &header.x_origin_lo,         sizeof(header.x_origin_lo));
 
555
    fileStream.write((char*) &header.x_origin_hi,         sizeof(header.x_origin_hi));
 
556
    fileStream.write((char*) &header.y_origin_lo,         sizeof(header.y_origin_lo));
 
557
    fileStream.write((char*) &header.y_origin_hi,         sizeof(header.y_origin_hi));
 
558
    fileStream.write((char*) &header.width_lo,            sizeof(header.width_lo));
 
559
    fileStream.write((char*) &header.width_hi,            sizeof(header.width_hi));
 
560
    fileStream.write((char*) &header.height_lo,           sizeof(header.height_lo));
 
561
    fileStream.write((char*) &header.height_hi,           sizeof(header.height_hi));
 
562
    fileStream.write((char*) &header.bpp,                 sizeof(header.bpp));
 
563
    fileStream.write((char*) &header.descriptor,          sizeof(header.descriptor));
 
564
 
 
565
    t_u32 i, j;
 
566
    for(j = 0; j < image->GetSurface(0).GetHeight(); j++)
 
567
    {
 
568
        for(i = 0; i < image->GetSurface(0).GetWidth(); i++)
 
569
        {
 
570
            t_u32 gba = image->GetSurface(0).Read(i, j);
 
571
            fileStream.write((char*) &gba, BPP);
 
572
        }
 
573
    }
 
574
 
 
575
    if(!fileStream.good())
 
576
    {
 
577
        fileStream.close();
 
578
        DEBUG_WARNING("error while writing TGA file");
 
579
        return HR_FILE_IO_FAIL;
 
580
    }
 
581
 
 
582
    fileStream.write((char*) &footer.extensionAreaOffset,         sizeof(footer.extensionAreaOffset));
 
583
    fileStream.write((char*) &footer.developerDirectoryOffset,    sizeof(footer.developerDirectoryOffset));
 
584
    fileStream.write((char*) &footer.signature,                   sizeof(footer.signature));
 
585
    fileStream.write((char*) &footer.dot,                         sizeof(footer.dot));
 
586
    fileStream.write((char*) &footer.null,                        sizeof(footer.null));
 
587
 
 
588
 
 
589
    fileStream.close();
 
590
    return HR_SUCCESS;
 
591
}
 
592
 
 
593
 
 
594
NAMESPACE_END
 
595
 
 
596