Skip to content

Instantly share code, notes, and snippets.

@gamefreak
Created October 1, 2011 22:16
Show Gist options
  • Save gamefreak/1256727 to your computer and use it in GitHub Desktop.
Save gamefreak/1256727 to your computer and use it in GitHub Desktop.
Partial PICT decoder for eventual use in Athena
//
// 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