mirror of
https://github.com/yuzu-emu/FasTC.git
synced 2024-12-01 08:24:25 +01:00
287 lines
7.6 KiB
C++
287 lines
7.6 KiB
C++
/* FasTC
|
|
* Copyright (c) 2012 University of North Carolina at Chapel Hill. All rights reserved.
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software and its documentation for educational,
|
|
* research, and non-profit purposes, without fee, and without a written agreement is hereby granted,
|
|
* provided that the above copyright notice, this paragraph, and the following four paragraphs appear
|
|
* in all copies.
|
|
*
|
|
* Permission to incorporate this software into commercial products may be obtained by contacting the
|
|
* authors or the Office of Technology Development at the University of North Carolina at Chapel Hill <otd@unc.edu>.
|
|
*
|
|
* This software program and documentation are copyrighted by the University of North Carolina at Chapel Hill.
|
|
* The software program and documentation are supplied "as is," without any accompanying services from the
|
|
* University of North Carolina at Chapel Hill or the authors. The University of North Carolina at Chapel Hill
|
|
* and the authors do not warrant that the operation of the program will be uninterrupted or error-free. The
|
|
* end-user understands that the program was developed for research purposes and is advised not to rely
|
|
* exclusively on the program for any reason.
|
|
*
|
|
* IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE AUTHORS BE LIABLE TO ANY PARTY FOR
|
|
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE
|
|
* USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE
|
|
* AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
|
|
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY
|
|
* STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY
|
|
* OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
|
|
* ENHANCEMENTS, OR MODIFICATIONS.
|
|
*
|
|
* Please send all BUG REPORTS to <pavel@cs.unc.edu>.
|
|
*
|
|
* The authors may be contacted via:
|
|
*
|
|
* Pavel Krajcevski
|
|
* Dept of Computer Science
|
|
* 201 S Columbia St
|
|
* Frederick P. Brooks, Jr. Computer Science Bldg
|
|
* Chapel Hill, NC 27599-3175
|
|
* USA
|
|
*
|
|
* <http://gamma.cs.unc.edu/FasTC/>
|
|
*/
|
|
|
|
#include "ImageFile.h"
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <limits.h>
|
|
#include <assert.h>
|
|
#include <algorithm>
|
|
|
|
#include "ImageWriter.h"
|
|
#include "ImageLoader.h"
|
|
#include "CompressedImage.h"
|
|
#include "Image.h"
|
|
#include "FileStream.h"
|
|
|
|
#ifdef PNG_FOUND
|
|
# include "ImageLoaderPNG.h"
|
|
# include "ImageWriterPNG.h"
|
|
#endif
|
|
|
|
#ifdef PVRTEXLIB_FOUND
|
|
# include "ImageLoaderPVR.h"
|
|
#endif
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Static helper functions
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static inline void ReportError(const CHAR *msg) {
|
|
fprintf(stderr, "ImageFile -- %s\n", msg);
|
|
}
|
|
|
|
template <typename T>
|
|
static inline T abs(const T &a) {
|
|
return a > 0? a : -a;
|
|
}
|
|
|
|
//!HACK!
|
|
#ifdef _MSC_VER
|
|
#define strncpy strncpy_s
|
|
#endif
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ImageFile implementation
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
ImageFile::ImageFile(const CHAR *filename)
|
|
: m_FileFormat( DetectFileFormat(filename) )
|
|
, m_Image(NULL)
|
|
{
|
|
strncpy(m_Filename, filename, kMaxFilenameSz);
|
|
}
|
|
|
|
ImageFile::ImageFile(const CHAR *filename, EImageFileFormat format)
|
|
: m_FileFormat(format)
|
|
, m_Image(NULL)
|
|
{
|
|
strncpy(m_Filename, filename, kMaxFilenameSz);
|
|
}
|
|
|
|
ImageFile::ImageFile(const char *filename, EImageFileFormat format, const Image &image)
|
|
: m_FileFormat(format)
|
|
, m_Image(new Image(image))
|
|
{
|
|
strncpy(m_Filename, filename, kMaxFilenameSz);
|
|
}
|
|
|
|
ImageFile::~ImageFile() {
|
|
if(m_Image) {
|
|
delete m_Image;
|
|
m_Image = NULL;
|
|
}
|
|
}
|
|
|
|
bool ImageFile::Load() {
|
|
|
|
if(m_Image) {
|
|
delete m_Image;
|
|
m_Image = NULL;
|
|
}
|
|
|
|
unsigned char *rawData = ReadFileData(m_Filename);
|
|
if(rawData) {
|
|
m_Image = LoadImage(rawData);
|
|
delete [] rawData;
|
|
}
|
|
|
|
return m_Image != NULL;
|
|
}
|
|
|
|
bool ImageFile::Write() {
|
|
|
|
ImageWriter *writer = NULL;
|
|
switch(m_FileFormat) {
|
|
|
|
#ifdef PNG_FOUND
|
|
case eFileFormat_PNG:
|
|
writer = new ImageWriterPNG(*m_Image);
|
|
break;
|
|
#endif // PNG_FOUND
|
|
|
|
default:
|
|
fprintf(stderr, "Unable to write image: unknown file format.\n");
|
|
return false;
|
|
}
|
|
|
|
if(NULL == writer)
|
|
return false;
|
|
|
|
if(!writer->WriteImage()) {
|
|
delete writer;
|
|
return false;
|
|
}
|
|
|
|
WriteImageDataToFile(writer->GetRawFileData(), uint32(writer->GetRawFileDataSz()), m_Filename);
|
|
|
|
delete writer;
|
|
return true;
|
|
}
|
|
|
|
Image *ImageFile::LoadImage(const unsigned char *rawImageData) const {
|
|
|
|
ImageLoader *loader = NULL;
|
|
switch(m_FileFormat) {
|
|
|
|
#ifdef PNG_FOUND
|
|
case eFileFormat_PNG:
|
|
loader = new ImageLoaderPNG(rawImageData);
|
|
break;
|
|
#endif // PNG_FOUND
|
|
|
|
#ifdef PVRTEXLIB_FOUND
|
|
case eFileFormat_PVR:
|
|
loader = new ImageLoaderPVR(rawImageData);
|
|
break;
|
|
#endif // PVRTEXLIB_FOUND
|
|
|
|
default:
|
|
fprintf(stderr, "Unable to load image: unknown file format.\n");
|
|
return NULL;
|
|
}
|
|
|
|
if(!loader)
|
|
return NULL;
|
|
|
|
if(!(loader->LoadImage())) {
|
|
fprintf(stderr, "Unable to load image!\n");
|
|
delete loader;
|
|
return NULL;
|
|
}
|
|
|
|
Image *i = new Image(*loader);
|
|
delete loader;
|
|
|
|
return i;
|
|
}
|
|
|
|
EImageFileFormat ImageFile::DetectFileFormat(const CHAR *filename) {
|
|
|
|
size_t len = strlen(filename);
|
|
if(len >= 256) {
|
|
// !FIXME! Report Error...
|
|
return kNumImageFileFormats;
|
|
}
|
|
|
|
size_t dotPos = len - 1;
|
|
|
|
while((dotPos >= len)? false : filename[dotPos--] != '.');
|
|
if (dotPos >= len) {
|
|
return kNumImageFileFormats;
|
|
}
|
|
|
|
// consume the last character...
|
|
dotPos++;
|
|
|
|
const CHAR *ext = &filename[dotPos];
|
|
|
|
if(strcmp(ext, ".png") == 0) {
|
|
return eFileFormat_PNG;
|
|
}
|
|
else if(strcmp(ext, ".pvr") == 0) {
|
|
return eFileFormat_PVR;
|
|
}
|
|
|
|
return kNumImageFileFormats;
|
|
}
|
|
|
|
unsigned char *ImageFile::ReadFileData(const CHAR *filename) {
|
|
FileStream fstr (filename, eFileMode_ReadBinary);
|
|
if(fstr.Tell() < 0) {
|
|
fprintf(stderr, "Error opening file for reading: %s\n", filename);
|
|
return 0;
|
|
}
|
|
|
|
// Figure out the filesize.
|
|
fstr.Seek(0, FileStream::eSeekPosition_End);
|
|
uint32 fileSize = fstr.Tell();
|
|
|
|
// Allocate data for file contents
|
|
unsigned char *rawData = new unsigned char[fileSize];
|
|
|
|
// Return stream to beginning of file
|
|
fstr.Seek(0, FileStream::eSeekPosition_Beginning);
|
|
assert(fstr.Tell() == 0);
|
|
|
|
// Read all of the data
|
|
uint64 totalBytesRead = 0;
|
|
uint64 totalBytesLeft = fileSize;
|
|
int32 bytesRead;
|
|
while((bytesRead = fstr.Read(rawData, uint32(fileSize))) > 0) {
|
|
totalBytesRead += bytesRead;
|
|
totalBytesLeft -= bytesRead;
|
|
}
|
|
|
|
if(totalBytesRead != fileSize) {
|
|
assert(!"We didn't read as much data as we thought we had!");
|
|
fprintf(stderr, "Internal error: Incorrect file size assumption\n");
|
|
return 0;
|
|
}
|
|
|
|
// Return the data..
|
|
return rawData;
|
|
}
|
|
|
|
bool ImageFile::WriteImageDataToFile(const uint8 *data,
|
|
const uint32 dataSz,
|
|
const CHAR *filename) {
|
|
|
|
// Open a file stream and write out the data...
|
|
FileStream fstr (filename, eFileMode_WriteBinary);
|
|
if(fstr.Tell() < 0) {
|
|
fprintf(stderr, "Error opening file for reading: %s\n", filename);
|
|
return 0;
|
|
}
|
|
|
|
fstr.Write(data, dataSz);
|
|
fstr.Flush();
|
|
return true;
|
|
}
|