27
#include "NuxCore/NKernel.h"
28
#include "NuxCore/NStreamBuffer.h"
31
#include "BitmapFormats.h"
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
45
NBitmapData* read_tga_file(const TCHAR* file_name)
47
std::ifstream fileStream;
48
BYTE *tga_buffer, *tga_data_pointer;
53
t_u32 rle, footer_present;
55
if(!GFileManager.FileExist(file_name))
57
//nuxAssertMsg(0, TEXT("[read_tga_file] File not found: %s"), file_name);
61
// NUnZip UZ(TEXT("..\\inalogic.pak"));
62
// NStreamBuffer *Stream = UZ.UnzipFileToStream(file_name);
63
// std::istream fileStream(Stream);
65
fileStream.open(file_name, std::ifstream::binary); // open as binary
66
if(!fileStream.is_open())
68
//nuxAssertMsg(0, TEXT("[read_tga_file] Can't open file: %s"), file_name);
72
fileStream.seekg( 0, std::ios::end);
73
t_u32 filesize = fileStream.tellg();
74
fileStream.seekg( 0, std::ios::beg);
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())
87
//nuxAssertMsg(0, TEXT("[read_tga_file] Error while reading the TGA footer: %s"), file_name);
91
// Check the footer to see if we have a v2.0 TGA file
93
if(Memcmp(footer.signature, TGA_SIGNATURE, TGA_SIGNATURE_SIZE) == 0)
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);
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())
128
//nuxAssertMsg(0, TEXT("[read_tga_file] Error while reading the TGA header: %s"), file_name);
132
switch(header.image_type)
140
case TGA_RLE_COLORMAP:
142
case TGA_RLE_GRAYSCALE:
148
//nuxAssertMsg(0, TEXT("[read_tga_file] Couldn't find the image type: %s"), file_name);
153
if(((header.image_type == TGA_COLORMAP) || (header.image_type == TGA_RLE_COLORMAP)) && header.colormap_type == 0)
155
// the image is pseudo color but there is no colormap
158
//nuxAssertMsg(0, TEXT("[read_tga_file] Couldn't find the colormap: %s"), file_name);
162
if(header.image_type == TGA_COLORMAP || header.image_type == TGA_RLE_COLORMAP)
166
//nuxAssertMsg(0, TEXT("[read_tga_file] TGA colormap image is not supported: %s"), file_name);
171
width = header.width_hi << 8 | header.width_lo;
172
height = header.height_hi << 8 | header.height_lo;
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));
178
// Prepare the finale image
179
BitmapFormat bitmap_format;
181
bitmap_format = BITFMT_A8;
183
bitmap_format = BITFMT_R5G6B5;
185
bitmap_format = BITFMT_R8G8B8;
187
bitmap_format = BITFMT_R8G8B8A8;
189
NTextureData* TextureObjectData = new NTextureData(bitmap_format, (header.width_hi << 8) | (header.width_lo), (header.height_hi << 8) | (header.height_lo), 1);
191
// Allocate memory for a temporary buffer
192
tga_buffer = new BYTE[datasize];
193
//memset(tga_buffer, 0, datasize);
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),
200
fileStream.read((char*)tga_buffer, datasize);
201
if(!fileStream.good())
205
//nuxAssertMsg(0, TEXT("[read_tga_file] Error while reading the TGA data: %s"), file_name);
206
INL_SAFE_DELETE(TextureObjectData);
210
tga_data_pointer = tga_buffer;
213
t_u32 image_width = TextureObjectData->GetSurface(0).GetWidth();
214
t_u32 image_height = TextureObjectData->GetSurface(0).GetHeight();
221
for(j=0; j < image_height; j++)
223
for(i=0; i < image_width; i++)
225
// In TGA the MSB is RED and the LSB is BLUE
226
switch(bitmap_format)
228
// 32 bits RGBA pixels
229
case BITFMT_R8G8B8A8:
230
position = (j*image_width + i);
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
237
TextureObjectData->GetSurface(0).Write32b(i, j, value);
238
tga_data_pointer += 4;
241
// 24 bits RGB pixels
243
position = (j*image_width + i);
245
value = (*((BYTE*)tga_data_pointer + 0) << 16) | // b
246
(*((BYTE*)tga_data_pointer + 1) << 8) | // g
247
*((BYTE*)tga_data_pointer + 2); // r
249
TextureObjectData->GetSurface(0).Write24b(i, j, value);
250
tga_data_pointer += 3;
253
// 16 bits RGB pixels
255
// FIXME: it seem the format is R5G5B5 and not R5G6B5
256
position = (j*image_width + i);
259
value = ((BYTE)*((BYTE*)(tga_data_pointer+1)) << 8) | ((BYTE)*((BYTE*)(tga_data_pointer+0)));
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);
267
value = (r << 11) | (g << 5) | b;
269
TextureObjectData->GetSurface(0).Write16b(i, j, value);
270
tga_data_pointer += 2;
273
// 8 bits black & white (grayscale)
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;
291
//unsigned BYTE *last_byte = buf_dest + 4*image->height*image->width; // last byte of destination image
293
t_u32 size = TextureObjectData->GetSurface(0).GetWidth()*TextureObjectData->GetSurface(0).GetHeight();
294
while(position < size)
296
t_u32 repetition_count = (*tga_data_pointer & 0x7f) + 1;
298
if(*tga_data_pointer & 0x80) // RLE Packet
300
tga_data_pointer++; // tga_data_pointer point the pixel value
302
// In TGA the MSB is RED and the LSB is BLUE
303
switch(bitmap_format)
305
// 32 bits RGBA pixels
306
case BITFMT_R8G8B8A8:
307
for(rep=0; rep<repetition_count; rep++)
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;}
318
tga_data_pointer += 4;
321
// 24 bits RGB pixels
323
for(rep=0; rep<repetition_count; rep++)
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;}
333
tga_data_pointer += 3;
336
// 16 bits RGB pixels
338
for(rep=0; rep<repetition_count; rep++)
340
// FIXME: it seem the format is R5G5B5 and not R5G6B5
342
value = (*(tga_data_pointer+1) << 8) | (*(tga_data_pointer+0));
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;
351
TextureObjectData->GetSurface(0).Write16b(i, j, value);
352
i++;if(i >= image_width) {j++;i = 0;}
355
tga_data_pointer += 2;
358
// 8 bits grayscale pixels
360
for(rep=0; rep<repetition_count; rep++)
362
value = *((BYTE*)tga_data_pointer + 0);
363
TextureObjectData->GetSurface(0).Write8b(i, j, value);
364
i++;if(i >= image_width) {j++;i = 0;}
367
tga_data_pointer += 1;
373
tga_data_pointer++; // tga_data_pointer point the pixel value
375
for(rep=0; rep<repetition_count; rep++)
377
switch(bitmap_format)
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;}
388
tga_data_pointer += 4;
391
// 24 bits RGB pixels
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;}
399
tga_data_pointer += 3;
402
// 16 bits RGB pixels
404
// FIXME: it seem the format is R5G5B5 and not R5G6B5
406
value = (*(tga_data_pointer+1) << 8) | (*(tga_data_pointer+0));
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;
415
TextureObjectData->GetSurface(0).Write16b(i, j, value);
416
i++;if(i >= image_width) {j++;i = 0;}
418
tga_data_pointer += 2;
421
// 8 bits grayscale pixels
423
value = *((BYTE*)tga_data_pointer + 0);
424
TextureObjectData->GetSurface(0).Write8b(i, j, value);
425
i++;if(i >= image_width) {j++;i = 0;}
427
tga_data_pointer += 1;
435
unsigned char flip = (header.descriptor & 0x30);
438
case 0x00: // bottom left
439
TextureObjectData->GetSurface(0).FlipVertical();
441
case 0x10: // bottom right
442
TextureObjectData->GetSurface(0).FlipHorizontal();
443
TextureObjectData->GetSurface(0).FlipVertical();
445
case 0x20: // top left
448
case 0x30: // top right
449
TextureObjectData->GetSurface(0).FlipHorizontal();
453
delete [] tga_buffer;
456
return TextureObjectData;
459
HReport write_tga_file(const TCHAR* file_name, NBitmapData *image)
461
std::fstream fileStream;
469
nuxAssertMsg(0, TEXT("[write_tga_file] Incorrect file name."));
470
return HR_INVALID_ARG;
472
/*if(image->get_format() != BITFMT_R8G8B8)
474
DEBUG_WARNING("Unsupported format");
475
return HR_INVALID_ARG;
478
fileStream.open(file_name, std::fstream::out | std::fstream::binary); // open as binary
479
if(!fileStream.is_open())
481
fprintf(stderr, "Open file %s failed", file_name);
482
DEBUG_WARNING("cannot open file");
483
return HR_FILE_IO_FAIL;
487
if(image->GetSurface(0).GetFormat() == BITFMT_R8G8B8 ||
488
image->GetSurface(0).GetFormat() == BITFMT_B8G8R8)
490
datasize = image->GetSurface(0).GetWidth() * image->GetSurface(0).GetHeight() * 3;
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)
499
datasize = image->GetSurface(0).GetWidth() * image->GetSurface(0).GetHeight() * 4;
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
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';
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));
566
for(j = 0; j < image->GetSurface(0).GetHeight(); j++)
568
for(i = 0; i < image->GetSurface(0).GetWidth(); i++)
570
t_u32 gba = image->GetSurface(0).Read(i, j);
571
fileStream.write((char*) &gba, BPP);
575
if(!fileStream.good())
578
DEBUG_WARNING("error while writing TGA file");
579
return HR_FILE_IO_FAIL;
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));
27
#include "NuxCore/NKernel.h"
28
#include "NuxCore/NStreamBuffer.h"
31
#include "BitmapFormats.h"
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
45
NBitmapData* read_tga_file(const TCHAR* file_name)
47
std::ifstream fileStream;
48
BYTE *tga_buffer, *tga_data_pointer;
53
t_u32 rle, footer_present;
55
if(!GFileManager.FileExist(file_name))
57
//nuxAssertMsg(0, TEXT("[read_tga_file] File not found: %s"), file_name);
61
// NUnZip UZ(TEXT("..\\inalogic.pak"));
62
// NStreamBuffer *Stream = UZ.UnzipFileToStream(file_name);
63
// std::istream fileStream(Stream);
65
fileStream.open(file_name, std::ifstream::binary); // open as binary
66
if(!fileStream.is_open())
68
//nuxAssertMsg(0, TEXT("[read_tga_file] Can't open file: %s"), file_name);
72
fileStream.seekg( 0, std::ios::end);
73
t_u32 filesize = fileStream.tellg();
74
fileStream.seekg( 0, std::ios::beg);
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())
87
//nuxAssertMsg(0, TEXT("[read_tga_file] Error while reading the TGA footer: %s"), file_name);
91
// Check the footer to see if we have a v2.0 TGA file
93
if(Memcmp(footer.signature, TGA_SIGNATURE, TGA_SIGNATURE_SIZE) == 0)
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);
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())
128
//nuxAssertMsg(0, TEXT("[read_tga_file] Error while reading the TGA header: %s"), file_name);
132
switch(header.image_type)
140
case TGA_RLE_COLORMAP:
142
case TGA_RLE_GRAYSCALE:
148
//nuxAssertMsg(0, TEXT("[read_tga_file] Couldn't find the image type: %s"), file_name);
153
if(((header.image_type == TGA_COLORMAP) || (header.image_type == TGA_RLE_COLORMAP)) && header.colormap_type == 0)
155
// the image is pseudo color but there is no colormap
158
//nuxAssertMsg(0, TEXT("[read_tga_file] Couldn't find the colormap: %s"), file_name);
162
if(header.image_type == TGA_COLORMAP || header.image_type == TGA_RLE_COLORMAP)
166
//nuxAssertMsg(0, TEXT("[read_tga_file] TGA colormap image is not supported: %s"), file_name);
171
width = header.width_hi << 8 | header.width_lo;
172
height = header.height_hi << 8 | header.height_lo;
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));
178
// Prepare the finale image
179
BitmapFormat bitmap_format;
181
bitmap_format = BITFMT_A8;
183
bitmap_format = BITFMT_R5G6B5;
185
bitmap_format = BITFMT_R8G8B8;
187
bitmap_format = BITFMT_R8G8B8A8;
189
NTextureData* TextureObjectData = new NTextureData(bitmap_format, (header.width_hi << 8) | (header.width_lo), (header.height_hi << 8) | (header.height_lo), 1);
191
// Allocate memory for a temporary buffer
192
tga_buffer = new BYTE[datasize];
193
//memset(tga_buffer, 0, datasize);
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),
200
fileStream.read((char*)tga_buffer, datasize);
201
if(!fileStream.good())
205
//nuxAssertMsg(0, TEXT("[read_tga_file] Error while reading the TGA data: %s"), file_name);
206
INL_SAFE_DELETE(TextureObjectData);
210
tga_data_pointer = tga_buffer;
213
t_u32 image_width = TextureObjectData->GetSurface(0).GetWidth();
214
t_u32 image_height = TextureObjectData->GetSurface(0).GetHeight();
221
for(j=0; j < image_height; j++)
223
for(i=0; i < image_width; i++)
225
// In TGA the MSB is RED and the LSB is BLUE
226
switch(bitmap_format)
228
// 32 bits RGBA pixels
229
case BITFMT_R8G8B8A8:
230
position = (j*image_width + i);
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
237
TextureObjectData->GetSurface(0).Write32b(i, j, value);
238
tga_data_pointer += 4;
241
// 24 bits RGB pixels
243
position = (j*image_width + i);
245
value = (*((BYTE*)tga_data_pointer + 0) << 16) | // b
246
(*((BYTE*)tga_data_pointer + 1) << 8) | // g
247
*((BYTE*)tga_data_pointer + 2); // r
249
TextureObjectData->GetSurface(0).Write24b(i, j, value);
250
tga_data_pointer += 3;
253
// 16 bits RGB pixels
255
// FIXME: it seem the format is R5G5B5 and not R5G6B5
256
position = (j*image_width + i);
259
value = ((BYTE)*((BYTE*)(tga_data_pointer+1)) << 8) | ((BYTE)*((BYTE*)(tga_data_pointer+0)));
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);
267
value = (r << 11) | (g << 5) | b;
269
TextureObjectData->GetSurface(0).Write16b(i, j, value);
270
tga_data_pointer += 2;
273
// 8 bits black & white (grayscale)
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;
291
//unsigned BYTE *last_byte = buf_dest + 4*image->height*image->width; // last byte of destination image
293
t_u32 size = TextureObjectData->GetSurface(0).GetWidth()*TextureObjectData->GetSurface(0).GetHeight();
294
while(position < size)
296
t_u32 repetition_count = (*tga_data_pointer & 0x7f) + 1;
298
if(*tga_data_pointer & 0x80) // RLE Packet
300
tga_data_pointer++; // tga_data_pointer point the pixel value
302
// In TGA the MSB is RED and the LSB is BLUE
303
switch(bitmap_format)
305
// 32 bits RGBA pixels
306
case BITFMT_R8G8B8A8:
307
for(rep=0; rep<repetition_count; rep++)
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;}
318
tga_data_pointer += 4;
321
// 24 bits RGB pixels
323
for(rep=0; rep<repetition_count; rep++)
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;}
333
tga_data_pointer += 3;
336
// 16 bits RGB pixels
338
for(rep=0; rep<repetition_count; rep++)
340
// FIXME: it seem the format is R5G5B5 and not R5G6B5
342
value = (*(tga_data_pointer+1) << 8) | (*(tga_data_pointer+0));
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;
351
TextureObjectData->GetSurface(0).Write16b(i, j, value);
352
i++;if(i >= image_width) {j++;i = 0;}
355
tga_data_pointer += 2;
358
// 8 bits grayscale pixels
360
for(rep=0; rep<repetition_count; rep++)
362
value = *((BYTE*)tga_data_pointer + 0);
363
TextureObjectData->GetSurface(0).Write8b(i, j, value);
364
i++;if(i >= image_width) {j++;i = 0;}
367
tga_data_pointer += 1;
373
tga_data_pointer++; // tga_data_pointer point the pixel value
375
for(rep=0; rep<repetition_count; rep++)
377
switch(bitmap_format)
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;}
388
tga_data_pointer += 4;
391
// 24 bits RGB pixels
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;}
399
tga_data_pointer += 3;
402
// 16 bits RGB pixels
404
// FIXME: it seem the format is R5G5B5 and not R5G6B5
406
value = (*(tga_data_pointer+1) << 8) | (*(tga_data_pointer+0));
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;
415
TextureObjectData->GetSurface(0).Write16b(i, j, value);
416
i++;if(i >= image_width) {j++;i = 0;}
418
tga_data_pointer += 2;
421
// 8 bits grayscale pixels
423
value = *((BYTE*)tga_data_pointer + 0);
424
TextureObjectData->GetSurface(0).Write8b(i, j, value);
425
i++;if(i >= image_width) {j++;i = 0;}
427
tga_data_pointer += 1;
435
unsigned char flip = (header.descriptor & 0x30);
438
case 0x00: // bottom left
439
TextureObjectData->GetSurface(0).FlipVertical();
441
case 0x10: // bottom right
442
TextureObjectData->GetSurface(0).FlipHorizontal();
443
TextureObjectData->GetSurface(0).FlipVertical();
445
case 0x20: // top left
448
case 0x30: // top right
449
TextureObjectData->GetSurface(0).FlipHorizontal();
453
delete [] tga_buffer;
456
return TextureObjectData;
459
HReport write_tga_file(const TCHAR* file_name, NBitmapData *image)
461
std::fstream fileStream;
469
nuxAssertMsg(0, TEXT("[write_tga_file] Incorrect file name."));
470
return HR_INVALID_ARG;
472
/*if(image->get_format() != BITFMT_R8G8B8)
474
DEBUG_WARNING("Unsupported format");
475
return HR_INVALID_ARG;
478
fileStream.open(file_name, std::fstream::out | std::fstream::binary); // open as binary
479
if(!fileStream.is_open())
481
fprintf(stderr, "Open file %s failed", file_name);
482
DEBUG_WARNING("cannot open file");
483
return HR_FILE_IO_FAIL;
487
if(image->GetSurface(0).GetFormat() == BITFMT_R8G8B8 ||
488
image->GetSurface(0).GetFormat() == BITFMT_B8G8R8)
490
datasize = image->GetSurface(0).GetWidth() * image->GetSurface(0).GetHeight() * 3;
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)
499
datasize = image->GetSurface(0).GetWidth() * image->GetSurface(0).GetHeight() * 4;
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
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';
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));
566
for(j = 0; j < image->GetSurface(0).GetHeight(); j++)
568
for(i = 0; i < image->GetSurface(0).GetWidth(); i++)
570
t_u32 gba = image->GetSurface(0).Read(i, j);
571
fileStream.write((char*) &gba, BPP);
575
if(!fileStream.good())
578
DEBUG_WARNING("error while writing TGA file");
579
return HR_FILE_IO_FAIL;
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));