//-----------------------------------------------------------------------------
// Prevodni program mezi grafickym formatem IMG a TGA
//
// Soucast serialu "Graficke formaty" publikovaneho na http://www.root.cz
// Autor: Pavel Tisnovsky
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define EXT_IMG ".img"
#define EXT_TGA ".tga"
//-----------------------------------------------------------------------------
// Otevreni souboru typu IMG (jmeno neobsahuje koncovku)
//-----------------------------------------------------------------------------
FILE *openImg(char *name)
{
char *imgName=(char *)malloc(strlen(name)+strlen(EXT_IMG)+1);
strcpy(imgName, name);
strcat(imgName, EXT_IMG);
printf("Opening file %s for reading\n", imgName);
return fopen(imgName, "rb");
}
//-----------------------------------------------------------------------------
// Otevreni souboru typu TGA (jmeno neobsahuje koncovku)
//-----------------------------------------------------------------------------
FILE *openTga(char *name)
{
char *tgaName=(char *)malloc(strlen(name)+strlen(EXT_TGA)+1);
strcpy(tgaName, name);
strcat(tgaName, EXT_TGA);
printf("Opening file %s for writing\n", tgaName);
return fopen(tgaName, "wb");
}
//-----------------------------------------------------------------------------
// Nacteni hlavicky ze souboru typu IMG, naplnuje se i rozliseni
//-----------------------------------------------------------------------------
int readIMGHeader(FILE *fin, int *width, int *height)
{
// makro pro prevod dvojice bytu na integer v usporadani big endian
#define twoBytes2int(b1, b2) ((int)(b1)<<8 | (b2))
unsigned char imgHeader[10];
int firstLine, lastLine, bpp;
if (fread(imgHeader, 10, 1, fin)!=1) return 0;
*width= twoBytes2int(imgHeader[0], imgHeader[1]);
*height= twoBytes2int(imgHeader[2], imgHeader[3]);
firstLine= twoBytes2int(imgHeader[4], imgHeader[5]);
lastLine= twoBytes2int(imgHeader[6], imgHeader[7]);
bpp= twoBytes2int(imgHeader[8], imgHeader[9]);
printf("IMG header: width= %d\n", *width);
printf("IMG header: height= %d\n", *height);
printf("IMG header: 1st line= %d\n", firstLine);
printf("IMG header: last line= %d\n", lastLine);
printf("IMG header: bpp= %d\n", bpp);
return 1;
}
//-----------------------------------------------------------------------------
// Ulozeni hlavicky souboru typu TGA
//-----------------------------------------------------------------------------
int writeTGAHeader(FILE *fout, int width, int height)
{
unsigned char tgaHeader[18]={ // hlavicka formatu typu TGA
0x00, // typ hlavicky TGA
0x00, // nepouzivame paletu
0x02, // typ obrazku je RGB TrueColor
0x00, 0x00, // delka palety je nulova
0x00, 0x00, 0x00, // pozice v palete nas nezajima
0x00, 0x00, 0x00, 0x00, // obrazek je umisteny na pozici [0, 0]
0x00, 0x00, 0x00, 0x00, // sirka a vyska obrazku (dva byty na polozku)
0x18, // format je 24 bitu na pixel
0x20 // orientace bitmapy v obrazku
};
memcpy(tgaHeader+12, &width, 2); // do hlavicky TGA zapsat sirku obrazku
memcpy(tgaHeader+14, &height, 2); // do hlavicky TGA zapsat vysku obrazku
return fwrite(tgaHeader, 18, 1, fout)==1; // zapsat hlavicku TGA do souboru
}
//-----------------------------------------------------------------------------
// Prevod obrazovych dat z formatu IMG do formatu TGA
//-----------------------------------------------------------------------------
int convert(FILE *fin, FILE *fout)
{
int count, r, g, b;
// nacteme vsechny ctverice hodnot ve sledu ("runu")
while ((count=fgetc(fin))!=EOF &&
(r=fgetc(fin))!=EOF &&
(g=fgetc(fin))!=EOF &&
(b=fgetc(fin))!=EOF) {
// rozkodovat cely sled a zapsat do vystupniho TGA
while (count--) {
if (fputc(r, fout)==EOF) return 0;
if (fputc(g, fout)==EOF) return 0;
if (fputc(b, fout)==EOF) return 0;
}
}
return 1;
}
//-----------------------------------------------------------------------------
// Hlavni funkce konzolove aplikace
//-----------------------------------------------------------------------------
int main(int argc, char **argv)
{
#define my_assert(cond, text)\
if ((cond)) {\
fprintf(stderr, "error: %s\n", (text));\
return 1;\
}
FILE *fin;
FILE *fout;
int width, height;
puts("img2tga processing:");
my_assert(argc<2, "file name (without extension) required!");
my_assert(!(fin=openImg(argv[1])), "open IMG for reading failed!");
my_assert(!(fout=openTga(argv[1])), "open TGA for writing failed!");
my_assert(!readIMGHeader(fin, &width, &height), "read IMG header failed!");
my_assert(!writeTGAHeader(fout, width, height), "write TGA header failed!");
my_assert(!convert(fin, fout), "unable to convert data!");
my_assert(fclose(fin), "close IMG failed!");
my_assert(fclose(fout), "close TGA failed!");
puts("img2tga done.\n");
return 0;
}
//-----------------------------------------------------------------------------
// finito
//-----------------------------------------------------------------------------