/*-
*|:_____: _____ __________ ._________ |
*||__ |/ /.\______ \./ _______/ |
*| / __/ ___/ . | ²__/ /\_____ \ |
*| / \ \_ . | \_____/ \ \_| /|
*| \ \ \_ . | : . : \_______/ |
*| \___\____\ .:____| : |
*| K.a.P.i.T.a.L. S i N ' 2013 |
*+-------------------------------------|
*|-KPS- -2013- |
*| # KPS PNG FIXER PARA VIS ENGINE 3# |
*
* ESTE PROGRAMA LO QUE HACE ES ARREGLAR LOS FICHEROS PNG PARA SU MODIFICACIÓN
* O VISUALIZACION DEL MOTOR VISIONARIE STUDIO 3
*
* LA LICENCIA DE ESTE CODIGO ES DE DOMINIO PUBLICO RESPETANDO
* A SUS AUTORES
*
* IDEA BASADA EN EL ARTICULO
*
* "A New Beginning" - PNG fixing
* http://www.nullsecurity.org/article/a_new_beginning-png_fixing
*
* OTROS GRUPOS SOLO COPIAN, KPS INNOVA
*
*/
#include <boost/crc.hpp> // for boost::crc_32_type
//#include <boost/program_options.hpp> // for boost::crc_32_type
#include <boost/format.hpp>
#include <boost/foreach.hpp>
#include <cstdio>
#include <iostream>
#include <fstream>
#include <cstring>
#include <string>
typedef unsigned int DWORD;
using namespace std;
DWORD crc32(char *buffer, int buffer_length) {
boost::crc_32_type result;
result.process_bytes(buffer, buffer_length );
return result.checksum();
}
/* 'IHDR': 4 bytes
Width: 4 bytes
Height: 4 bytes
Bit depth: 1 byte
Color type: 1 byte
Compression method: 1 byte
Filter method: 1 byte
Interlace method: 1 byte
*/
int main(int argc, char *argv[]) {
// Get command line options
if(argc < 2) {
cout << "Missing PNG file!" << endl;
cout << "Usage: pngfixer file.png" << endl;
exit(-1);
}
// Open file
ifstream infile(argv[1]);
char buffer[80];
// Check file is PNG
infile.read(buffer, 4);
if(strncmp(buffer, "\x89PNG", 4) !=0 ) {
// Incorret magik number
cout << "File is not PNG type!" << endl;
exit(-2);
}
// Read IHDR chunk
// char IHDR[] = "\x49\x48\x44\x52\x61\x64\x31\x9D\x66\x61\x33\x8F\x08\x06\x00\x00\x00";
// 0xEB35350F
// char IHDR[] = "\x49\x48\x44\x52\x65\x37\x32\x32\x62\x36\x31\x35\x08\x06\x00\x00\x00";
// 0x6d9ab2fb;
char IHDR[17];
char CHECKSUM[4];
infile.seekg(12, ios_base::beg);
infile.read(IHDR, 17);
infile.read(CHECKSUM, 4);
DWORD checksum = (((DWORD)CHECKSUM[0])&0xFF) << (3*8)
| (((DWORD)CHECKSUM[1])&0xFF) << (2*8)
| (((DWORD)CHECKSUM[2])&0xFF) << (1*8)
| (((DWORD)CHECKSUM[3])&0xFF) << (0*8);
// Save original size from the header
char original_size[8];
memcpy(original_size, &IHDR[4], 8);
// Brute force size check
unsigned int w, h, i;
for(w = 0; w < 2000; w++) {
for(h = 0; h < 2000; h++) {
*(DWORD*)&IHDR[4] = w;
__asm__("bswap %0" : "+r" (*(DWORD*)&IHDR[4]));
*(DWORD*)&IHDR[8] = h;
__asm__("bswap %0" : "+r" (*(DWORD*)&IHDR[8]));
// Correct size: W:164 x H:187
// if(w == 256 && h == 512) {
// printf("CRC 0x%x\n", crc32(IHDR, 17));
// printf("IHDR "); for(int i=0;i<17;i++) printf(" %02x", IHDR[i]);
// printf("\n");
// }
//if (crc32(IHDR, 17) == 0xEB35350F) {
//if (crc32(IHDR, 17) == 0x6d9ab2fb) {
if (crc32(IHDR, 17) == checksum) {
printf("Correct size: W:%d x H:%d\n", w, h);
//printf("Correct size: W:0x%x x H:0x%x\n", w, h);
// Save original size into filename
std::string fname(argv[1]);
std::string hexa;
for(int i = 0; i < sizeof(original_size); i++) {
//printf("%02x", original_size[i]);
hexa.append(boost::str(boost::format("%1$02x") % (int) original_size[i]));
}
fname.append(boost::str(boost::format("_%1%.png") % hexa));
std::cout <<std::endl << fname <<std::endl;
// Inject header with correct size
fstream outfile(argv[1], ios::out|ios::in);
outfile.seekp(12, ios_base::beg);
outfile.write(IHDR, 17);
outfile.close();
// Rename file
rename(argv[1],fname.c_str());
// Exit
return 0;
}
}
}
cout << "Could not find correct size. Failed!" << endl;
return -3;
}