/*=========================================================================== * * File: Dfimg.CPP * Author: Dave Humphrey (uesp@m0use.net) * Created On: Monday, June 25, 2001 * * Implements the CDFImgFile class for handling Daggerfall IMG files. * *=========================================================================*/ /* Include Files */ #include "dfimg.h" /*=========================================================================== * * Begin Local Variable Definitions * *=========================================================================*/ DEFINE_FILE(); /*=========================================================================== * End of Local Variable Definitions *=========================================================================*/ /*=========================================================================== * * Class CDFImgFile Constructor * *=========================================================================*/ CDFImgFile::CDFImgFile() { /* Initialize the image data and palette pointers */ m_pData = NULL; m_pPalette = NULL; /* Initialize the IMG header */ m_Header.Width = 0; m_Header.Height = 0; m_Header.XOffset = 0; m_Header.YOffset = 0; m_Header.Unknown = 0; m_Header.ImageSize = 0; m_ImageSize = 0; /* Initialize the object flags */ m_Flags = 0; } /*=========================================================================== * End of Class CDFImgFile Constructor *=========================================================================*/ /*=========================================================================== * * Class CDFImgFile Destructor * *=========================================================================*/ void CDFImgFile::Destroy (void) { DEFINE_FUNCTION("CDFImgFile::Destroy()"); /* Delete any allocated image data */ DestroyArrayPointer(m_pData); DestroyArrayPointer(m_pPalette); /* Re-initialize the IMG header */ m_Header.Width = 0; m_Header.Height = 0; m_Header.XOffset = 0; m_Header.YOffset = 0; m_Header.Unknown = 0; m_Header.ImageSize = 0; m_ImageSize = 0; /* Re-initialize the object flags */ m_Flags = 0; } /*=========================================================================== * End of Class CDFImgFile Destructor *=========================================================================*/ /*=========================================================================== * * Class CDFImgFile Method - boolean CheckSpecialIMG (IMGInfo, FileSize); * * Checks the given IMG filesize to see if it matches any special IMG * format. If it does, TRUE is returned and the Header structure is * filled in with the appropiate image width, height, size and flags. FALSE * is returned if the IMG filesize does not match any known special formats. * *=========================================================================*/ boolean CDFImgFile::CheckSpecialIMG (dfimginfo_t& IMGInfo, const long FileSize) { DEFINE_FUNCTION("CDFImgFile::CheckSpecialIMG()"); static dfimginfo_t s_ImgInfo[] = { /* Describes the special formats */ /* Size, Width, Height, Flags */ { 720l, 9, 80, DFIMG_FLAG_HASNOHEADER }, { 990l, 45, 22, DFIMG_FLAG_HASNOHEADER }, { 1720l, 43, 40, DFIMG_FLAG_HASNOHEADER }, { 2140l, 107, 20, DFIMG_FLAG_HASNOHEADER }, { 2916l, 81, 36, DFIMG_FLAG_HASNOHEADER }, { 3200l, 40, 80, DFIMG_FLAG_HASNOHEADER }, { 3938l, 179, 22, DFIMG_FLAG_HASNOHEADER }, { 4508l, 322, 14, DFIMG_FLAG_HASNOHEADER }, { 4280l, 107, 40, DFIMG_FLAG_HASNOHEADER }, { 20480l, 320, 64, DFIMG_FLAG_HASNOHEADER }, { 26496l, 184, 144, DFIMG_FLAG_HASNOHEADER }, { 64000l, 320, 200, DFIMG_FLAG_HASNOHEADER }, { 64768l, 320, 200, DFIMG_FLAG_HASNOHEADER | DFIMG_FLAG_HASPALETTE }, { 68800l, 320, 215, DFIMG_FLAG_HASNOHEADER }, { 112128l, 512, 219, DFIMG_FLAG_HASNOHEADER }, { 0, 0, 0, 0 } /* Must be last element */ }; int Index; /* Ensure valid input */ ASSERT(FileSize > 0); /* Search static array for filesize match */ for (Index = 0; s_ImgInfo[Index].FileSize != 0; Index++) { if (s_ImgInfo[Index].FileSize == FileSize) { IMGInfo = s_ImgInfo[Index]; return (TRUE); } } /* Image is not a known special format */ return (FALSE); } /*=========================================================================== * End of Class Method CDFImgFile::CheckSpecialIMG() *=========================================================================*/ /*=========================================================================== * * Class CDFImgFile Method - boolean Load (pFilename); * * Opens and read a IMG file. Returns FALSE on any error. * *=========================================================================*/ boolean CDFImgFile::Load (const char* pFilename) { dfimginfo_t IMGInfo; boolean Result; /* Delete the current image contents */ Destroy(); /* Attempt to open file for input */ Result = Open(pFilename, "rb"); if (!Result) return (FALSE); /* Check special IMG files by checking the file size */ Result = CheckSpecialIMG(IMGInfo, GetFileSize()); if (Result) { m_Flags = IMGInfo.Flags; SetWidth(IMGInfo.Width); SetHeight(IMGInfo.Height); m_ImageSize = (long) IMGInfo.Width * (long) IMGInfo.Height; m_Header.ImageSize = (ushort) m_ImageSize; } /* Read the image file */ Result = Read(); Close(); return (Result); } /*=========================================================================== * End of Class Method CDFImgFile::Load() *=========================================================================*/ /*=========================================================================== * * Class CDFImgFile Method - boolean Save (pFilename); * * Opens and writes an IMG file. Returns FALSE on any error. * *=========================================================================*/ boolean CDFImgFile::Save (const char* pFilename) { boolean Result; /* Attempt to open file for output */ Result = Open(pFilename, "wb"); if (!Result) return (FALSE); /* Write image file */ Result = Write(); Close(); return (Result); } /*=========================================================================== * End of Class Method CDFImgFile::Save() *=========================================================================*/ /*=========================================================================== * * Class CDFImgFile Method - boolean Read (void); * * Read an IMG file from the current position in the file. Returns FALSE * on any error. * *=========================================================================*/ boolean CDFImgFile::Read (void) { DEFINE_FUNCTION("CDFImgFile::Read()"); boolean Result = TRUE; /* Ensure an open file */ ASSERT(IsOpen()); /* Read in the image header if required */ if (HasHeader()) Result = ReadHeader(); /* Read in the image data */ if (Result) Result = ReadData(); /* Read in the palette data if present */ if (Result && HasPalette()) Result = ReadPalette(); return (Result); } /*=========================================================================== * End of Class Method CDFImgFile::Read() *=========================================================================*/ /*=========================================================================== * * Class CDFImgFile Method - boolean ReadHeader (void); * * Protected class method which reads in the IMF file header from the * current position in the file. Returns FALSE on any error. * *=========================================================================*/ boolean CDFImgFile::ReadHeader (void) { DEFINE_FUNCTION("CDFImgFile::ReadHeader()"); boolean Result; /* Ensure valid parameters */ ASSERT(HasHeader()); /* Input header all at once */ Result = CGenFile::Read((char*)&m_Header, sizeof(dfimgheader_t)); if (!Result) return (FALSE); m_ImageSize = (long)GetWidth() * (long)GetHeight(); return (TRUE); } /*=========================================================================== * End of Class Method CDFImgFile::ReadHeader() *=========================================================================*/ /*=========================================================================== * * Class CDFImgFile Method - boolean ReadData (void); * * Protected class method which reads in the uncompressed image data from * the current position in the file. Returns FALSE on any error. * *=========================================================================*/ boolean CDFImgFile::ReadData (void) { DEFINE_FUNCTION("CDFImgFile::ReadData()"); boolean Result; /* Ensure valid object state */ ASSERT(m_pData == NULL); /* Check for valid image size */ if (m_ImageSize < 0 || (ulong)m_ImageSize >= (ulong) UINT_MAX) { ErrorHandler.AddError(DFERR_IMG_IMAGESIZE); return (FALSE); } /* Ignore if no data to load */ if (m_ImageSize == 0) return (TRUE); /* Allocate the image data */ CreateArrayPointer(m_pData, byte, (size_t)m_ImageSize); /* Read in image data all at once */ Result = CGenFile::Read((char*)m_pData, (size_t)m_ImageSize); return (Result); } /*=========================================================================== * End of Class Method CDFImgFile::ReadData() *=========================================================================*/ /*=========================================================================== * * Class CDFImgFile Method - boolean ReadPalette (void); * * Reads the optional image palette data from the current position in the * file stream. Returns FALSE on any error. Protected class method. * *=========================================================================*/ boolean CDFImgFile::ReadPalette (void) { DEFINE_FUNCTION("CDFImgFile::ReadPalette()"); /* Ensure valid state */ ASSERT(HasPalette() && m_pPalette == NULL); /* Allocate and read palette data */ CreateArrayPointer(m_pPalette, rgbpalraw_t, DFIMG_PALETTE_SIZE); return CGenFile::Read((char*)m_pPalette, DFIMG_PALETTE_SIZE*sizeof(rgbpalraw_t)); } /*=========================================================================== * End of Class Method CDFImgFile::ReadPalette() *=========================================================================*/ /*=========================================================================== * * Class CDFImgFile Method - boolean Write (void); * * Attempts to output the current image data to the current file stream. * Returns FALSE on any error. * *=========================================================================*/ boolean CDFImgFile::Write (void) { DEFINE_FUNCTION("CDFImgFile::Write()"); boolean Result = TRUE; /* Ensure a valid file stream */ ASSERT(IsOpen()); /* Write the image header if required */ if (HasHeader()) Result = WriteHeader(); /* Write the image data */ if (Result) Result = WriteData(); /* Write in the palette data if present */ if (Result && HasPalette()) Result = WritePalette(); return (Result); } /*=========================================================================== * End of Class Method CDFImgFile::Write() *=========================================================================*/ /*=========================================================================== * * Class CDFImgFile Method - boolean WriteHeader (void); * * Protected class method which outputs the header data to the current * position in the file stream. Returns FALSE on any error. * *=========================================================================*/ boolean CDFImgFile::WriteHeader (void) { DEFINE_FUNCTION("CDFImgFile::WriteHeader()"); boolean Result; /* Ensure valid state */ ASSERT(HasHeader()); /* Write header all at once */ Result = CGenFile::Write((char *)&m_Header, sizeof(dfimgheader_t)); return (Result); } /*=========================================================================== * End of Class Method CDFImgFile::WriteHeader() *=========================================================================*/ /*=========================================================================== * * Class CDFImgFile Method - boolean WriteData (void); * * Protected class method which outputs the image data to the current * position in the file stream. Returns FALSE on any error. * *=========================================================================*/ boolean CDFImgFile::WriteData (void) { DEFINE_FUNCTION("CDFImgFile::WriteData()"); /* Ignore if no image data to output */ if (m_ImageSize == 0) return (TRUE); /* Output data all at once */ return CGenFile::Write((char *)m_pData, (size_t) m_ImageSize); } /*=========================================================================== * End of Class Method CDFImgFile::WriteData() *=========================================================================*/ /*=========================================================================== * * Class CDFImgFile Method - boolean WritePalette (void); * * Protected class method which writes the optional image palette data to * the current position in the data file. Returns FALSE on any error. * *=========================================================================*/ boolean CDFImgFile::WritePalette (void) { DEFINE_FUNCTION("CDFImgFile::WritePalette()"); /* Ensure valid object state */ ASSERT(HasPalette()); /* Write palette data all at once */ return CGenFile::Write((char*)m_pPalette, DFIMG_PALETTE_SIZE*sizeof(rgbpalraw_t)); } /*=========================================================================== * End of Class Method CDFImgFile::WritePalette() *=========================================================================*/