129 lines
3.0 KiB
C++
129 lines
3.0 KiB
C++
#include "stdafx.h"
|
|
|
|
#include "filemanip.h"
|
|
|
|
// Ensure there's no padding added into the struct,
|
|
// in a very non-portable way
|
|
#ifdef _WIN32
|
|
#pragma pack(push)
|
|
#pragma pack(1)
|
|
#endif
|
|
|
|
typedef struct
|
|
{
|
|
char identsize; // size of ID field that follows 18 byte header (0 usually)
|
|
char colourmaptype; // type of colour map 0=none, 1=has palette
|
|
char imagetype; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed
|
|
|
|
short colourmapstart; // first colour map entry in palette
|
|
short colourmaplength; // number of colours in palette
|
|
char colourmapbits; // number of bits per palette entry 15,16,24,32
|
|
|
|
short xstart; // image x origin
|
|
short ystart; // image y origin
|
|
short width; // image width in pixels
|
|
short height; // image height in pixels
|
|
char bits; // image bits per pixel 8,16,24,32
|
|
char descriptor; // image descriptor bits (vh flip bits)
|
|
#ifdef _WIN32
|
|
} TGA_HEADER;
|
|
# pragma pack(pop)
|
|
#else
|
|
} __attribute__ ((packed)) TGA_HEADER;
|
|
#endif
|
|
|
|
// Convert the RGB image to 8-bit greyscale and output
|
|
void RGB_OutputGreyscaleTGA(unsigned char* image_data, int width, int height, int pitch, wxFFile& file)
|
|
{
|
|
assert(sizeof(TGA_HEADER) == 18);
|
|
|
|
TGA_HEADER header;
|
|
|
|
header.identsize = 0;
|
|
header.colourmaptype = 0;
|
|
header.imagetype = 3;
|
|
header.xstart = 0;
|
|
header.ystart = 0;
|
|
header.width = (short)width;
|
|
header.height = (short)height;
|
|
header.bits = 8;
|
|
header.descriptor = 0;
|
|
|
|
file.Write(&header, sizeof(header));
|
|
|
|
// Start from the bottom, so things look the right way up
|
|
image_data += height*pitch;
|
|
|
|
for (int y = 0; y < height; ++y)
|
|
{
|
|
image_data -= pitch;
|
|
|
|
for (int x = 0; x < width; ++x)
|
|
file.Write(&image_data[x*3], 1);
|
|
}
|
|
}
|
|
|
|
std::set<wchar_t> AnalyseChars(wxString filename)
|
|
{
|
|
wxFFile File (filename, "rb");
|
|
if (! File.IsOpened())
|
|
throw "Cannot open file";
|
|
|
|
enum {
|
|
UNKNOWN,
|
|
UTF8,
|
|
UTF16SE, // same-endian as this machine
|
|
UTF16DE // different-endian
|
|
} Format = UNKNOWN;
|
|
|
|
unsigned short BOM;
|
|
File.Read(&BOM, 2);
|
|
if (BOM == 0xFEFF)
|
|
Format = UTF16SE;
|
|
else if (BOM == 0xFFFE)
|
|
Format = UTF16DE;
|
|
else {
|
|
// Make an educated guess based on the first byte
|
|
// If it's like "_\0" it's probably little-endian,
|
|
// if it's like "\0_" it's probably big-endian
|
|
if ((BOM & 0xFF00) == 0)
|
|
Format = UTF16SE;
|
|
else if ((BOM & 0x00FF) == 0)
|
|
Format = UTF16DE;
|
|
else
|
|
throw "Can't determine endianness of source file - make sure it's UTF16 and starts with a simple letter";
|
|
// (Maybe it's UTF8, but I don't want to bother with that)
|
|
|
|
File.Seek(0); // Make sure the first character is included in the list
|
|
}
|
|
|
|
std::set<wchar_t> Chars;
|
|
if (Format == UTF16SE)
|
|
{
|
|
wchar_t c;
|
|
while (! File.Eof())
|
|
{
|
|
File.Read(&c, 2);
|
|
if (c != '\r' && c != '\n')
|
|
Chars.insert(c);
|
|
}
|
|
}
|
|
else if (Format == UTF16DE)
|
|
{
|
|
unsigned short c;
|
|
while (! File.Eof())
|
|
{
|
|
if (File.Read(&c, 2) != 2) break; // abort if failed (i.e. eof)
|
|
c = (c>>8)|((c&0xff)<<8); // swap bytes
|
|
if (c != '\r' && c != '\n')
|
|
Chars.insert(c);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw "Internal error - invalid file format";
|
|
}
|
|
|
|
return Chars;
|
|
}
|