Code: //----------------------------------------------------------------------------- // // VTFCreate - Convert images to VTF with DXT compression // Based on VTFConv by Darkimmortal and various DevIL tutorials // // @Author ALHat // @Date 7.4.2012 // @Version 1.0 // //----------------------------------------------------------------------------- // DevIL core #include <IL/il.h> // fopen, ftell, fwrite, fseek // also included by il.h but I won't rely on that #include <stdio.h> // strcmp #include <string.h> // malloc & free #include <stdlib.h> int main(int argc, char **argv) { // DevIL handle for the current image ILuint ImgId; // Size of the compressed image data ILuint DXTCSize; // type of compression to use ILenum DXType; // the compressed image data ILubyte *compressedData; // the uncompressed image data ILubyte *data; // pointer used during repair of image file FILE * pFile; long int uncompressedSize; long int fileSize; // check for the correct number of arguments, else print usage info if (argc < 3 || argc > 4) { fprintf(stderr, "Usage: vtfconv <file> <destination> [<DXT[1,3,5]>]\n"); return 1; } // Check if the shared lib's version matches the executable's version. if (ilGetInteger(IL_VERSION_NUM) < IL_VERSION) { printf("DevIL version is different...exiting!\n"); return 2; } // check if the user specified a compression type; use DXT1 as default if (argc == 4) { if(strcmp(argv[3], "DXT3") == 0) DXType = IL_DXT3; else if(strcmp(argv[3], "DXT5") == 0) DXType = IL_DXT5; else DXType = IL_DXT1; } else { DXType = IL_DXT1; } // Initialize DevIL core. ilInit(); // Generate the main image name to use. ilGenImages(1, &ImgId); // Bind this image name. ilBindImage(ImgId); // allow overwriting existing files ilEnable(IL_FILE_OVERWRITE); // set the application wide compression type // not sure if this actually has any effect on VTFs ilSetInteger(IL_DXTC_FORMAT, DXType); // set the VTF specific compression type ilSetInteger(IL_VTF_COMP, DXType); // Loads the image specified by File into the image named by ImgId. if (!ilLoadImage(argv[1])) { printf("Could not open file...exiting.\n"); return 3; } // Try and save the file; if no error occurs we're done. if(ilSave(IL_VTF,argv[2]) == IL_TRUE) return 0; /* If the file could not be saved without error we'll try to repair * it. As of April 2012 DevIL 1.7.8-10 manages to create the file * header but dies when trying to write the image data. */ // first open the file in read mode for some checks pFile = fopen(argv[2],"r"); // if no file was created at there's nothing to fix here, we failed. if(pFile == NULL) { // TODO write image header ourselves? printf("DevIL did not even create a stump for %s; aborting.\n",argv[2]); return 4; } // get the file size of the stump fseek(pFile,0L, SEEK_END); fileSize = ftell(pFile); fclose(pFile); /* VTF headers are 80 bytes long. If has a different size it's * probably not a valid VTF header. We failed. */ if(fileSize != 80) { // TODO write image header ourselves? printf("DevIL did not create a properly sized VTF header; aborting.\n"); remove(argv[2]); return 5; } /* OK so we probably have a valid VTF header. Next steps are to compress * the image data and append it to the header without relying on DevIL */ /* calculate the memory needed for the source image data and allocate it * formula is height*width for the number of pixels and that times 3 because * we have three components per pixel (RGB, BGR, etc.). Make that four if * you want an alpha channel, I guess. */ uncompressedSize = ilGetInteger(IL_IMAGE_WIDTH) *ilGetInteger(IL_IMAGE_HEIGHT) * 3 * sizeof(unsigned char); data = (ILubyte*) malloc(uncompressedSize); // get the image data from the source image ilCopyPixels(0, 0, 0, ilGetInteger(IL_IMAGE_WIDTH), ilGetInteger(IL_IMAGE_HEIGHT), 1, IL_RGB, IL_UNSIGNED_BYTE, data); // compress the data from the source image compressedData = ilCompressDXT(data,ilGetInteger(IL_IMAGE_WIDTH),ilGetInteger(IL_IMAGE_HEIGHT),1,DXType,&DXTCSize); // open the destination file for appending, write the data and close the file pFile = fopen(argv[2],"a"); fwrite(compressedData,DXTCSize,1,pFile); fclose(pFile); // done! now some cleanup. ilDeleteImages(1, &ImgId); free(data); data = NULL; free(compressedData); compressedData = NULL; return 0; } | ||
