/* ** Command & Conquer Renegade(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ /**************************************************************************** * * C O N F I D E N T I A L --- W E S T W O O D S T U D I O S * *---------------------------------------------------------------------------- * * FILE * targa.cpp * * DESCRIPTION * Targa image file class. * * PROGRAMMER * Denzil E. Long, Jr. * * DATE * August 8, 1995 * *---------------------------------------------------------------------------- * * PUBLIC * Open - Open Targa image file. * Close - Close Targa image file. * Load - Load Targa image file. * Save - Save a Targa Image File. * XFlip - X flip the image. * YFlip - Y flip the image. * SetImage - Set the image buffer. * GetImage - Get the current image buffer address. * SetPalette - Set the palette buffer. * GetPalette - Retrieve the current palette buffer address. * GetExtension - Get Extension data. (Targa 2.0 files only) * * PRIVATE * DecodeImage - Decompress Targa image data. * EncodeImage - Compress the image using targa RLE. * InvertImage - Invert TrueColor image data. * * MODIFICATIONS: * Converted to work with FileClass, FileFactory (changes are inside * ifdefs, so can be easily reversed). Naty Hoffman, January 25, 2001 * ****************************************************************************/ #include "targa.h" #ifndef TGA_USES_WWLIB_FILE_CLASSES #include #endif #include #include #include #ifdef TGA_USES_WWLIB_FILE_CLASSES #include "wwfile.h" #include "ffactory.h" #else #include #include #include #endif /**************************************************************************** * * NAME * Targa::Targa - Initialize a Targa instance. * * SYNOPSIS * Targa() * * void Targa(void); * * FUNCTION * Initialize the targa class instance. * * INPUTS * NONE * * RESULT * NONE * ****************************************************************************/ Targa::Targa(void) { mImage = NULL; mPalette = NULL; Clear_File(); mAccess = TGA_READMODE; mFlags = 0; memset(&Header, 0, sizeof(TGAHeader)); memset(&mExtension, 0, sizeof(TGA2Extension)); } /**************************************************************************** * * NAME * Targa::~Targa - Targa class destructor. * * SYNOPSIS * ~Targa() * * void ~Targa(void); * * FUNCTION * * INPUTS * NONE * * RESULT * NONE * ****************************************************************************/ Targa::~Targa(void) { /* Close the file if has been left open. */ Close(); /* Free the palette buffer if we allocated it. */ if ((mPalette != NULL) && (mFlags & TGAF_PAL)) free(mPalette); /* Free the image buffer if we allocated it. */ if ((mImage != NULL) && (mFlags & TGAF_IMAGE)) free(mImage); } /**************************************************************************** * * NAME * Targa::Open - Open Targa image file. * * SYNOPSIS * Error = Open(Name, Mode) * * long Open(char *, long); * * FUNCTION * Open a Targa image file and read in its header. The file stream will * positioned after the ID field (if there is one). * * INPUTS * Name - Pointer to name of Targa file. * Mode - Access mode. * * RESULT * Error - Error code, 0 if okay. * ****************************************************************************/ long Targa::Open(const char* name, long mode) { TGA2Footer footer; long size; long error = 0; /* File already open? */ if (Is_File_Open() && (mAccess == mode)) { return (0); } Close(); /* Initialize the access mode. */ mAccess = mode; mFlags &= ~TGAF_TGA2; switch (mode) { /* Open targa file for read. */ case TGA_READMODE: if (File_Open_Read(name)) { /* Check for 2.0 targa file by loading the footer */ if (File_Seek(-26, SEEK_END) == -1) { error = TGAERR_READ; } if (!error) { if (File_Read(&footer, sizeof(TGA2Footer)) != sizeof(TGA2Footer)) { error = TGAERR_READ; } else { /* If this a 2.0 file with an extension? */ if (strncmp(footer.Signature, TGA2_SIGNATURE, 16) == 0) { if (footer.Extension != 0) { mFlags |= TGAF_TGA2; } } } } /* Read in Extension data */ if (!error && (mFlags & TGAF_TGA2)) { if (File_Seek(footer.Extension, SEEK_SET) == -1) { error = TGAERR_READ; } if (!error) { if (File_Read(&mExtension, sizeof(TGA2Extension)) != sizeof(TGA2Extension)) { error = TGAERR_READ; } } } /* Read in header. */ if (!error && (File_Seek(0, SEEK_SET) == -1)) { error = TGAERR_READ; } else { size = File_Read(&Header, sizeof(TGAHeader)); if (size != sizeof(TGAHeader)) { error = TGAERR_READ; } } /* Skip the ID field */ if (!error && (Header.IDLength != 0)) { if (File_Seek(Header.IDLength, SEEK_CUR) == -1) { error = TGAERR_READ; } } } else { error = TGAERR_OPEN; } break; /* Open targa file for write. */ case TGA_WRITEMODE: if (!File_Open_Write(name)) { error = TGAERR_OPEN; } else { // printf("\r"); } break; /* Open targa file for read/write.*/ case TGA_RDWRMODE: if (File_Open_ReadWrite(name)) { /* Read in header. */ size = File_Read(&Header, sizeof(TGAHeader)); if (size != sizeof(TGAHeader)) { error = TGAERR_READ; } /* Skip the ID field */ if (!error && (Header.IDLength != 0)) { if (File_Seek(Header.IDLength, SEEK_CUR) == -1) { error = TGAERR_READ; } } } else { error = TGAERR_OPEN; } break; } /* Close on any error! */ if (error) { Close(); } return (error); } /**************************************************************************** * * NAME * Targa::Close - Close Targa image file. * * SYNOPSIS * Close() * * void Close(void); * * FUNCTION * Close the Targa image file and free its handle. * * INPUTS * NONE * * RESULT * NONE * ****************************************************************************/ void Targa::Close(void) { #ifdef TGA_USES_WWLIB_FILE_CLASSES if (TGAFile) { TGAFile->Close(); _TheFileFactory->Return_File(TGAFile); TGAFile = NULL; } #else /* Close the file if it is open. */ if (mFH != -1) { close(mFH); mFH = -1; } #endif } /**************************************************************************** * * NAME * Targa::Load - Load Targa Image File into specified buffers. * * SYNOPSIS * Error = Load(Name, Palette, ImageBuffer) * * long Load(char *, char *, char *); * * FUNCTION * Open and load the Targa into the specified buffers. If either buffer * pointer is NULL then that field will not be processed. * * INPUTS * Name - Name of Targa image file to load. * Palette - Pointer to buffer to load the palette into. * ImageBuffer - Pointer to buffer to load the image data into. * * RESULT * Error - 0 if successful, or TGAERR_??? error code. * ****************************************************************************/ long Targa::Load(const char* name, char* palette, char* image,bool invert_image) { long size; long depth; long error = 0; /* Open the Targa */ if (Open(name, TGA_READMODE) == NULL) { /* Process ColorMap (palette) */ if (Header.ColorMapType == 1) { depth = (Header.CMapDepth >> 3); size = (Header.CMapLength * depth); /* Load the palette from the TGA if a palette buffer is provided * otherwise we will skip it. */ if ((palette != NULL) && (Header.CMapLength > 0)) { /* Adjust palette to the starting color entry. */ palette += (Header.CMapStart * depth); /* Read in the palette. */ if (File_Read(palette, size) != size) { error = TGAERR_READ; } } else { if (File_Seek(size, SEEK_CUR) == -1) { error = TGAERR_READ; } } } /* Load the image data from the TGA if an image buffer is provided * otherwise we are done. */ if (!error && (image != NULL)) { depth = TGA_BytesPerPixel(Header.PixelDepth); size = ((Header.Width * Header.Height) * depth); switch (Header.ImageType) { case TGA_CMAPPED: if (File_Read(image, size) != size) { error = TGAERR_READ; } break; case TGA_TRUECOLOR: if (File_Read(image, size) == size) { if (invert_image) InvertImage(); } else { error = TGAERR_READ; } break; case TGA_MONO: if (File_Read(image, size) != size) { error = TGAERR_READ; } break; case TGA_CMAPPED_ENCODED: error = DecodeImage(); break; case TGA_TRUECOLOR_ENCODED: if ((error = DecodeImage()) == NULL) { if (invert_image) InvertImage(); } break; default: error = TGAERR_NOTSUPPORTED; break; } /* Arrange the image so that the origin position (coordinate 0,0) * is the upperleft hand corner of the image. */ if (!error) { if ( Header.ImageDescriptor & TGAIDF_XORIGIN ) { XFlip(); Header.ImageDescriptor &= ~TGAIDF_XORIGIN; } // Mod (IML) : Locate the origin at the bottom-left corner instead. This // will make ot consistent with .TGA's that have been generated with our // existing software. // if (( Header.ImageDescriptor & TGAIDF_YORIGIN ) == 0){ if ( Header.ImageDescriptor & TGAIDF_YORIGIN ) { YFlip(); // Bug fix (IML) : Clear this flag to indicate to the targa reader // that the Y-origin is at the bottom of the image. Header.ImageDescriptor &= ~TGAIDF_YORIGIN; } } } /* Close the Targa */ Close(); } else { error = TGAERR_OPEN; } return (error); } /**************************************************************************** * * NAME * Targa::Load - Load Targa Image File. (Auto buffer allocation). * * SYNOPSIS * Error = Load(Name, Flags) * * long Load(char, long); * * FUNCTION * Open and load the Targa into buffers allocated by this function. * * INPUTS * Name - Name of Targa image file to load. * Flags - * * RESULT * Error - 0 if successful, or TGAERR_??? error code. * ****************************************************************************/ long Targa::Load(const char* name, long flags, bool invert_image) { long size; long error = 0; /* Open the file to get the header. */ if (Open(name, TGA_READMODE) == 0) { /* Allocate palette memory if requested to and the targa has one. */ if ((flags & TGAF_PAL) && (Header.ColorMapType == 1)) { /* Dispose of any previous palette. */ if ((mPalette != NULL) && (mFlags & TGAF_PAL)) { free(mPalette); mPalette = NULL; mFlags &= ~TGAF_PAL; } /* Only allocate a palette if the client hasn't assigned one. */ if ((mPalette == NULL) && !(mFlags & TGAF_PAL)) { /* Compute the size of the palette from the targa header. */ size = (Header.CMapLength * (Header.CMapDepth >> 3)); if (size != 0) { /* Allocate memory for the palette. */ if ((mPalette = (char *)malloc(size)) != NULL) { mFlags |= TGAF_PAL; /* We allocated the palette. */ } else { error = TGAERR_NOMEM; } } } } /* Allocate image memory if requested to. */ if (!error && (flags & TGAF_IMAGE)) { /* Dispose of any previous image. */ if ((mImage != NULL) && (mFlags & TGAF_IMAGE)) { free(mImage); mImage = NULL; mFlags &= ~TGAF_IMAGE; } /* Only allocate an image if the client hasn't assigned one. */ if ((mImage == NULL) && !(mFlags & TGAF_IMAGE)) { /* Compute the size of the image data from the targa header. */ size = ((Header.Width * Header.Height) * TGA_BytesPerPixel(Header.PixelDepth)); if (size != 0) { /* Allocate memory for the image. */ if ((mImage = (char *)malloc(size)) != NULL) { mFlags |= TGAF_IMAGE; /* We allocated the image. */ } else { error = TGAERR_NOMEM; } } } } /* Read in the file contents. */ if (!error) { error = Load(name, mPalette, mImage, invert_image); } /* Close the file. */ Close(); } else { error = TGAERR_OPEN; } return (error); } /**************************************************************************** * * NAME * Targa::Save - Save a Targa Image File. * * SYNOPSIS * Error = Save(Name, Flags) * * long Save(char *, long); * * FUNCTION * * INPUTS * Name - Pointer to name of file to save. * Flags - * * RESULT * Error - 0 if successful, or TGAERR_??? error code. * ****************************************************************************/ long Targa::Save(const char* name, long flags, bool addextension) { long size; long depth; char *palette; char *temppal; char *ptr; //long i,n; //char c; long error = 0; TGA2Footer footer; /* Open the Targa for write. */ if (Open(name, TGA_WRITEMODE) == NULL) { Header.IDLength = 0; /* Set the ImageType for compression. */ if (flags & TGAF_COMPRESS) { switch (Header.ImageType) { case TGA_CMAPPED: case TGA_TRUECOLOR: case TGA_MONO: Header.ImageType += 8; break; case TGA_CMAPPED_ENCODED: case TGA_TRUECOLOR_ENCODED: case TGA_MONO_ENCODED: break; /* Turn off compression for unknown types. */ default: flags &= ~TGAF_COMPRESS; break; } } /*----------------------------------------------------------------------- * WRITE THE HEADER DATA SECTION *---------------------------------------------------------------------*/ if (File_Write(&Header, sizeof(TGAHeader)) != sizeof(TGAHeader)) error = TGAERR_WRITE; /*----------------------------------------------------------------------- * WRITE THE COLORMAP (PALETTE) DATA SECTION *---------------------------------------------------------------------*/ if (!error && (flags & TGAF_PAL) && (mPalette != NULL) && (Header.CMapLength > 0)) { /* Adjust palette to the starting color entry. */ depth = (Header.CMapDepth >> 3); palette = mPalette + (Header.CMapStart * depth); size = (Header.CMapLength * depth); /* Allocate temporary buffer for palette manipulation. */ if ((temppal = (char *)malloc(size)) != NULL) { memcpy(temppal, palette, size); ptr = temppal; #if(0) /* Swap the byte ordering of the palette entries. */ for (i = 0; i < Header.CMapLength; i++) { c = *ptr; *ptr = *(ptr + (depth - 1)); *(ptr + (depth - 1)) = c; /* Next entry */ palette += depth; } #endif /* Write the palette. */ if (File_Write(temppal, size) != size) error = TGAERR_WRITE; /* Free temporary palette buffer. */ free(temppal); } else error = TGAERR_NOMEM; } /*----------------------------------------------------------------------- * WRITE THE IMAGE DATA SECTION *---------------------------------------------------------------------*/ if (!error && (flags & TGAF_IMAGE) && (mImage != NULL)) { bool imageinverted; /* Invert truecolor data. */ if ((Header.ImageType == TGA_TRUECOLOR) || (Header.ImageType == TGA_TRUECOLOR_ENCODED)) { InvertImage(); imageinverted = true; } else { imageinverted = false; } /* Write the image. */ if (flags & TGAF_COMPRESS) EncodeImage(); else { depth = TGA_BytesPerPixel(Header.PixelDepth); size = (((Header.Width * Header.Height)) * depth); if (File_Write(mImage, size) != size) error = TGAERR_WRITE; } // Bug fix (IML) : If the image was inverted, invert it again to restore it to its prior state. if (imageinverted) InvertImage(); } /*----------------------------------------------------------------------- * WRITE THE EXTENSION DATA SECTION *---------------------------------------------------------------------*/ // Mod (IML) Optionally add an extension to the file. if (addextension) { if (!error) { mExtension.ExtSize = 495; strncpy(mExtension.SoftID, "Denzil's Targa Code", 41); mExtension.SoftVer.Number = (1 * 100); mExtension.SoftVer.Letter = 0; /* Save position of extension area. */ if ((footer.Extension = File_Seek(0, SEEK_CUR)) == -1) error = TGAERR_WRITE; if (!error && (File_Write(&mExtension, sizeof(TGA2Extension)) != sizeof(TGA2Extension))) error = TGAERR_WRITE; } } else { footer.Extension = 0; } /*----------------------------------------------------------------------- * WRITE THE FOOTER DATA SECTION *---------------------------------------------------------------------*/ if (!error) { footer.Developer = 0; strncpy(footer.Signature, TGA2_SIGNATURE, 16); footer.RsvdChar = '.'; footer.BZST = 0; if (File_Write(&footer, sizeof(TGA2Footer)) != sizeof(TGA2Footer)) error = TGAERR_WRITE; } /* Close targa file. */ Close(); } else error = TGAERR_OPEN; return (error); } /**************************************************************************** * * NAME * Targa::XFlip - X flip the image. * * SYNOPSIS * XFlip() * * void XFlip(); * * FUNCTION * Flip the image in memory on its X axis. (left to right) * * INPUTS * NONE * * RESULT * NONE * ****************************************************************************/ void Targa::XFlip(void) { char *ptr,*ptr1; long x,y,d; char v,v1; char depth; /* Pixel depth in bytes. */ depth = TGA_BytesPerPixel(Header.PixelDepth); for (y = 0; y < Header.Height; y++) { ptr = (mImage + ((Header.Width * depth) * y)); ptr1 = (ptr + ((Header.Width * depth) - depth)); for (x = 0; x < (Header.Width / 2); x++) { for (d = 0; d < depth; d++) { v = *(ptr + d); v1 = *(ptr1 + d); *(ptr + d) = v1; *(ptr1 + d) = v; } ptr += depth; ptr1 -= depth; } } } /**************************************************************************** * * NAME * Targa::YFlip - Y flip the image. * * SYNOPSIS * YFlip() * * void YFlip(); * * FUNCTION * Flip the image in memory on its Y axis. (top to bottom) * * INPUTS * NONE * * RESULT * NONE * ****************************************************************************/ void Targa::YFlip(void) { char *ptr,*ptr1; long x,y; char v,v1; char depth; /* Pixel depth in bytes. */ depth = TGA_BytesPerPixel(Header.PixelDepth); for (y = 0; y < (Header.Height >> 1); y++) { /* Compute address of lines to exchange. */ ptr = (mImage + ((Header.Width * y) * depth)); ptr1 = (mImage + ((Header.Width * (Header.Height - 1)) * depth)); ptr1 -= ((Header.Width * y) * depth); /* Exchange all the pixels on this scan line. */ for (x = 0; x < (Header.Width * depth); x++) { v = *ptr; v1 = *ptr1; *ptr = v1; *ptr1 = v; ptr++; ptr1++; } } } /**************************************************************************** * * NAME * Targa::SetImage - Set the image buffer. * * SYNOPSIS * OldImage = SetImage(Image) * * char *SetImage(char *); * * FUNCTION * Set the image buffer to one provided by the caller. * * INPUTS * Image - Pointer to buffer to use for the image buffer. * * RESULT * OldImage - Previous caller assigned image buffer. * ****************************************************************************/ char *Targa::SetImage(char *buffer) { char *oldbuffer = NULL; /* Free any image buffer before assigning another. */ if ((mImage != NULL) && (mFlags & TGAF_IMAGE)) { free(mImage); mImage = NULL; mFlags &= ~TGAF_IMAGE; } /* Get the old user buffer. */ if (mImage != NULL) oldbuffer = mImage; /* Assign the new image buffer. */ mImage = buffer; return (oldbuffer); } /**************************************************************************** * * NAME * Targa::SetPalette - Set the palette buffer. * * SYNOPSIS * OldPal = SetPalette(Pal) * * char *SetPalette(char *); * * FUNCTION * * INPUTS * Pal - Pointer to buffer to use for palette. * * RESULT * OldPal - Pointer to previous user palette. * ****************************************************************************/ char *Targa::SetPalette(char *buffer) { char *oldbuffer = NULL; /* Free any image buffer before assigning another. */ if ((mPalette != NULL) && (mFlags & TGAF_PAL)) { free(mPalette); mPalette = NULL; mFlags &= ~TGAF_PAL; } /* Get the old user buffer. */ if (mPalette != NULL) oldbuffer = mPalette; /* Assign the new image buffer. */ mPalette = buffer; return (oldbuffer); } bool Targa::IsCompressed(void) { if (Header.ImageType > 8) return true; return false; } /**************************************************************************** * * NAME * Targa::GetExtension - Get Extension data. (Targa 2.0 files only) * * SYNOPSIS * Ext = GetExtension() * * TGA2Extension *GetExtension(void); * * FUNCTION * Retrieve a pointer to the Targa 2.0 extension data area. If the file * version is 1.0 OR there is no extensio area then a NULL will be returned. * * INPUTS * NONE * * RESULT * Ext - Pointer to Extension data, NULL if not available. * ****************************************************************************/ TGA2Extension *Targa::GetExtension(void) { if (mFlags & TGAF_TGA2) return (&mExtension); return (NULL); } /**************************************************************************** * * NAME * Targa::DecodeImage - Decompress Targa image data. * * SYNOPSIS * Error = DecodeImage() * * long DecodeImage(); * * FUNCTION * Decode the RLE compressed image data into the specified buffer from * the file I/O stream. * * INPUTS * NONE * * RESULT * Error - 0 if successful, or TGAERR_??? error code. * ****************************************************************************/ long Targa::DecodeImage() { char *image; char *color; unsigned char count; unsigned char depth; unsigned long pixel_count; unsigned long size; unsigned long c,i; long error = 0; /* Initialize */ image = mImage; /* Compute pixel depth in bytes. */ depth = TGA_BytesPerPixel(Header.PixelDepth); /* Total number of pixels compressed in this image. */ pixel_count = (Header.Width * Header.Height); while ((pixel_count > 0) && !error) { /* Read count. */ if (File_Read(&count, 1) == 1) { /* If bit 8 of the count is set then we have a run of pixels, * otherwise the data is raw pixels. */ if (count & 0x80) { count &= 0x7F; count++; /* Read in run pixel. */ if (File_Read(image, depth) == depth) { color = image; image += depth; /* Repeat the pixel for the run count in the image buffer. */ for (c = 1; c < count; c++) for (i = 0; i < depth; i++) *image++ = *(color + i); } else error = TGAERR_READ; } else { count++; size = (count * depth); /* Read in raw pixels. */ if ((unsigned)File_Read(image, size) == size) image += size; else error = TGAERR_READ; } /* Adjust the pixel count. */ pixel_count -= count; } else error = TGAERR_READ; } return (error); } /**************************************************************************** * * NAME * Targa::EncodeImage - Compress the image using targa RLE. * * SYNOPSIS * EncodeImage() * * void EncodeImage(void); * * FUNCTION * Encode the image data using the RLE algorithm outlined in the TARGA * file specification. * * INPUTS * NONE * * RESULT * NONE * ****************************************************************************/ long Targa::EncodeImage() { char *packet; long packet_index; char *start; char *end; long depth; long pixels; long count; long match; long i; long error = 0; /* Initialize variables. */ depth = TGA_BytesPerPixel(Header.PixelDepth); /* Allocate packet buffer to hold maximum encoded data run. */ if ((packet = (char *)malloc(128 * depth)) != NULL) { pixels = Header.Width * Header.Height; start = mImage; end = start; count = 0; packet[0] = 0; packet_index = 1; while ((pixels != 0) && !error) { match = 1; /* Advance to the next pixel */ end += depth; pixels--; /* Compare pixels. */ for (i = 0; i < depth; i++) { if (start[i] != end[i]) { match = 0; break; } } /* Run of pixels */ if (match == 1) { count++; /* Continue counting until the maximum has been reached. */ if (count < 128) { if (packet[0] == 0) continue; } else count--; } /* If there is a count then write out the run. Otherwise, write * the raw pixel to the packet. */ if ((count != 0) && (packet[0] == 0)) { /* Run count */ packet[0] = (count | 0x80); /* Run pixel */ for (i = 0; i < depth; i++) packet[i + 1] = start[i]; /* Write the run packet. */ if (File_Write(packet, (depth + 1)) != (depth + 1)) error = TGAERR_WRITE; /* Reposition start and reset. */ start = end; count = 0; packet[0] = 0; } else { if (count == 0) { /* Copy the raw pixel to the packet. */ for (i = 0; i < depth; i++) packet[packet_index + i] = start[i]; /* Increment the raw packet count. */ packet[0]++; /* Reposition start */ start = end; packet_index += depth; } /* Write the raw packet if the packet is full or a run has started * or all the pixels have been processed. */ if ((packet[0] == 127) || (count != 0) || (pixels == 0)) { i = packet[0]; packet[0]--; if (File_Write(packet, ((i * depth) + 1)) != ((i * depth) + 1)) error = TGAERR_WRITE; packet_index = 1; packet[0] = 0; } } } /* Free the packet buffer. */ free(packet); } else error = TGAERR_NOMEM; return (error); } /**************************************************************************** * * NAME * Targa::InvertImage - Invert TrueColor image data. * * SYNOPSIS * InvertImage() * * void InvertImage(void); * * FUNCTION * * INPUTS * NONE * * RESULT * NONE * ****************************************************************************/ void Targa::InvertImage(void) { char *buffer; long depth; long pixel_count; long i; char c; /* Initialize */ buffer = mImage; /* Compute the pixel depth in bytes. */ depth = TGA_BytesPerPixel(Header.PixelDepth); /* Total number of pixels in this image. */ pixel_count = (Header.Width * Header.Height); /* 16-bit pixel layout is different that 24-bit and 32-bit. */ if (depth > 2) { while (pixel_count > 0) { for (i = 0; i < (depth / 2); i++) { c = *(buffer + i); *(buffer + i) = *(buffer + ((depth - 1) - i)); *(buffer + ((depth - 1) - i)) = c; } /* Next pixel */ pixel_count--; buffer += depth; } } } /* ** These functions are just for ease of ifdef'ing between standard io calls and FileClass. */ void Targa::Clear_File(void) { #ifdef TGA_USES_WWLIB_FILE_CLASSES TGAFile = NULL; #else mFH = -1; #endif } bool Targa::Is_File_Open(void) { #ifdef TGA_USES_WWLIB_FILE_CLASSES return (TGAFile != NULL); #else return (mFH != -1); #endif } bool Targa::File_Open_Read(const char* name) { #ifdef TGA_USES_WWLIB_FILE_CLASSES TGAFile = _TheFileFactory->Get_File(name); if (TGAFile && TGAFile->Is_Available()) { return (TGAFile->Open(FileClass::READ) != 0); } else { return false; } #else mFH = open(name, (O_RDONLY|O_BINARY)); return (mFH != -1); #endif } bool Targa::File_Open_Write(const char* name) { #ifdef TGA_USES_WWLIB_FILE_CLASSES TGAFile = _TheWritingFileFactory->Get_File(name); if (TGAFile) { return (TGAFile->Open(FileClass::WRITE) != 0); } else { return false; } #else mFH = open(name, (O_CREAT|O_TRUNC|O_WRONLY|O_BINARY), (S_IREAD|S_IWRITE)); return (mFH != -1); #endif } bool Targa::File_Open_ReadWrite(const char* name) { #ifdef TGA_USES_WWLIB_FILE_CLASSES TGAFile = _TheWritingFileFactory->Get_File(name); if (TGAFile && TGAFile->Is_Available()) { return (TGAFile->Open(FileClass::READ|FileClass::WRITE) != 0); } else { return false; } #else mFH = open(name, (O_RDWR|O_BINARY), (S_IREAD|S_IWRITE)); return (mFH != -1); #endif } int Targa::File_Seek(int pos, int dir) { #ifdef TGA_USES_WWLIB_FILE_CLASSES return TGAFile->Seek(pos, dir); #else return lseek(mFH, pos, dir); #endif } int Targa::File_Read(void *buffer, int size) { #ifdef TGA_USES_WWLIB_FILE_CLASSES return TGAFile->Read(buffer, size); #else return read(mFH, buffer, size); #endif } int Targa::File_Write(void *buffer, int size) { #ifdef TGA_USES_WWLIB_FILE_CLASSES return TGAFile->Write(buffer, size); #else return write(mFH, buffer, size); #endif } // ---------------------------------------------------------------------------- // // Output targa load error message. // // ---------------------------------------------------------------------------- long Targa_Error_Handler(long load_err,const char* filename) { switch (load_err) { case 0: return 0; case TGAERR_OPEN: WWDEBUG_SAY(("Targa: Failed to open file \"%s\"\n", filename)); break; case TGAERR_READ: WWDEBUG_SAY(("Targa: Failed to read file \"%s\"\n", filename)); break; case TGAERR_NOTSUPPORTED: WWDEBUG_SAY(("Targa: File \"%s\" is an unsupported Targa type\n", filename)); break; case TGAERR_NOMEM: WWDEBUG_SAY(("Targa: Failed to allocate memory for file \"%s\"\n", filename)); break; default: WWDEBUG_SAY(("Targa: Unknown error when loading file \"%s\"\n", filename)); break; } return load_err; }