Created
October 1, 2011 22:16
-
-
Save gamefreak/1256727 to your computer and use it in GitHub Desktop.
Partial PICT decoder for eventual use in Athena
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// main.cpp | |
// pictdecoder | |
// | |
// Created by Scott McClaugherty on 9/30/11. | |
// Copyright 2011 __MyCompanyName__. All rights reserved. | |
// | |
#include <iostream> | |
#include <fstream> | |
#include <assert.h> | |
#include <unistd.h> | |
#include <arpa/inet.h> | |
class bifstream : public std::ifstream { | |
public: | |
bifstream(const char *filename, ios_base::openmode mode = ios_base::in): std::ifstream(filename, mode) {} | |
bifstream& operator>> (char& val ) { | |
std::ifstream::read(&val, sizeof(char&)); | |
return *this; | |
} | |
bifstream& operator>> (unsigned char& val ) { | |
std::ifstream::read((char*)&val, sizeof(unsigned char&)); | |
return *this; | |
} | |
bifstream& operator>> (short& val ) { | |
char block[sizeof(short&)]; | |
std::ifstream::read(block, sizeof(short&)); | |
val = ntohs(*(short *)block); | |
return *this; | |
} | |
bifstream& operator>> (unsigned short& val ) { | |
char block[sizeof(unsigned short&)]; | |
std::ifstream::read(block, sizeof(unsigned short&)); | |
val = ntohs(*(unsigned short *)block); | |
return *this; | |
} | |
bifstream& operator>> (int& val ) { | |
char block[sizeof(int)]; | |
std::ifstream::read(block, sizeof(int&)); | |
val = ntohl(*(int*)block); | |
return *this; | |
} | |
bifstream& operator>> (unsigned int& val ){ | |
char block[sizeof(unsigned int)]; | |
std::ifstream::read(block, sizeof(unsigned int&)); | |
val = ntohl(*(unsigned int*)block); | |
return *this; | |
} | |
}; | |
class bofstream : public std::ofstream { | |
public: | |
bofstream(const char *filename, ios_base::openmode mode = ios_base::out | ios_base::trunc | ios_base::binary): std::ofstream(filename, mode) {} | |
// bofstream& operator<< (char& val ) { | |
// std::ofstream::write(&val, sizeof(char&)); | |
// return *this; | |
// } | |
bofstream& operator<< (char val ) { | |
std::ofstream::write(&val, sizeof(char&)); | |
return *this; | |
} | |
// bofstream& operator<< (unsigned char& val ) { | |
// std::ofstream::write((char*)&val, sizeof(unsigned char&)); | |
// return *this; | |
// } | |
bofstream& operator<< (unsigned char val ) { | |
std::ofstream::write((char*)&val, sizeof(unsigned char&)); | |
return *this; | |
} | |
// bofstream& operator<< (short& val ) { | |
// short v = htons(val); | |
// std::ofstream::write((char*)&v, sizeof(short&)); | |
// return *this; | |
// } | |
bofstream& operator<< (short val ) { | |
short v = htons(val); | |
std::ofstream::write((char*)&v, sizeof(short&)); | |
return *this; | |
} | |
// bofstream& operator<< (unsigned short& val ) { | |
// unsigned short v = htons(val); | |
// std::ofstream::write((char*)&v, sizeof(unsigned short&)); | |
// return *this; | |
// } | |
bofstream& operator<< (unsigned short val ) { | |
unsigned short v = htons(val); | |
std::ofstream::write((char*)&v, sizeof(unsigned short&)); | |
return *this; | |
} | |
// bofstream& operator<< (int& val ) { | |
// int v = htonl(val); | |
// std::ofstream::write((char*)&v, sizeof(int&)); | |
// return *this; | |
// } | |
bofstream& operator<< (int val ) { | |
int v = htonl(val); | |
std::ofstream::write((char*)&v, sizeof(int&)); | |
return *this; | |
} | |
// bofstream& operator<< (unsigned int& val ){ | |
// unsigned int v = htonl(val); | |
// std::ofstream::write((char*)&v, sizeof(unsigned int&)); | |
// return *this; | |
// } | |
bofstream& operator<< (unsigned int val ){ | |
unsigned int v = htonl(val); | |
std::ofstream::write((char*)&v, sizeof(unsigned int&)); | |
return *this; | |
} | |
}; | |
class Rect { | |
public: | |
short top, left, bottom, right; | |
// std::istream &operator>>(std::istream &stream, Rect &rect){ | |
// stream >> rect.top >> rect.left >> rect.bottom >> rect.right; | |
// printf("%hi, %hi, %hi, %hi\n", rect.top, rect.left, rect.bottom, rect.right); | |
// return stream; | |
// } | |
}; | |
std::istream &operator>>(std::istream &stream, Rect &rect); | |
std::ostream &operator<<(std::ostream &stream, Rect &rect); | |
std::istream &operator>>(std::istream &stream, Rect &rect){ | |
stream >> rect.top >> rect.left >> rect.bottom >> rect.right; | |
return stream; | |
} | |
bifstream &operator>>(bifstream &stream, Rect &rect){ | |
stream >> rect.top >> rect.left >> rect.bottom >> rect.right; | |
return stream; | |
} | |
std::ostream &operator<<(std::ostream &stream, Rect &rect){ | |
stream << rect.top << ", " << rect.left << ", " << rect.bottom << ", " << rect.right; | |
return stream; | |
} | |
bofstream &operator<<(bofstream &stream, Rect &rect){ | |
stream << rect.top << rect.left << rect.bottom << rect.right; | |
return stream; | |
} | |
class Pixmap { | |
public: | |
short version, pack_type; | |
int pack_size; | |
short horizontal_resolution, vertical_resolution; | |
short pixel_type, bits_per_pixel, component_count, component_size; | |
int plane_bytes, table, reserved; | |
}; | |
bofstream &operator<<(bofstream &stream, Pixmap &pix) { | |
stream << pix.version << pix.pack_type; | |
stream << pix.pack_size; | |
stream << pix.horizontal_resolution; stream.seekp(2, std::ios_base::cur); | |
stream << pix.vertical_resolution; stream.seekp(2, std::ios_base::cur); | |
stream << pix.pixel_type << pix.bits_per_pixel << pix.component_count << pix.component_size; | |
stream << pix.plane_bytes << pix.table << pix.reserved; | |
return stream; | |
} | |
bifstream &operator>>(bifstream &stream, Pixmap &pix) { | |
stream >> pix.version >> pix.pack_type; | |
stream >> pix.pack_size; | |
stream >> pix.horizontal_resolution; stream.ignore(2); | |
stream >> pix.vertical_resolution; stream.ignore(2); | |
stream >> pix.pixel_type >> pix.bits_per_pixel >> pix.component_count >> pix.component_size; | |
stream >> pix.plane_bytes >> pix.table >> pix.reserved; | |
return stream; | |
} | |
std::ostream &operator<<(std::ostream &stream, Pixmap &pix) { | |
stream << "\t\t\tVERSION: " << pix.version << std::endl; | |
stream << "\t\t\tPACK TYPE: " << pix.pack_type << std::endl; | |
stream << "\t\t\tPACK SIZE: " << pix.pack_size << std::endl; | |
stream << "\t\t\tH RES: " << pix.horizontal_resolution << std::endl; | |
stream << "\t\t\tV RES: " << pix.vertical_resolution << std::endl; | |
stream << "\t\t\tPIXEL TYPE: " << pix.pixel_type << std::endl; | |
stream << "\t\t\tBITS PER PIXEL: " << pix.bits_per_pixel << std::endl; | |
stream << "\t\t\tCOMPONENT COUNT: " << pix.component_count << std::endl; | |
stream << "\t\t\tCOMPONENT SIZE: " << pix.component_size << std::endl; | |
stream << "\t\t\tPLANE BYTES: " << pix.plane_bytes << std::endl; | |
stream << "\t\t\tTABLE: " << pix.table << std::endl; | |
return stream; | |
} | |
class Image { | |
public: | |
int columns, rows; | |
short colorCount; | |
short colors[256][3]; | |
uint8_t *pixels; | |
Image(int columns, int rows): columns(columns), rows(rows) { | |
pixels = NULL; | |
// bytes = new uint8_t[4 * rows * columns]; | |
} | |
~Image() { | |
delete pixels; | |
} | |
// size_t length() { | |
// return 4 * rows * columns; | |
// } | |
}; | |
uint8_t *expand(uint8_t *pixels, int *bytes_per_line, uint32_t bits_per_pixel) { | |
uint8_t *p = pixels; | |
// static uint8_t scanline[8*256];//? | |
static uint8_t scanline[8*256]; | |
uint8_t *q =scanline; | |
switch (bits_per_pixel) { | |
case 8: | |
case 16: | |
case 32: | |
return pixels; | |
break; | |
case 4: { | |
for (int i = 0; i < *bytes_per_line; i++) { | |
*q++ = (*p >> 4) & 0xff; | |
*q++ = (*p & 0x0f); | |
p++; | |
} | |
*bytes_per_line *= 2; | |
break; | |
} | |
case 2: { | |
for (int i = 0; i < *bytes_per_line; i++) { | |
*q++ = (*p >> 6) & 0x03; | |
*q++ = (*p >> 4) & 0x03; | |
*q++ = (*p >> 2) & 0x03; | |
*q++ = (*p & 0x03); | |
p++; | |
} | |
*bytes_per_line *= 4; | |
break; | |
} | |
case 1: { | |
for (int i = 0; i < *bytes_per_line; i++) { | |
*q++ = (*p >> 7) & 0x01; | |
*q++ = (*p >> 6) & 0x01; | |
*q++ = (*p >> 5) & 0x01; | |
*q++ = (*p >> 4) & 0x01; | |
*q++ = (*p >> 3) & 0x01; | |
*q++ = (*p >> 2) & 0x01; | |
*q++ = (*p >> 1) & 0x01; | |
*q++ = (*p & 0x01); | |
p++; | |
} | |
*bytes_per_line *= 8; | |
break; | |
} | |
default: | |
break; | |
} | |
return scanline; | |
} | |
//THIS ONE IS BROKEN | |
//EVEN THOUGH I KNOW HOW TO FIX IT | |
//IT DOESN'T MATTER SINCE decode2 WORKS | |
uint8_t *decode1(bifstream &in, Image *image, int bytes_per_line, unsigned int bits_per_pixel, int *extent) { | |
//determine size | |
if (bits_per_pixel <= 8) { | |
printf("TRACE1\n"); | |
bytes_per_line &= 0x7fff; | |
} | |
int width = image->columns; | |
int bytes_per_pixel = 1; | |
if (bits_per_pixel == 16) { | |
bytes_per_pixel = 2; | |
width *= 2; | |
} else if (bits_per_pixel == 32) { | |
//MATTE, WUT? | |
assert(0); | |
} | |
/* | |
because storing 0x8000 bpl must mean it uses compression | |
so the &= 0x7fff sets it to zero only if it is compressed | |
thus in that case we use the calculated value | |
*/ | |
if (bytes_per_line == 0) { | |
bytes_per_line = width; | |
} | |
int row_bytes = (1 * image->columns) | 0x8000; | |
// std::cout << "BPL: " << bytes_per_line << " | LINES: " << image->rows << std::endl; | |
printf("BPL: %i | LINES: %i\n", bytes_per_line, image->rows); | |
uint8_t *pixels = new uint8_t[row_bytes * image->rows]; | |
*extent = row_bytes * image->rows; | |
if (bytes_per_line < 8) {//pixels are uncompressed???? | |
//do I need to handle this yet? | |
//i don't know why this state would happen | |
//just copy the pixels | |
assert(0); | |
// return pixels; | |
} | |
uint8_t *p, *q; | |
for (int y = 0; y < image->rows; y++) { | |
q = pixels + y * width; | |
short scanLength; | |
/* | |
if (bytes_per_line > 200) { | |
/*/ | |
if (!(bytes_per_line > 200)) { | |
//*/ | |
char tmp; | |
in >> tmp; | |
scanLength = tmp; | |
printf("A"); | |
} else { | |
short tmp; | |
in >> tmp; | |
scanLength = tmp; | |
printf("B"); | |
} | |
printf("%hi",scanLength); | |
if (scanLength >= row_bytes) assert(0); | |
uint8_t *scanline = new uint8_t[row_bytes]; | |
// in.read(scanline, scanLength); | |
in.read((char *)scanline, scanLength); | |
for (int j = 0; j < scanLength;) { | |
if ((scanline[j] & 0x80) == 0) { | |
int length = ((scanline[j] & 0xff) + 1); | |
int num_pixels = length * bytes_per_pixel; | |
p = expand(scanline+j+1, &num_pixels, bits_per_pixel); | |
if ((q-pixels+num_pixels) <= *extent) { | |
memcpy(q, p, num_pixels + 1); | |
} | |
printf("(%i)",num_pixels); | |
q += num_pixels; | |
j += length * bytes_per_line + 1; | |
} else { | |
printf("[B%i]", j); | |
int length = (((scanline[j] ^ 0xff) & 0xff) + 2); | |
int num_pixels = length * bytes_per_pixel; | |
p = expand(scanline + j + 1, &num_pixels, bits_per_pixel); | |
for (int i = 0; i < length; i++) { | |
if ((q-pixels+num_pixels) <= *extent) { | |
memcpy(q, p, num_pixels); | |
} | |
printf("(%i)",num_pixels); | |
q += num_pixels; | |
} | |
j += bytes_per_pixel + 1; | |
// if ((q - pixels + num_pixels | |
} | |
} | |
printf("\n"); | |
delete [] scanline; | |
} | |
return pixels; | |
} | |
uint8_t *decode2(bifstream &in, Image *image, int bytes_per_line, unsigned int bits_per_pixel, int *extent) { | |
// printf("READING IMAGE\n"); | |
// printf("BYTES PER LINE: %i\n", bytes_per_line); | |
// printf("BITS PER PIXEL: %u\n", bits_per_pixel); | |
if (bits_per_pixel <= 8) { | |
bytes_per_line &= 0x7fff; | |
// printf("STRIP COMPRESSION FLAG: %i\n", bytes_per_line); | |
} | |
int width = image->columns; | |
// printf("WIDTH: %i\n", width); | |
size_t bytes_per_pixel = 1; | |
if (bits_per_pixel == 16) { | |
assert(0); | |
bytes_per_pixel = 2; | |
width *= 2; | |
// printf("SCALING DATA 2x\n"); | |
} else if (bits_per_pixel == 32) { | |
assert(0); | |
} | |
if (bytes_per_line == 0) { | |
bytes_per_line = width; | |
// printf("FIX BPL\n"); | |
} | |
size_t row_bytes = (image->columns * 1) | 0x8000; | |
// printf("SET ROWBYTES 0x%x = %i\n", row_bytes, row_bytes); | |
uint8_t *pixels; | |
size_t pixel_buffer_size = image->rows * row_bytes * sizeof(*pixels); | |
pixels = new uint8_t[pixel_buffer_size]; | |
assert(pixels); | |
*extent = pixel_buffer_size; | |
memset(pixels, 0x00, image->rows * row_bytes * sizeof(*pixels)); | |
// printf("MADE PIXEL BUFFER[%i]\n", pixel_buffer_size); | |
uint8_t *scanline = new uint8_t[row_bytes * sizeof(*scanline)]; | |
assert(scanline); | |
// printf("MADE SCANLINE BUFFER[%i]\n",row_bytes * sizeof(*scanline)); | |
if (bytes_per_line < 8) { | |
assert(0); | |
//Run uncompressed buffer | |
for (int y = 0; y < image->rows; y++) { | |
printf("COPYING ROW %i\n", y); | |
uint8_t *p, *q; | |
q = pixels + y * width; | |
int number_pixels = bytes_per_line; | |
in.read((char*)scanline, number_pixels); | |
printf("READ %i BYTES\n", number_pixels); | |
} | |
} | |
for (int y = 0; y < image->rows; y++) { | |
uint8_t *p, *q; | |
q = pixels + y * width; | |
size_t scanline_length = 0xbeef; | |
// printf("\tDECOMPRESSING ROW %i\n", y); | |
if (bytes_per_line > 200) { | |
short tmp; | |
in >> tmp; | |
scanline_length = tmp; | |
} else { | |
char tmp; | |
in >> tmp; | |
scanline_length = tmp; | |
} | |
// printf("\t\tSCANLINE LENGTH: %zi\n", scanline_length); | |
if (scanline_length >= row_bytes) assert(0); | |
in.read((char *)scanline, scanline_length); | |
// printf("\t\tGOT SCANLINE\n"); | |
for (int j = 0; j < scanline_length; ) { | |
if (((scanline[j] & 0x80) == 0)) { | |
size_t length = ((scanline[j] & 0xff) + 1); | |
// printf("\t\tLENGTH OF RUN: %zi\n", length); | |
int number_pixels = length*bytes_per_pixel; | |
p = expand(scanline+j+1, &number_pixels, bits_per_pixel); | |
if ((q-pixels+number_pixels) <= *extent) { | |
memcpy(q, p, number_pixels); | |
} | |
q += number_pixels; | |
j += length*bytes_per_pixel+1; | |
} else { | |
size_t length = (((scanline[j] ^ 0xff) & 0xff) + 2); | |
// printf("\t\tLENGTH OF RUN: %zi\n", length); | |
int number_pixels = bytes_per_pixel; | |
p = expand(scanline+j+1, &number_pixels, bits_per_pixel); | |
// printf("\t\tPIXELS EXPANDED TO %i \n", number_pixels); | |
for (int i = 0; i < length; i++) { | |
if ((q-pixels+number_pixels) <= *extent) { | |
memcpy(q, p, number_pixels); | |
} | |
q += number_pixels; | |
} | |
j += bytes_per_pixel + 1; | |
} | |
} | |
// if (((scanline | |
} | |
return pixels; | |
} | |
uint8_t *decode(bifstream &in, Image *image, int bytes_per_line, unsigned int bits_per_pixel, int *extent) { | |
return decode2(in, image, bytes_per_line, bits_per_pixel, extent); | |
} | |
size_t encode(bofstream &out, uint8_t *scanline, size_t bytes_per_line, uint8_t *pixels) { | |
uint8_t *p, *q; | |
short count = 0, runlength = 0, repeat_count = 0; | |
p = scanline + bytes_per_line - 1; | |
q = pixels; | |
uint8_t index = *p; | |
for (int i = bytes_per_line - 1; i >= 0; i--) { | |
if (index == *p) { | |
runlength++; | |
} else { | |
if (runlength < 3) { | |
while (runlength > 0) { | |
*q++ = (uint8_t)index; | |
runlength--; | |
count++; | |
if (count == 128) { | |
*q++ = (uint8_t)(127); | |
count-=128; | |
} | |
} | |
} else { | |
if (count > 0) { | |
*q++ = (uint8_t)(count - 1); | |
} | |
count = 0; | |
while (runlength > 0) { | |
repeat_count = runlength; | |
if (repeat_count > 128) { | |
repeat_count = 128; | |
} | |
*q++ = (uint8_t)index; | |
*q++ = (uint8_t)(257-repeat_count); | |
runlength -= repeat_count; | |
} | |
} | |
runlength = 1; | |
} | |
index = *p; | |
p--; | |
} | |
if (runlength < 3) { | |
while (runlength > 0) { | |
*q++ = (uint8_t)index; | |
runlength--; | |
count++; | |
if (count == 128) { | |
*q++ = (uint8_t)127; | |
count -= 128; | |
} | |
} | |
} else { | |
if (count > 0) { | |
*q++ = (uint8_t)(count-1); | |
} | |
count = 0; | |
while (runlength > 0) { | |
repeat_count = runlength; | |
if (repeat_count > 128) { | |
repeat_count = 128; | |
} | |
*q++ = (uint8_t)index; | |
*q++ = (uint8_t)(257-repeat_count); | |
runlength -= repeat_count; | |
} | |
} | |
if (count > 0) { | |
*q++ = (uint8_t)(count - 1); | |
} | |
short length = q - pixels; | |
if (bytes_per_line > 200) { | |
out << (uint16_t)length; | |
length += 2; | |
} else { | |
out << (uint8_t)length; | |
length++; | |
} | |
while (q != pixels) { | |
q--; | |
out << (uint8_t)*q; | |
} | |
return length; | |
} | |
//using namespace std; | |
int main (int argc, const char *argv[]) { | |
std::cout << argc << std::endl; | |
for (int i = 0; i < argc; i++) { | |
std::cout << i << ": " << argv[i] << std::endl; | |
} | |
bifstream in(argv[1], std::ifstream::in | std::ifstream::binary); | |
in.ignore(512);//skip blank header | |
uint16_t picsize; | |
in >> picsize; | |
std::cout << picsize << std::endl; | |
Rect rect; | |
in >> rect; | |
std::cout << "RECT: " << rect << std::endl; | |
uint8_t vcode = 0; | |
do { | |
in >> vcode; | |
} while (vcode == 0); | |
assert(vcode == 0x11); | |
uint8_t version = 0; | |
in >> version; | |
assert(version == 1 || version == 2); | |
if (version == 2) { | |
uint8_t ch; | |
in >> ch; | |
assert(ch == 0xff); | |
} | |
Image *image = NULL; | |
//PREFORM RECT CHECK | |
//BLACK CANVAS | |
uint16_t code; | |
while (in.good()) { | |
{//Get the code | |
if (version == 1 || (in.tellg() % 2) == 1) { | |
uint8_t tcode; | |
in >> tcode; | |
code = tcode; | |
} else { | |
in >> code; | |
} | |
} | |
switch (code) { | |
case 0x0c00: | |
printf("STRANGE CODE\n"); | |
//skip 24 bytes (dunno why) | |
in.ignore(24); | |
break; | |
case 0x0001: | |
std::cout << "CLIP REGION" << std::endl; | |
int16_t reg_size; | |
Rect reg_rect; | |
in >> reg_size >> reg_rect; | |
if (reg_size != 10) assert(0); | |
std::cout << "\tSIZE: " << reg_size << std::endl; | |
std::cout << "\tRECT: " << reg_rect << std::endl; | |
break; | |
case 0x0098:{ | |
image = new Image(rect.right - rect.left, rect.bottom - rect.top); | |
std::cout << "PACKBITS RECT" << std::endl; | |
short row_bytes; //Bytes per row | |
in >> row_bytes; | |
std::cout << "\tROW BYTES: " << row_bytes << std::endl; | |
Rect packRect; | |
in >> packRect; | |
std::cout << "\tRECT: " << packRect << std::endl; | |
//Clone the subimage defined by RECT | |
Pixmap pix; | |
in >> pix; | |
std::cout << pix; | |
short flags = 0; | |
short colors = 2; | |
if ((0x8000 & row_bytes) != 0) { | |
in.ignore(4); | |
in >> flags >> colors; | |
colors++; | |
printf("\t\tFLAGS: 0x%hx\n", flags); | |
std::cout << "\t\tCOLORS: " << colors << std::endl; | |
} | |
// short colorArray[colors][3]; | |
std::cout << "POS BEFORE: " << std::dec << in.tellg() << std::endl; | |
for (int i = 0; i < colors; i++) { | |
short j; | |
in >> j; | |
if ((flags & 0x8000) != 0) j =i; | |
// in >> colorArray[i][0] >> colorArray[i][1] >> colorArray[i][2]; | |
in >> image->colors[i][0] >> image->colors[i][1] >> image->colors[i][2]; | |
// std::cout << "\t\t\t" << std::dec << i << ": (" << std::hex << std::showbase << colorArray[i][0] << ", " << colorArray[i][1] << ", " << colorArray[i][2] << ")" << std::endl; | |
} | |
std::cout << "POS AFTER: " << std::dec << in.tellg() << std::endl; | |
std::cout << std::dec; | |
Rect sourceRect, destRect; | |
in >> sourceRect >> destRect; | |
in.ignore(2); | |
std::cout << "\tSOURCE RECT: " << sourceRect << std::endl; | |
std::cout << "\tDESTINATION RECT: " << destRect << std::endl; | |
//MAYBE SKIP REGION? | |
// uint8_t *pixels; | |
int extent; | |
if (((code != 0x9a) && (code != 0x9b) && ((row_bytes & 0x8000) == 0))) { | |
printf("TRACE0A\n"); | |
image->pixels = decode(in, image, row_bytes, 1, &extent); | |
} else { | |
printf("TRACE0B\n"); | |
image->pixels = decode(in, image, row_bytes, pix.bits_per_pixel, &extent); | |
} | |
// delete image; | |
// assert(0); | |
} | |
break; | |
case 0xff: | |
std::cout << "END CODE" << std::endl; | |
break; | |
default: | |
std::cout << "UNKNOWN CODE: " << std::hex << std::showbase << (int)code << std::endl; | |
goto loopend; | |
break; | |
} | |
} | |
loopend: | |
in.close(); | |
if (image != NULL) { | |
} | |
{ | |
std::string path(argv[1]); | |
path.erase(path.find_last_of("."), path.length()); | |
std::cout << path << std::endl; | |
path.append(".tga"); | |
std::ofstream out(path.c_str(), std::ofstream::binary | std::ofstream::out | std::ofstream::trunc); | |
//#pragma pack(1) | |
struct { | |
int8_t idlength; | |
int8_t colourmaptype; | |
int8_t datatypecode; | |
int16_t colourmaporigin; | |
int16_t colourmaplength; | |
int8_t colourmapdepth; | |
int16_t x_origin; | |
int16_t y_origin; | |
int16_t width; | |
int16_t height; | |
int8_t bitsperpixel; | |
int8_t imagedescriptor; | |
} HEADER; | |
// printf("SIZE = %i\n", sizeof(HEADER)); | |
// assert(sizeof(HEADER) == 18); | |
HEADER.idlength = 0; | |
HEADER.colourmaptype = 1; | |
HEADER.datatypecode = 1; | |
HEADER.colourmaporigin = 18; | |
HEADER.colourmaplength = 256; | |
HEADER.colourmapdepth = 24; | |
HEADER.x_origin = 0; | |
HEADER.y_origin = 0; | |
HEADER.width = image->columns; | |
HEADER.height = image->rows; | |
HEADER.bitsperpixel = 8; | |
HEADER.imagedescriptor = 0; | |
// out.write((char*)&HEADER, 18); | |
#define WRITE(var) out.write((char *)&var, sizeof(var)); | |
WRITE(HEADER.idlength); | |
WRITE(HEADER.colourmaptype); | |
WRITE(HEADER.datatypecode); | |
WRITE(HEADER.colourmaporigin); | |
WRITE(HEADER.colourmaplength); | |
WRITE(HEADER.colourmapdepth); | |
WRITE(HEADER.x_origin) | |
WRITE(HEADER.y_origin) | |
WRITE(HEADER.width);WRITE(HEADER.height)//CORRECT | |
// WRITE(HEADER.height);WRITE(HEADER.width) | |
WRITE(HEADER.bitsperpixel) | |
WRITE(HEADER.imagedescriptor) | |
// printf("{"); | |
for (int i = 0; i < 256; i++) { | |
char c; | |
c = ((((short)image->colors[i][2]) >> 8) & 0xff);//B | |
// printf("{"); | |
out.write(&c, 1); | |
// printf("0x%hhx, ", c); | |
// std::cout.write(&c, 1); | |
c = ((((short)image->colors[i][1]) >> 8) & 0xff);//G | |
out.write(&c, 1); | |
// printf("0x%hhx, ", c); | |
// std::cout.write(&c, 1); | |
c = ((((short)image->colors[i][0]) >> 8) & 0xff);//R | |
out.write(&c, 1); | |
// printf("0x%hhx", c); | |
// std::cout.write(&c, 1); | |
// printf("}"); | |
// if (i != 255) { | |
// printf(","); | |
// } | |
} | |
// printf("}"); | |
out.write((char*)image->pixels, image->rows * image->columns); | |
out.close(); | |
} | |
printf("WRITING OUT\n"); | |
std::string path(argv[1]); | |
path.erase(path.find_last_of("."), path.length()); | |
// std::cout << path << std::endl; | |
path.append("-2.pict"); | |
bofstream out(path.c_str(), std::ofstream::binary | std::ofstream::out | std::ofstream::trunc); | |
out.seekp(512);//blank header | |
out.write("\x00\x00", 2); | |
Rect sizerect = {0, 0, image->rows, image->columns}; | |
out << sizerect; | |
out.write("\x00\x11\x02\xff", 4); | |
out.write("\x0c\x00", 2); | |
out.write("\xff\xfe\x00\x00", 4); | |
double size_d = 72.0; | |
unsigned short size_s = (unsigned short)size_d; | |
out << size_s; | |
out.write("\x00\x00", 2); | |
out << size_s; | |
out.write("\x00\x00", 2); | |
out << sizerect; | |
out.write("\x00\x00\x00\x00", 4); | |
out.write("\x00\x01\x00\x0a", 4); | |
out << sizerect; | |
if (true) { | |
out.write("\x00\x98", 2); | |
} else { | |
out.write("\x00\x9a", 2); | |
out.write("\x00\x00\x00\xff", 4); | |
} | |
short row_bytes = image->columns;// | 0x8000; | |
if (row_bytes % 2 == 1) { | |
row_bytes++; | |
} | |
out << (short)(row_bytes|0x8000) << sizerect; | |
Pixmap pix; | |
pix.version = 0; | |
pix.pack_type = 0; | |
pix.pack_size = 0; | |
pix.pixel_type = 0; | |
pix.bits_per_pixel = 8; | |
pix.component_count = 1; | |
pix.component_size = 8; | |
pix.plane_bytes = 0; | |
pix.table = 0; | |
pix.reserved = 0; | |
out << pix.version << pix.pack_type << pix.pack_size; | |
///??//?????????????? | |
out << size_s; | |
out.write("\x00\x00", 2); | |
out << size_s; | |
out.write("\x00\x00", 2); | |
out << pix.pixel_type << pix.bits_per_pixel; | |
out << pix.component_count << pix.component_size; | |
out << pix.plane_bytes << pix.table; | |
printf("TRACE: %4x\n", (int)out.tellp()); | |
out << pix.reserved; | |
printf("COLORMAP: %i\n", (int)out.tellp()); | |
{ | |
//WRITE colormap | |
out.write("\x00\x44\x9d\x88", 4); | |
out.write("\x00\x00", 2); | |
short colors = 255; | |
out << colors; | |
for (short i = 0; i < 256; i++) { | |
short pre = (short)out.tellp(); | |
out << i << image->colors[i][0] << image->colors[i][1] << image->colors[i][2]; | |
short post = (short)out.tellp(); | |
assert(post-pre == 8); | |
} | |
} | |
out << sizerect << sizerect; | |
out.write("\x00\x00", 2); | |
printf("INDEX A: %i\n", (int)out.tellp()); | |
bool isIndexed = true; | |
int count = 0; | |
for (int y = 0; y < image->rows; y++) { | |
//GETPIXEL | |
uint8_t *scanline = new uint8_t[row_bytes & 0x7fff]; | |
uint8_t *packedScanline = new uint8_t[row_bytes & 0x7fff]; | |
for (int x = 0; x < image->rows; x++) { | |
if (isIndexed == true) { | |
scanline[x] = image->pixels[x + y* image->columns]; | |
} else { | |
assert(0); | |
//getQuantitizedPixel(); | |
} | |
} | |
count += encode(out, scanline, (row_bytes & 0x7fff), packedScanline); | |
delete scanline, packedScanline; | |
} | |
if (count & 0x01) { | |
out.write("\x00", 1); | |
} | |
out.write("\x00\xff", 2); | |
int index = (int)out.tellp() - 512; | |
out.seekp(512, std::ios_base::beg); | |
out << (short)index; | |
printf("INDEX B: %i\n", (int)out.tellp()); | |
/* | |
out.write("\xff\xff", 2);//put dummy data here for now | |
Rect sizerect = {0, 0, image->rows, image->columns};//We will use this seveal times | |
out << rect; | |
//write some nulls here too? | |
out.write("\x11\x01", 2);//set version 1 | |
// out.write("\x11\0x02\xff", 3);//set version 2 | |
// out.write("\x0c\x00", 2);//header thing? | |
// out.seekp(24, std::ios_base::cur); | |
out.write("\x01\x0a", 2);//clip region command with default data length 10 | |
out << rect;//write the clip rect | |
//write the image | |
out.write("\x98", 1);//pack bits rect command | |
// short row_bytes = htons(image->columns+1); | |
short row_bytes = (image->columns%2==0?image->columns:image->columns+1) | 0x8000; | |
// out.write((char*)&row_bytes, 2);//estimate row bytes | |
out << row_bytes;//estimate row bytes | |
out << sizerect; //write the rect again for benifit of the pixmap | |
Pixmap pix; | |
pix.version = 0; | |
pix.pack_type = 0; | |
pix.pack_size = 0; | |
pix.horizontal_resolution = 72; | |
pix.vertical_resolution = 72; | |
pix.pixel_type = 0; | |
pix.bits_per_pixel = 8; | |
pix.component_count = 1; | |
pix.component_size = 1; | |
pix.plane_bytes = 0; | |
pix.table = 0; | |
out << pix; | |
out.write("\x00\x00", 2);//let flags be null | |
out.write("\x00\xff", 2);//encode 256 -1 colors | |
for (short i = 0; i < 256; i++) { | |
//write out the color table | |
out << i << image->colors[i][0] << image->colors[i][1] << image->colors[i][2]; | |
} | |
//write source and destination rect | |
//which are still the same rects | |
out << sizerect << sizerect; | |
out.write("\x00\x00", 2);//nulls | |
char *buffer = new char[(row_bytes&0x7fff)+1]; | |
// char buffer[row | |
for (int y = 0; y < image->rows; y++) { | |
memset(buffer, 0, row_bytes&0x7fff); | |
memcpy(buffer, image->pixels + image->columns * y, image->columns); | |
out.write(buffer, row_bytes&0x7fff); | |
} | |
delete buffer; | |
// out.write((char*)image->pixels, image->columns * image->rows); | |
// for (int i = 0; i < image->columns * image->rows; i++) { | |
// | |
// } | |
short size = out.tellp(); | |
size -= 512; | |
out.seekp(512, std::ios_base::beg); | |
// out.write((char*)&size, <#streamsize __n#>) | |
out << size; | |
*/ | |
out.close(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment