Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <zlib.h>
- #ifdef WIN32
- #include <io.h>
- #define set_binary_mode(f) setmode (f, O_BINARY)
- #else
- #define set_binary_mode(f)
- #endif
- /*
- 'n', 'i', 'f', '\0' (32 bits)
- image width (16 bits)
- image height (16 bits)
- compressed image size (32 bits)
- compressed image data (ARGB format, 32bpp, zlib)
- for each shift table
- length (32 bits)
- for each shift entry
- x (16 bits)
- y (16 bits)
- */
- typedef struct
- {
- unsigned char id_length;
- unsigned char cmap_type;
- unsigned char image_type;
- unsigned short cmap_start;
- unsigned short cmap_length;
- unsigned char cmap_esize;
- unsigned short xorigin;
- unsigned short yorigin;
- unsigned short width;
- unsigned short height;
- unsigned char depth;
- unsigned char desc;
- } tgainfo_t;
- int readtgainfo (int fd, tgainfo_t *info)
- {
- int totalread = 0;
- totalread += read (fd, &info->id_length, 1);
- totalread += read (fd, &info->cmap_type, 1);
- totalread += read (fd, &info->image_type, 1);
- totalread += read (fd, &info->cmap_start, 2);
- totalread += read (fd, &info->cmap_length, 2);
- totalread += read (fd, &info->cmap_esize, 1);
- totalread += read (fd, &info->xorigin, 2);
- totalread += read (fd, &info->yorigin, 2);
- totalread += read (fd, &info->width, 2);
- totalread += read (fd, &info->height, 2);
- totalread += read (fd, &info->depth, 1);
- totalread += read (fd, &info->desc, 1);
- return totalread;
- }
- int main (int argc, char **argv)
- {
- const char *nifstart = "nif"; // string to begin a .nif file with
- int base, shift, nifout;
- int len, i, j;
- tgainfo_t baseinfo;
- char *nifname;
- unsigned char *img = NULL, *zimg = NULL;
- unsigned long imglen, zimglen;
- FILE *windbg = fopen ("tga2nif.log", "w");
- if (argc < 2)
- {
- fprintf (stderr, "Usage: tga2nif [base].tga [shift1].tga [shift2].tga ... [shiftN].tga\n");
- return 1;
- }
- // open base file
- base = open (argv [1], O_RDONLY);
- if (base < 0)
- {
- fprintf (stderr, "Couldn't open file %s (%s)\n", argv [1], strerror (errno));
- return 1;
- }
- // read base file tga info
- if (readtgainfo (base, &baseinfo) != 18)
- {
- fprintf (stderr, "input file %s was incomplete\n", argv [1]);
- return 1;
- }
- if (baseinfo.cmap_type)
- {
- fprintf (stderr, "input file %s has color map\n", argv [1]);
- return 1;
- }
- // open nif file
- len = strlen (argv [1]);
- nifname = malloc (len + 1);
- sprintf (nifname, "%s", argv [1]);
- sprintf (nifname + len - 4, ".nif");
- nifout = creat (nifname, S_IRUSR | S_IWUSR);
- set_binary_mode (nifout);
- if (nifout < 0)
- {
- fprintf (stderr, "Couldn't open output file %s (%s)\n", nifname, strerror (errno));
- return 1;
- }
- // write nif header info
- if (write (nifout, nifstart, 4) != 4
- || write (nifout, &baseinfo.width, 2) != 2
- || write (nifout, &baseinfo.height, 2) != 2)
- {
- fprintf (stderr, "Error writing nif header (%s)\n", strerror (errno));
- return 1;
- }
- fprintf (windbg, "image is %ux%u\n", baseinfo.width, baseinfo.height);
- // prepare/write image data array
- imglen = 4 * baseinfo.width * baseinfo.height;
- zimglen = compressBound (imglen);
- img = malloc (imglen);
- zimg = malloc (zimglen);
- if (!img || !zimg)
- {
- fprintf (stderr, "Couldn't malloc image buffer\n");
- return 1;
- }
- fprintf (windbg, "Allocated %luB for image data and %luB for compressed data\n", imglen, zimglen);
- for (i = 0; i < baseinfo.width; i++)
- for (j = 0; j < baseinfo.height; j++)
- {
- unsigned char colors [3]; // bgr from .tga
- unsigned int outcolor; // argb for .nif
- unsigned int *pxp; // pixel pointer
- read (base, colors, 3); // get three bytes from the tga file
- if (colors [0] == 0x00 && colors [1] == 0xff && colors [2] == 0x00) // green, transparent
- outcolor = 0x00000000;
- else
- outcolor = 0xff << 24 | colors [2] << 16 | colors [1] << 8 | colors [0];
- fprintf (windbg, "[%i, %i, %x] -> %u\n", i, j, outcolor, (baseinfo.width - 1 - i) * baseinfo.height + (j + baseinfo.height) % baseinfo.width);
- if ((baseinfo.width - 1 - i) * baseinfo.height + (j + baseinfo.height) % baseinfo.width > imglen)
- fprintf (windbg, "offset exceeds image buffer length, we're gonna crash here! :D\n");
- pxp = (unsigned int*)img + (baseinfo.width - 1 - i) * baseinfo.height + (j + baseinfo.height) % baseinfo.width;
- *pxp = outcolor;
- }
- int zret;
- if ((zret = compress2 (zimg, &zimglen, img, imglen, Z_BEST_COMPRESSION)) != Z_OK)
- {
- fprintf (stderr, "Error compressing image data (%s)\n", zError (zret));
- return 1;
- }
- unsigned int zimglen32 = (unsigned int)zimglen;
- if (write (nifout, &zimglen32, 4) != 4)
- {
- fprintf (stderr, "Error writing nif header (%s)\n", strerror (errno));
- return 1;
- }
- // write image data to file
- int totalwrite = 0;
- do
- {
- totalwrite += write (nifout, zimg + totalwrite, zimglen - totalwrite);
- } while (totalwrite < zimglen);
- // make shift tables
- for (i = 2; i < argc; i++)
- {
- tgainfo_t shiftinfo;
- off_t pos;
- unsigned short k, l;
- unsigned int numentr = 0;
- shift = open (argv [i], O_RDONLY);
- if (shift < 0)
- continue;
- if (readtgainfo (shift, &shiftinfo) != 18 || shiftinfo.cmap_type)
- continue;
- // save position so we can go back and write how many entries
- pos = lseek (nifout, 0, SEEK_CUR);
- write (nifout, &numentr, 4);
- for (k = 0; k < shiftinfo.width; k++)
- for (l = 0; l < shiftinfo.height; l++)
- {
- unsigned char colors [3];
- unsigned short ex, ey;
- read (shift, colors, 3);
- if (colors [0] == 0x00 && colors [1] == 0xff && colors [2] == 0x00)
- continue;
- numentr ++;
- ex = (l + shiftinfo.height) % shiftinfo.width;
- ey = shiftinfo.width - 1 - k;
- write (nifout, &ex, 2);
- write (nifout, &ey, 2);
- }
- // go back and write how many entries there are
- lseek (nifout, pos, SEEK_SET);
- write (nifout, &numentr, 4);
- lseek (nifout, numentr * 4, SEEK_CUR);
- }
- close (nifout);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement