208 lines
4.1 KiB
C++
208 lines
4.1 KiB
C++
|
|
#include "ImageLoader.h"
|
|
#include <Spectre/System/Log.h>
|
|
#include <Spectre/Graphics/Image.h>
|
|
|
|
static ImageLoader _loader;
|
|
|
|
Image::Image() :
|
|
m_size (0, 0),
|
|
m_format (PF_Unknown)
|
|
{
|
|
}
|
|
|
|
void Image::create(unsigned width, unsigned height, const Color& color)
|
|
{
|
|
m_size.x = width;
|
|
m_size.y = height;
|
|
m_format = PixelFormat::PF_RGBA;
|
|
|
|
m_pixels.resize(m_size.x * m_size.y * (getBpp() / 8));
|
|
|
|
for(size_t i = 0; i < m_pixels.size(); i += 4) {
|
|
|
|
m_pixels[i+0] = color.r;
|
|
m_pixels[i+1] = color.g;
|
|
m_pixels[i+2] = color.b;
|
|
m_pixels[i+3] = color.a;
|
|
}
|
|
}
|
|
|
|
void Image::create(unsigned width, unsigned height, const void* pixels)
|
|
{
|
|
create(PixelFormat::PF_RGBA, width, height, pixels);
|
|
}
|
|
|
|
void Image::create(PixelFormat format, unsigned width, unsigned height, const Color& color)
|
|
{
|
|
m_size.x = width;
|
|
m_size.y = height;
|
|
m_format = format;
|
|
|
|
m_pixels.resize(m_size.x * m_size.y * (getBpp() / 8));
|
|
|
|
if (getBpp() == 32) {
|
|
for(size_t i = 0; i < m_pixels.size(); i += 4) {
|
|
|
|
m_pixels[i+0] = color.r;
|
|
m_pixels[i+1] = color.g;
|
|
m_pixels[i+2] = color.b;
|
|
m_pixels[i+3] = color.a;
|
|
}
|
|
} else if (getBpp() == 24) {
|
|
for(size_t i = 0; i < m_pixels.size(); i += 3) {
|
|
|
|
m_pixels[i+0] = color.r;
|
|
m_pixels[i+1] = color.g;
|
|
m_pixels[i+2] = color.b;
|
|
}
|
|
} else {
|
|
for(size_t i = 0; i < m_pixels.size(); i += 1) {
|
|
m_pixels[i] = color.a;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Image::create(PixelFormat format, unsigned width, unsigned height, const void* pixels)
|
|
{
|
|
m_size.x = width;
|
|
m_size.y = height;
|
|
m_format = format;
|
|
|
|
setPixels(pixels);
|
|
}
|
|
|
|
const Vector2u& Image::getSize() const
|
|
{
|
|
return m_size;
|
|
}
|
|
|
|
unsigned int Image::getWidth() const
|
|
{
|
|
return m_size.x;
|
|
}
|
|
|
|
unsigned int Image::getHeight() const
|
|
{
|
|
return m_size.y;
|
|
}
|
|
|
|
unsigned int Image::getBpp() const
|
|
{
|
|
switch(m_format) {
|
|
case PixelFormat::PF_RGBA : return 32;
|
|
case PixelFormat::PF_RGB : return 24;
|
|
case PixelFormat::PF_Alpha : return 8;
|
|
case PixelFormat::PF_Unknown :
|
|
default : break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
unsigned int Image::getStride() const
|
|
{
|
|
return m_size.x * (getBpp() / 8);
|
|
}
|
|
|
|
PixelFormat Image::getFormat() const
|
|
{
|
|
return m_format;
|
|
}
|
|
|
|
bool Image::hasAlpha() const
|
|
{
|
|
return m_format == PixelFormat::PF_RGBA || m_format == PixelFormat::PF_Alpha;
|
|
}
|
|
|
|
bool Image::loadFromFile(const std::string& filename)
|
|
{
|
|
m_pixels.clear();
|
|
|
|
return _loader.loadFromFile(filename.c_str(), *this);
|
|
}
|
|
|
|
bool Image::loadFromMemory(const void *data, unsigned int size)
|
|
{
|
|
m_pixels.clear();
|
|
|
|
return _loader.loadFromMemory(data, size, *this);
|
|
}
|
|
|
|
void Image::saveToFile(const std::string& filename) const
|
|
{
|
|
_loader.saveToFile(*this, filename.c_str());
|
|
}
|
|
|
|
void Image::setPixel(unsigned x, unsigned y, const Color& c)
|
|
{
|
|
unsigned char *base = m_pixels.data() + ((getBpp() / 8) * ((y * m_size.x) + x));
|
|
|
|
if (m_format == PixelFormat::PF_RGB || m_format == PixelFormat::PF_RGBA) {
|
|
base[0] = c.r;
|
|
base[1] = c.g;
|
|
base[2] = c.b;
|
|
if (m_format == PixelFormat::PF_RGBA) {
|
|
base[3] = c.a;
|
|
}
|
|
}
|
|
else if (m_format == PixelFormat::PF_Alpha) {
|
|
base[0] = c.a;
|
|
}
|
|
}
|
|
|
|
Color Image::getPixel(unsigned x, unsigned y) const
|
|
{
|
|
Color c;
|
|
const unsigned char *base = m_pixels.data() + ((getBpp() / 8) * ((y * m_size.x) + x));
|
|
|
|
// RGB / RGBA formats.
|
|
if (m_format == PixelFormat::PF_RGB || m_format == PixelFormat::PF_RGBA) {
|
|
c.r = base[0];
|
|
c.g = base[1];
|
|
c.b = base[2];
|
|
if (m_format == PixelFormat::PF_RGBA) {
|
|
c.a = base[3];
|
|
} else {
|
|
c.a = 255;
|
|
}
|
|
}
|
|
// Alpha, single channel format.
|
|
else if (m_format == PixelFormat::PF_Alpha) {
|
|
c = Color(0, 0, 0, base[0]);
|
|
}
|
|
return c;
|
|
}
|
|
|
|
void Image::flipY()
|
|
{
|
|
unsigned int stride = getStride();
|
|
|
|
// The quick and dirty way :)
|
|
for(size_t y = 0; y < m_size.y / 2; y++) {
|
|
|
|
int row0 = y * stride;
|
|
int row1 = (m_size.y - y - 1) * stride;
|
|
|
|
for(size_t x = 0; x < stride; x++) {
|
|
unsigned char tmp = m_pixels[row0 + x];
|
|
m_pixels[row0 + x] = m_pixels[row1 + x];
|
|
m_pixels[row1 + x] = tmp;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Image::setPixels(const void *pixels)
|
|
{
|
|
unsigned int size = m_size.y * getStride();
|
|
|
|
m_pixels.resize(size);
|
|
std::memcpy(&m_pixels[0], pixels, m_pixels.size());
|
|
}
|
|
|
|
const unsigned char* Image::getPixels() const
|
|
{
|
|
if (m_pixels.size()) {
|
|
return &m_pixels[0];
|
|
}
|
|
return NULL;
|
|
}
|