When writing the X11 (linux) implementation there was a problem with X11 defining a "Display" type and we also have a Display class in the engine. So to fix that problem and minimize the risk for running into other name conflicts. We move everything from global namespace.
213 lines
No EOL
4.1 KiB
C++
213 lines
No EOL
4.1 KiB
C++
|
|
#include <cstring>
|
|
#include <Spectre/System/Log.h>
|
|
#include <Spectre/Graphics/Image.h>
|
|
#include "ImageLoader.h"
|
|
|
|
namespace sp {
|
|
|
|
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);
|
|
memcpy(&m_pixels[0], pixels, m_pixels.size());
|
|
}
|
|
|
|
const unsigned char* Image::getPixels() const
|
|
{
|
|
if (m_pixels.size()) {
|
|
return &m_pixels[0];
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
} // namespace sp
|