Inheritance: ImageFile
Exemplo n.º 1
0
        public ImageMipMapHandler(string imageWithMipMaps, byte[] data)
        {
            imageWithMipMaps = (imageWithMipMaps == "") ? ".dds" : imageWithMipMaps;
            imageList = new List<ImageFile>();
            string fileFormat = Path.GetExtension(imageWithMipMaps).ToLowerInvariant();
            string fileName = Path.GetFileNameWithoutExtension(imageWithMipMaps);
            ImageFile imageMipMap;
            int headerSize;

            if (data != null)
            {
                headerSize = 128;
                imageMipMap = new DDS("", data);
            }
            else
            {
                switch (fileFormat)
                {
                    case ".dds":
                        headerSize = 128;
                        imageMipMap = new DDS(imageWithMipMaps, null);
                        break;
                    case ".tga":
                        headerSize = 18;
                        imageMipMap = new TGA(imageWithMipMaps, null);
                        break;
                    default: throw new FormatException("Invalid image format");
                }
            }

            //Console.WriteLine("Image Format: {0}", imageMipMap.format);

            //check if image has mipmaps
            /* using (FileStream imageStream = File.OpenRead(imageWithMipMaps))
            {
                long size = ImageMipMapDataSize(imageMipMap.imgSize, CprFormat(imageMipMap.format), imageMipMap.BPP);
                if (imageStream.Length - headerSize != ImageMipMapDataSize(imageMipMap.imgSize, CprFormat(imageMipMap.format), imageMipMap.BPP))
                {
                    //MessageBox.Show("bytes in file: " + (imageStream.Length - headerSize) + ", bytes calulated: " + ImageMipMapDataSize(imageMipMap.imgSize, imageMipMap.format, imageMipMap.BPP) + ", BPP: " + imageMipMap.BPP + ", format: " + imageMipMap.format);
                    //Console.WriteLine("bytes in file: {0}, bytes calulated: {1}, BPP: {2}", imageStream.Length - headerSize, ImageMipMapDataSize(imageMipMap.imgSize, imageMipMap.format, imageMipMap.BPP), imageMipMap.BPP);
                    throw new FormatException("The image doesn't have any mipmaps");
                }
            } */
            var size = ImageMipMapDataSize(imageMipMap.imgSize, CprFormat(imageMipMap.format), imageMipMap.BPP);
            if (imageMipMap.imgData.Length != size)
                throw new FormatException("The image doesn't have any mipmaps");

            byte[] buffer = null;

            // add the first tga image
            if (fileFormat == ".tga")
            {
                //buffer = new byte[imageMipMap.imgData.Length];
                buffer = imageMipMap.imgData;
                //imageList.Add(imageMipMap);
            }

            // Heff: Use Max to support 1x1 mips for 1:2 ratio images.
            int maxCount = (int)Math.Max(imageMipMap.imgSize.width, imageMipMap.imgSize.height);
            int count = 1;
            int imgDataPos = 0;
            while (count <= maxCount)
            {
                ImageFile newImageFile;
                ImageSize newImageSize = imageMipMap.imgSize / count;
                //if (newImageSize.width < 4 || newImageSize.height < 4)
                //    break;
                int imgDataSize = (int)ImageDataSize(newImageSize, imageMipMap.format, imageMipMap.BPP);

                if (fileFormat == ".dds")
                {
                    buffer = new byte[imgDataSize];
                    Buffer.BlockCopy(imageMipMap.imgData, imgDataPos, buffer, 0, imgDataSize);
                    imgDataPos += imgDataSize;

                    if (imageMipMap.format == "R8G8B8") // Automatic conversion to 32-bit
                    {
                        buffer = ConvertTo32bit(buffer, (int)newImageSize.width, (int)newImageSize.height);
                        newImageFile = new DDS(fileName + "_" + newImageSize + fileFormat, newImageSize, "A8R8G8B8", buffer);
                    }
                    else
                        newImageFile = new DDS(fileName + "_" + newImageSize + fileFormat, newImageSize, imageMipMap.format, buffer);
                }
                else if (fileFormat == ".tga")
                {
                    newImageFile = new TGA(fileName + "_" + newImageSize + fileFormat, newImageSize, imageMipMap.format, buffer);
                    if (newImageSize != new ImageSize(1, 1))
                        buffer = ShrinkImage(buffer, newImageSize, imageMipMap.BPP);
                }
                else
                    throw new FormatException("Invalid image format");

                imageList.Add(newImageFile);

                count *= 2;
            }
        }
