bgfx/3rdparty/openctm/tools/image.cpp
2012-10-07 20:41:18 -07:00

134 lines
4 KiB
C++

//-----------------------------------------------------------------------------
// Product: OpenCTM tools
// File: image.cpp
// Description: Implementation of the Image class.
//-----------------------------------------------------------------------------
// Copyright (c) 2009-2010 Marcus Geelnard
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//-----------------------------------------------------------------------------
#include <stdexcept>
#include <cstdio>
#include <jpeglib.h>
#include <pnglite.h>
#include "image.h"
#include "common.h"
using namespace std;
/// Flip the image vertically.
void Image::FlipVertically()
{
if((mWidth <= 0) || (mHeight <= 0))
return;
for(int y = 0; y < mHeight / 2; ++ y)
{
for(int x = 0; x < mWidth; ++ x)
{
for(int k = 0; k < mComponents; ++ k)
{
unsigned char tmp = mData[(y * mWidth + x) * mComponents + k];
mData[(y * mWidth + x) * mComponents + k] = mData[((mHeight - 1 - y) * mWidth + x) * mComponents + k];
mData[((mHeight - 1 - y) * mWidth + x) * mComponents + k] = tmp;
}
}
}
}
/// Load image from a JPEG file.
void Image::LoadJPEG(const char * aFileName)
{
FILE * inFile = fopen(aFileName, "rb");
if(inFile != NULL)
{
// Init libjpeg resources
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, inFile);
// Read JPEG header
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
SetSize(cinfo.output_width, cinfo.output_height, cinfo.output_components);
// Read pixel data
for(int i = 0; i < mHeight; ++ i)
{
unsigned char * scanLines[1];
scanLines[0] = &mData[(mHeight - 1 - i) * mWidth * mComponents];
jpeg_read_scanlines(&cinfo, scanLines, 1);
}
// Finalize libjpeg resources
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
// Close input file
fclose(inFile);
}
}
/// Load image from a PNG file.
void Image::LoadPNG(const char * aFileName)
{
bool success = false;
png_t p;
png_init(0, 0);
if(png_open_file(&p, aFileName) == PNG_NO_ERROR)
{
if((p.depth == 8) && ((p.color_type == PNG_GREYSCALE) ||
(p.color_type == PNG_TRUECOLOR) ||
(p.color_type == PNG_TRUECOLOR_ALPHA)) && (p.width > 0) &&
(p.height > 0) && (p.bpp >= 1) && (p.bpp <= 4))
{
SetSize(p.width, p.height, p.bpp);
if(png_get_data(&p, &mData[0]) == PNG_NO_ERROR)
{
FlipVertically();
success = true;
}
}
png_close_file(&p);
}
// Did we have an error?
if(!success)
{
Clear();
throw runtime_error("Unable to load PNG file.");
}
}
/// Load an image from a file (any supported format).
void Image::LoadFromFile(const char * aFileName)
{
string fileExt = UpperCase(ExtractFileExt(string(aFileName)));
if((fileExt == string(".JPG")) || (fileExt == string(".JPEG")))
LoadJPEG(aFileName);
else if(fileExt == string(".PNG"))
LoadPNG(aFileName);
else
throw runtime_error("Unknown input file extension.");
}