blob: 2e02e22c01218ee981661dec7dfe68cf25fac021 [file] [log] [blame]
/* GFX2mo5 - png2mo5.c
* CloudStrife - 20080921
* PulkoMandy - 2012-2014
* Diffusé sous licence libre CeCILL v2
* Voir LICENCE
*/
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <png.h>
#include "libraw2mo5.h"
#include <assert.h>
#define ERROR 1
int main(int argc, char **argv)
{
FILE *inFile, *outFile;
unsigned char *inBuffer, *outBuffer;
png_uint_32 width;
png_uint_32 height;
int bitdepth;
int colorType;
unsigned char header[8];
unsigned char is_png;
unsigned int y;
png_structp png_ptr;
png_infop info_ptr;
png_infop end_info;
png_bytep * ptrRow;
int pxsize;
char opt;
int fixup = -1;
bool to = false;
unsigned char thomheader[] = {
// Block 1 : address A7C0, 1 byte, select FORME
0x00, 0x00, 0x01, 0xA7, 0xC0, 0x51,
// Block 2 : address 0000, 1F40 bytes, FORME data
0x00, 0x1F, 0x40, 0x00, 0x00
};
// End marker block : type=255, size and address=0
const unsigned char end[]={255,0,0,0,0};
if(argc < 3)
{
printf("Utilisation : %s [options] input_filename output_filename\n",argv[0]);
printf("Option -t: use TO transcoding.\n");
printf("Option -f n: use modified algorithm to avoid artifacts on some MO5 gate array versions. n is the index of the background color.\n");
exit(0);
}
while((opt = getopt(argc, argv, "tf:")) != -1) {
switch(opt) {
case 't':
to = true;
thomheader[3] = 0xE7;
thomheader[4] = 0xC3;
thomheader[5] = 0x65;
thomheader[9] = 0x40;
break;
case 'f':
fixup = atoi(optarg);
break;
}
}
inFile = fopen(argv[optind++],"rb");
if (inFile == NULL)
{
printf("Fichier Inexistant\n");
exit(1);
}
fread(header, 1, 8, inFile);
is_png = !png_sig_cmp(header, 0, 8);
if (!is_png)
{
printf("Ce n'est pas un png\n");
exit(2);
}
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL);
if (!png_ptr) return (ERROR);
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
{
png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
return (ERROR);
}
end_info = png_create_info_struct(png_ptr);
if (!end_info)
{
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
return (ERROR);
}
if (setjmp(png_jmpbuf(png_ptr)))
{
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(inFile);
return (ERROR);
}
png_init_io(png_ptr, inFile);
png_set_sig_bytes(png_ptr, 8);
png_read_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bitdepth, &colorType, NULL, NULL, NULL);
if(!((colorType == PNG_COLOR_TYPE_GRAY) || (colorType == PNG_COLOR_TYPE_PALETTE)))
{
puts("Ce PNG n'est pas dans un format exploitable (niveaux de gris ou palette)");
return (ERROR);
}
if (bitdepth > 8)
{
puts("Ce PNG n'est pas dans un format exploitable (bitdepth = 1, 2 ou 4)");
return (ERROR);
}
png_set_packing(png_ptr); /* Convertir en mode 1 pixel par octets */
png_read_update_info(png_ptr, info_ptr);
inBuffer = (unsigned char*)malloc(width*height);
if (inBuffer == NULL)
{
printf("Allocation inBuffer raté\n");
exit(3);
}
ptrRow = (png_bytep*)malloc(sizeof(png_bytep)*height);
for(y = 0; y < height; y++)
{
ptrRow[y] = (inBuffer + width*y);
}
png_read_image(png_ptr, ptrRow);
outBuffer = raw2mo5(inBuffer, height, fixup, to);
pxsize = width * height / 8;
thomheader[7] = pxsize >> 8;
thomheader[8] = pxsize;
outFile = fopen(argv[optind++], "wb");
fwrite(thomheader, 1, sizeof(thomheader), outFile);
//write forme data
fwrite(outBuffer, 1, pxsize, outFile);
--thomheader[5];
fwrite(thomheader, 1, sizeof(thomheader), outFile);
// write color data
fwrite(outBuffer+0x2000, 1, pxsize, outFile);
fwrite(end, 1, sizeof(end), outFile);
fclose(outFile);
png_read_end(png_ptr, end_info);
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
free(inBuffer);
inBuffer = NULL;
free(outBuffer);
outBuffer = NULL;
return 0;
}