Exemplo n.º 2
0
        public void replaceImage(string strImgSize, string fileToReplace, string archiveDir)
        {
            ImageSize imgSize = ImageSize.stringToSize(strImgSize);
            if (!imgList.Exists(img => img.imgSize == imgSize))
                throw new FileNotFoundException("Image with resolution " + imgSize + " isn't found");

            int imageIdx = imgList.FindIndex(img => img.imgSize == imgSize);
            ImageInfo imgInfo = imgList[imageIdx];

            if (!File.Exists(fileToReplace))
                throw new FileNotFoundException("invalid file to replace: " + fileToReplace);

            // check if replacing image is supported
            ImageFile imgFile;
            string fileFormat = Path.GetExtension(fileToReplace);
            switch (fileFormat)
            {
                case ".dds": imgFile = new DDS(fileToReplace, null); break;
                case ".tga": imgFile = new TGA(fileToReplace, null); break;
                default: throw new FileFormatException(fileFormat + " image extension not supported");
            }

            // check if images have same format type
            if (texFormat != imgFile.format)
            {
                DialogResult selection = MessageBox.Show("Warning, replacing image has format " + imgFile.subtype() + " while original has " + texFormat + ", would you like to replace it anyway?", "Warning, different image format found", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                if (selection == DialogResult.Yes)
                    imgFile.format = texFormat;
                else
                    return;
                //throw new FormatException("Different image format, original is " + texFormat + ", new is " + imgFile.subtype());
            }

            byte[] imgBuffer;

            // if the image is empty then recover the archive compression from the image list
            if (imgInfo.storageType == storage.empty)
            {
                imgInfo.storageType = imgList.Find(img => img.storageType != storage.empty && img.storageType != storage.pccSto).storageType;
                imgInfo.uncSize = imgFile.resize().Length;
                imgInfo.cprSize = imgFile.resize().Length;
            }

            switch (imgInfo.storageType)
            {
                case storage.arcCpr: 
                case storage.arcUnc:
                    string archivePath = archiveDir + "\\" + arcName + ".tfc";
                    if (!File.Exists(archivePath))
                        throw new FileNotFoundException("Texture archive not found in " + archivePath);

                    if (getFileFormat() == ".tga")
                        imgBuffer = imgFile.resize(); // shrink image to essential data
                    else
                        imgBuffer = imgFile.imgData;

                    if (imgBuffer.Length != imgInfo.uncSize)
                        throw new FormatException("image sizes do not match, original is " + imgInfo.uncSize + ", new is " + imgBuffer.Length);

                    using (FileStream archiveStream = new FileStream(archivePath, FileMode.Append, FileAccess.Write))
                    {
                        int newOffset = (int)archiveStream.Position;

                        if (imgInfo.storageType == storage.arcCpr)
                        {
                            imgBuffer = ZBlock.Compress(imgBuffer);
                            /*byte[] compressed = ZBlock.Compress(imgBuffer);
                            archiveStream.Write(compressed, 0, compressed.Length);*/
                            imgInfo.cprSize = imgBuffer.Length;
                        }
                        //else
                        archiveStream.Write(imgBuffer, 0, imgBuffer.Length);

                        imgInfo.offset = newOffset;
                    }
                    break;

                case storage.pccSto:
                    imgBuffer = imgFile.imgData; // copy image data as-is
                    if (imgBuffer.Length != imgInfo.uncSize)
                        throw new FormatException("image sizes do not match, original is " + imgInfo.uncSize + ", new is " + imgBuffer.Length);

                    using (MemoryStream dataStream = new MemoryStream(imageData))
                    {
                        dataStream.Seek(imgInfo.offset, SeekOrigin.Begin);
                        dataStream.Write(imgBuffer, 0, imgBuffer.Length);
                    }

                    break;
            }

            imgList[imageIdx] = imgInfo;
        }
Exemplo n.º 3
0
        public void addBiggerImage(string imagePathToAdd, string archiveDir)
        {
            ImageSize biggerImageSizeOnList = imgList.Max(image => image.imgSize);
            // check if replacing image is supported
            ImageFile imgFile;
            string fileFormat = Path.GetExtension(imagePathToAdd);
            switch (fileFormat)
            {
                case ".dds": imgFile = new DDS(imagePathToAdd, null); break;
                case ".tga": imgFile = new TGA(imagePathToAdd, null); break;
                default: throw new FileFormatException(fileFormat + " image extension not supported");
            }

            // check if image to add is valid
            if(biggerImageSizeOnList.width * 2 != imgFile.imgSize.width || biggerImageSizeOnList.height * 2 != imgFile.imgSize.height)
                throw new FormatException("image size " + imgFile.imgSize + " isn't valid, must be " + new ImageSize(biggerImageSizeOnList.width * 2,biggerImageSizeOnList.height * 2));

            // this check avoids insertion inside textures that have only 1 image stored inside pcc
            if(!imgList.Exists(img => img.storageType != storage.empty && img.storageType != storage.pccSto))
                throw new Exception("Unable to add image, texture must have a reference to an external archive");

            // !!! warning, this method breaks consistency between imgList and imageData[] !!!
            ImageInfo newImgInfo = new ImageInfo();
            newImgInfo.storageType = imgList.Find(img => img.storageType != storage.empty && img.storageType != storage.pccSto).storageType;
            newImgInfo.imgSize = imgFile.imgSize;
            newImgInfo.uncSize = imgFile.resize().Length;
            newImgInfo.cprSize = 0x00; // not yet filled
            newImgInfo.offset = 0x00; // not yet filled
            imgList.Insert(0, newImgInfo); // insert new image on top of the list
            //now I let believe the program that I'm doing an image replace, saving lot of code ;)
            replaceImage(newImgInfo.imgSize.ToString(), imagePathToAdd, archiveDir);
            
            //updating num of images
            numMipMaps++;

            // update MipTailBaseIdx
            //PropertyReader.Property MipTail = properties["MipTailBaseIdx"];
            int propVal = properties["MipTailBaseIdx"].Value.IntValue;
            propVal++;
            properties["MipTailBaseIdx"].Value.IntValue = propVal;
            //MessageBox.Show("raw size: " + properties["MipTailBaseIdx"].raw.Length + "\nproperty offset: " + properties["MipTailBaseIdx"].offsetval);
            using (MemoryStream rawStream = new MemoryStream(properties["MipTailBaseIdx"].raw))
            {
                rawStream.Seek(rawStream.Length - 4, SeekOrigin.Begin);
                rawStream.WriteValueS32(propVal);
                properties["MipTailBaseIdx"].raw = rawStream.ToArray();
            }
            //properties["MipTailBaseIdx"] = MipTail;

            // update Sizes
            //PropertyReader.Property Size = properties["SizeX"];
            propVal = (int)newImgInfo.imgSize.width;
            properties["SizeX"].Value.IntValue = propVal;
            using (MemoryStream rawStream = new MemoryStream(properties["SizeX"].raw))
            {
                rawStream.Seek(rawStream.Length - 4, SeekOrigin.Begin);
                rawStream.WriteValueS32(propVal);
                properties["SizeX"].raw = rawStream.ToArray();
            }
            //properties["SizeX"] = Size;
            //Size = properties["SizeY"];
            properties["SizeY"].Value.IntValue = (int)newImgInfo.imgSize.height;
            using (MemoryStream rawStream = new MemoryStream(properties["SizeY"].raw))
            {
                rawStream.Seek(rawStream.Length - 4, SeekOrigin.Begin);
                rawStream.WriteValueS32(propVal);
                properties["SizeY"].raw = rawStream.ToArray();
            }
            //properties["SizeY"] = Size;
            properties["OriginalSizeX"].Value.IntValue = propVal;
            using (MemoryStream rawStream = new MemoryStream(properties["OriginalSizeX"].raw))
            {
                rawStream.Seek(rawStream.Length - 4, SeekOrigin.Begin);
                rawStream.WriteValueS32(propVal);
                properties["OriginalSizeX"].raw = rawStream.ToArray();
            }
            properties["OriginalSizeY"].Value.IntValue = propVal;
            using (MemoryStream rawStream = new MemoryStream(properties["OriginalSizeY"].raw))
            {
                rawStream.Seek(rawStream.Length - 4, SeekOrigin.Begin);
                rawStream.WriteValueS32(propVal);
                properties["OriginalSizeY"].raw = rawStream.ToArray();
            }
        }
Exemplo n.º 4
0
        public void extractImage(ImageInfo imgInfo, string archiveDir = null, string fileName = null)
        {
            ImageFile imgFile;
            if (fileName == null)
            {
                fileName = texName + "_" + imgInfo.imgSize + getFileFormat();
            }

            byte[] imgBuffer;

            switch (imgInfo.storageType)
            {
                case storage.pccSto:
                    imgBuffer = new byte[imgInfo.uncSize];
                    Buffer.BlockCopy(imageData, imgInfo.offset, imgBuffer, 0, imgInfo.uncSize);
                    break;
                case storage.arcCpr:
                case storage.arcUnc:
                    string archivePath = archiveDir + "\\" + arcName + ".tfc";
                    if (!File.Exists(archivePath))
                    {
                        throw new FileNotFoundException("Texture archive not found in " + archivePath);
                    }

                    using (FileStream archiveStream = File.OpenRead(archivePath))
                    {
                        archiveStream.Seek(imgInfo.offset, SeekOrigin.Begin);
                        if (imgInfo.storageType == storage.arcCpr)
                        {
                            imgBuffer = ZBlock.Decompress(archiveStream, imgInfo.cprSize);
                        }
                        else
                        {
                            imgBuffer = new byte[imgInfo.uncSize];
                            archiveStream.Read(imgBuffer, 0, imgBuffer.Length);
                        }
                    }
                    break;
                default:
                    throw new FormatException("Unsupported texture storage type");
            }

            if (getFileFormat() == ".dds")
                imgFile = new DDS(fileName, imgInfo.imgSize, texFormat, imgBuffer);
            else
                imgFile = new TGA(fileName, imgInfo.imgSize, texFormat, imgBuffer);

            byte[] saveImg = imgFile.ToArray();
            using (FileStream outputImg = new FileStream(imgFile.fileName, FileMode.Create, FileAccess.Write))
                outputImg.Write(saveImg, 0, saveImg.Length);
        }
Exemplo n.º 5
0
        public void replaceImage(string strImgSize, string fileToReplace)
        {
            ImageSize imgSize = ImageSize.stringToSize(strImgSize);
            if (!imgList.Exists(img => img.imgSize == imgSize))
                throw new FileNotFoundException("Image with resolution " + imgSize + " isn't found");

            int imageIdx = imgList.FindIndex(img => img.imgSize == imgSize);
            ImageInfo imgInfo = imgList[imageIdx];

            if (!File.Exists(fileToReplace))
                throw new FileNotFoundException("invalid file to replace: " + fileToReplace);

            // check if replacing image is supported
            ImageFile imgFile;
            string fileFormat = Path.GetExtension(fileToReplace);
            switch (fileFormat)
            {
                case ".dds": imgFile = new DDS(fileToReplace, null); break;
                case ".DDS": imgFile = new DDS(fileToReplace, null); break;
                case ".tga": imgFile = new TGA(fileToReplace, null); break;
                case ".TGA": imgFile = new TGA(fileToReplace, null); break;
                default: throw new FormatException(fileFormat + " image extension not supported");
            }

            if (imgFile.imgSize.height != imgInfo.imgSize.height || imgFile.imgSize.width != imgInfo.imgSize.width)
                throw new FormatException("Incorrect input texture dimensions. Expected: " + imgInfo.imgSize.ToString());

            // check if images have same format type
            if (texFormat != imgFile.format && texFormat != ("PF_" + imgFile.format) && imgFile.format != "ATI2")
            {
                throw new FormatException("Different image format, original is " + texFormat + ", new is " + imgFile.subtype());
            }

            byte[] imgBuffer;

            // if the image is empty then recover the archive compression from the image list
            if (imgInfo.storageType == storage.empty)
            {
                imgInfo.storageType = imgList.Find(img => img.storageType != storage.empty && img.storageType != storage.pccSto).storageType;
                imgInfo.uncSize = imgFile.resize().Length;
                imgInfo.cprSize = imgFile.resize().Length;
            }

            switch (imgInfo.storageType)
            {
                case storage.arcCpr:
                case storage.arcUnc:
                    throw new NotImplementedException("Texture replacement not supported in external packages yet");
                case storage.pccSto:
                    imgBuffer = imgFile.resize();
                    using (MemoryStream dataStream = new MemoryStream())
                    {
                        dataStream.WriteBytes(imageData);
                        if (imgBuffer.Length <= imgInfo.uncSize && imgInfo.offset > 0)
                            dataStream.Seek(imgInfo.offset, SeekOrigin.Begin);
                        else
                            imgInfo.offset = (int)dataStream.Position;
                        dataStream.WriteBytes(imgBuffer);
                        imgInfo.cprSize = imgBuffer.Length;
                        imgInfo.uncSize = imgBuffer.Length;
                        imageData = dataStream.ToArray();
                    }
                    break;
                case storage.pccCpr:
                    using (MemoryStream dataStream = new MemoryStream())
                    {
                        dataStream.WriteBytes(imageData);
                        SaltLZOHelper lzohelper = new SaltLZOHelper();
                        imgBuffer = lzohelper.CompressTex(imgFile.resize());
                        if (imgBuffer.Length <= imgInfo.cprSize && imgInfo.offset > 0)
                            dataStream.Seek(imgInfo.offset, SeekOrigin.Begin);
                        else
                            imgInfo.offset = (int)dataStream.Position;
                        dataStream.WriteBytes(imgBuffer);
                        imgInfo.cprSize = imgBuffer.Length;
                        imgInfo.uncSize = imgFile.resize().Length;
                        imageData = dataStream.ToArray();
                    }
                    break;
            }

            imgList[imageIdx] = imgInfo;
        }
Exemplo n.º 6
0
        public void extractImage(ImageInfo imgInfo, string archiveDir = null, string fileName = null)
        {
            ImageFile imgFile;
            if (fileName == null)
                fileName = texName + "_" + imgInfo.imgSize + getFileFormat();

            byte[] imgBuffer = null;

            switch (imgInfo.storageType)
            {
                case storage.pccSto:
                    imgBuffer = new byte[imgInfo.uncSize];
                    Buffer.BlockCopy(imageData, imgInfo.offset, imgBuffer, 0, imgInfo.uncSize);
                    break;
                case storage.arcCpr:
                case storage.arcUnc:
                    string archivePath = FindFile();
                    if (String.IsNullOrEmpty(archivePath))
                        throw new FileNotFoundException();
                    PCCObject temp = new PCCObject(archivePath);
                    for (int i = 0; i < temp.ExportCount; i++)
                    {
                        if (String.Compare(texName, temp.Exports[i].ObjectName, true) == 0 && temp.Exports[i].ClassName == "Texture2D")
                        {
                            Texture2D temptex = new Texture2D(temp, i);
                            temptex.extractImage(imgInfo.imgSize.ToString(), temp, null, fileName);
                        }
                    }
                    break;
                case storage.pccCpr:
                    using (MemoryStream ms = new MemoryStream(imageData))
                    {
                        SaltLZOHelper lzohelp = new SaltLZOHelper();
                        imgBuffer = lzohelp.DecompressTex(ms, imgInfo.offset, imgInfo.uncSize, imgInfo.cprSize);
                    }
                    break;
                default:
                    throw new FormatException("Unsupported texture storage type");
            }

            if (imgInfo.storageType == storage.pccSto || imgInfo.storageType == storage.pccCpr)
            {
                if (getFileFormat() == ".dds")
                    imgFile = new DDS(fileName, imgInfo.imgSize, texFormat, imgBuffer);
                else
                    imgFile = new TGA(fileName, imgInfo.imgSize, texFormat, imgBuffer);

                byte[] saveImg = imgFile.ToArray();
                using (FileStream outputImg = new FileStream(imgFile.fileName, FileMode.Create, FileAccess.Write))
                    outputImg.Write(saveImg, 0, saveImg.Length);
            }
        }
Exemplo n.º 7
0
        public ImageMipMapHandler(string imageWithMipMaps, byte[] data)
        {
            imageWithMipMaps = (imageWithMipMaps == "") ? ".dds" : imageWithMipMaps;
            imageList        = new List <ImageFile>();
            string    fileFormat = Path.GetExtension(imageWithMipMaps).ToLowerInvariant();
            string    fileName   = Path.GetFileNameWithoutExtension(imageWithMipMaps);
            ImageFile imageMipMap;
            int       headerSize;

            if (data != null)
            {
                headerSize  = 128;
                imageMipMap = new DDS("", data);
            }
            else
            {
                switch (fileFormat)
                {
                case ".dds":
                    headerSize  = 128;
                    imageMipMap = new DDS(imageWithMipMaps, null);
                    break;

                case ".tga":
                    headerSize  = 18;
                    imageMipMap = new TGA(imageWithMipMaps, null);
                    break;

                default: throw new FormatException("Invalid image format");
                }
            }

            //Console.WriteLine("Image Format: {0}", imageMipMap.format);

            //check if image has mipmaps

            /* using (FileStream imageStream = File.OpenRead(imageWithMipMaps))
             * {
             *  long size = ImageMipMapDataSize(imageMipMap.imgSize, CprFormat(imageMipMap.format), imageMipMap.BPP);
             *  if (imageStream.Length - headerSize != ImageMipMapDataSize(imageMipMap.imgSize, CprFormat(imageMipMap.format), imageMipMap.BPP))
             *  {
             *      //MessageBox.Show("bytes in file: " + (imageStream.Length - headerSize) + ", bytes calulated: " + ImageMipMapDataSize(imageMipMap.imgSize, imageMipMap.format, imageMipMap.BPP) + ", BPP: " + imageMipMap.BPP + ", format: " + imageMipMap.format);
             *      //Console.WriteLine("bytes in file: {0}, bytes calulated: {1}, BPP: {2}", imageStream.Length - headerSize, ImageMipMapDataSize(imageMipMap.imgSize, imageMipMap.format, imageMipMap.BPP), imageMipMap.BPP);
             *      throw new FormatException("The image doesn't have any mipmaps");
             *  }
             * } */



            // KFreon: This can be wrong too much. Single mip images etc.

            /*
             * var size = ImageMipMapDataSize(imageMipMap.imgSize, CprFormat(imageMipMap.format), imageMipMap.BPP);
             * if (imageMipMap.imgData.Length != size)
             *  throw new FormatException("The image doesn't have any mipmaps");*/

            byte[] buffer = null;

            // add the first tga image
            if (fileFormat == ".tga")
            {
                //buffer = new byte[imageMipMap.imgData.Length];
                buffer = imageMipMap.imgData;
                //imageList.Add(imageMipMap);
            }

            // Heff: Use Max to support 1x1 mips for 1:2 ratio images.
            int maxCount   = (int)Math.Max(imageMipMap.imgSize.width, imageMipMap.imgSize.height);
            int count      = 1;
            int imgDataPos = 0;

            while (count <= maxCount)
            {
                ImageFile newImageFile;
                ImageSize newImageSize = imageMipMap.imgSize / count;
                //if (newImageSize.width < 4 || newImageSize.height < 4)
                //    break;
                int imgDataSize = (int)ImageDataSize(newImageSize, imageMipMap.format, imageMipMap.BPP);

                if (fileFormat == ".dds")
                {
                    buffer = new byte[imgDataSize];
                    Buffer.BlockCopy(imageMipMap.imgData, imgDataPos, buffer, 0, imgDataSize);
                    imgDataPos += imgDataSize;

                    if (imageMipMap.format == "R8G8B8") // Automatic conversion to 32-bit
                    {
                        buffer       = ConvertTo32bit(buffer, (int)newImageSize.width, (int)newImageSize.height);
                        newImageFile = new DDS(fileName + "_" + newImageSize + fileFormat, newImageSize, "A8R8G8B8", buffer);
                    }
                    else
                    {
                        newImageFile = new DDS(fileName + "_" + newImageSize + fileFormat, newImageSize, imageMipMap.format, buffer);
                    }
                }
                else if (fileFormat == ".tga")
                {
                    newImageFile = new TGA(fileName + "_" + newImageSize + fileFormat, newImageSize, imageMipMap.format, buffer);
                    if (newImageSize != new ImageSize(1, 1))
                    {
                        buffer = ShrinkImage(buffer, newImageSize, imageMipMap.BPP);
                    }
                }
                else
                {
                    throw new FormatException("Invalid image format");
                }

                imageList.Add(newImageFile);

                count *= 2;
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// Load an image into one of AK86's classes.
        /// </summary>
        /// <param name="im">AK86 image already, just return it unless null. Then load from fileToLoad.</param>
        /// <param name="fileToLoad">Path to file to be loaded. Irrelevent if im is provided.</param>
        /// <returns>AK86 Image file.</returns>
        public static ImageFile LoadAKImageFile(ImageFile im, string fileToLoad)
        {
            ImageFile imgFile = null;
            if (im != null)
                imgFile = im;
            else
            {
                if (!File.Exists(fileToLoad))
                    throw new FileNotFoundException("invalid file to replace: " + fileToLoad);

                // check if replacing image is supported
                string fileFormat = Path.GetExtension(fileToLoad);
                switch (fileFormat)
                {
                    case ".dds": imgFile = new DDS(fileToLoad, null); break;
                    case ".tga": imgFile = new TGA(fileToLoad, null); break;
                    default: throw new FileNotFoundException(fileFormat + " image extension not supported");
                }
            }
            return imgFile;
        }