Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
382 lines (294 sloc) 9.33 KB
////////////////////////////////////////////////////////////////////////////////
// -------------------------------------------------------------------------- //
// //
// (C) 2010-2016 Robot Developers //
// See LICENSE for licensing info //
// //
// -------------------------------------------------------------------------- //
////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------//
// Prefaces //
//----------------------------------------------------------------------------//
#include "Image.h"
#include "Color.h"
#include "Size.h"
#include "Point.h"
#include <cstring>
using std::memcpy;
using std::memcmp;
ROBOT_NS_BEGIN
//----------------------------------------------------------------------------//
// Macros //
//----------------------------------------------------------------------------//
////////////////////////////////////////////////////////////////////////////////
#define RESET( target ) \
(target).mWidth = 0; \
(target).mHeight = 0; \
(target).mLength = 0; \
(target).mData = nullptr; \
(target).mLimit = 0;
//----------------------------------------------------------------------------//
// Constructors Image //
//----------------------------------------------------------------------------//
////////////////////////////////////////////////////////////////////////////////
Image::Image (void)
{
RESET (*this);
}
////////////////////////////////////////////////////////////////////////////////
Image::~Image (void)
{
Destroy();
}
////////////////////////////////////////////////////////////////////////////////
Image::Image (const Image& image)
{
RESET (*this);
Create (image.mWidth, image.mHeight);
if (mLength != 0) memcpy (mData, image.
mData, mLength * sizeof (uint32));
}
////////////////////////////////////////////////////////////////////////////////
Image::Image (Image&& image)
{
mWidth = image.mWidth;
mHeight = image.mHeight;
mLength = image.mLength;
mData = image.mData;
mLimit = image.mLimit;
RESET (image);
}
////////////////////////////////////////////////////////////////////////////////
Image::Image (const Size& size)
{
RESET (*this);
Create (size);
}
////////////////////////////////////////////////////////////////////////////////
Image::Image (uint16 w, uint16 h)
{
RESET (*this);
Create (w, h);
}
//----------------------------------------------------------------------------//
// Functions Image //
//----------------------------------------------------------------------------//
////////////////////////////////////////////////////////////////////////////////
bool Image::IsValid (void) const
{
return mData != nullptr;
}
////////////////////////////////////////////////////////////////////////////////
bool Image::Create (const Size& size)
{
return Create (size.W, size.H);
}
////////////////////////////////////////////////////////////////////////////////
bool Image::Create (uint16 w, uint16 h)
{
// Verify dimensions
if (w == 0 || h == 0)
return false;
mWidth = w;
mHeight = h;
mLength = (uint32) w * h;
// Can we reuse memory
if (mLimit < mLength)
{
if (mData != nullptr)
delete[] mData;
// Allocate memory
mData = new uint32
[mLimit = mLength];
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
void Image::Destroy (void)
{
if (mData != nullptr)
delete[] mData;
RESET (*this);
}
////////////////////////////////////////////////////////////////////////////////
Color Image::GetPixel (const Point& point) const
{
return GetPixel (point.X, point.Y);
}
////////////////////////////////////////////////////////////////////////////////
Color Image::GetPixel (uint16 x, uint16 y) const
{
// Perform simple boundary check
if (x >= mWidth || y >= mHeight)
return Color();
// Return color at the specified coordinate
return ((Color*) mData) [x + (y * mWidth)];
}
////////////////////////////////////////////////////////////////////////////////
void Image::SetPixel (const Point& point, Color c)
{
return SetPixel (point.X, point.Y, c);
}
////////////////////////////////////////////////////////////////////////////////
void Image::SetPixel (uint16 x, uint16 y, Color c)
{
// Perform simple boundary check
if (x >= mWidth || y >= mHeight)
return;
// Set color at the specified coordinate
((Color*) mData) [x + (y * mWidth)] = c;
}
////////////////////////////////////////////////////////////////////////////////
bool Image::Fill (const Color& color)
{
// Check the validity of this image
if (mData == nullptr) return false;
// Loop data and fill contents
uint32 argb = color.GetARGB();
for (uint32 i = 0; i < mLength; ++i)
mData[i] = argb;
return true;
}
////////////////////////////////////////////////////////////////////////////////
bool Image::Fill (uint8 r, uint8 g, uint8 b, uint8 a)
{
return Fill (Color (r, g, b, a));
}
////////////////////////////////////////////////////////////////////////////////
bool Image::Swap (const char* sw)
{
// Verify parameters
if (mData == nullptr ||
sw == nullptr)
return false;
int8 a = -1; int8 r = -1;
int8 g = -1; int8 b = -1;
int8 count;
// Parse and validate the switch parameter
for (count = 0; sw[count] != '\0'; ++count)
{
char c = sw[count] | 32; // Lower case
if (c == 'a' && a == -1) a = (3-count) << 3;
else if (c == 'r' && r == -1) r = (3-count) << 3;
else if (c == 'g' && g == -1) g = (3-count) << 3;
else if (c == 'b' && b == -1) b = (3-count) << 3;
else return false;
}
// Check for missing channels
if (count != 4) return false;
Color* data = (Color*) mData;
// Loop data and perform the switch
for (uint32 i = 0; i < mLength; ++i)
{
mData[i] = (data[i].A << a) |
(data[i].R << r) |
(data[i].G << g) |
(data[i].B << b);
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
bool Image::Flip (bool h, bool v)
{
// Check the validity of this image
if (mData == nullptr) return false;
if ( h && v) Flip ();
if ( h && !v) FlipH();
if (!h && v) FlipV();
return true;
}
//----------------------------------------------------------------------------//
// Internal Image //
//----------------------------------------------------------------------------//
////////////////////////////////////////////////////////////////////////////////
void Image::Flip (void)
{
uint32 length = mLength / 2;
// Loop data and perform mirroring
for (uint32 i = 0; i < length; ++i)
{
uint32 f = mLength - 1 - i;
uint32 c = mData[i];
mData[i] = mData[f];
mData[f] = c;
}
}
////////////////////////////////////////////////////////////////////////////////
void Image::FlipH (void)
{
uint16 width = mWidth / 2;
// Loop data and perform mirroring
for (uint32 y = 0; y < mHeight; ++y)
{
for (uint32 x = 0; x < width; ++x)
{
uint32 f = mWidth - 1 - x;
uint32 a = mData[x + (y * mWidth)];
uint32 b = mData[f + (y * mWidth)];
mData[x + (y * mWidth)] = b;
mData[f + (y * mWidth)] = a;
}
}
}
////////////////////////////////////////////////////////////////////////////////
void Image::FlipV (void)
{
uint16 height = mHeight / 2;
// Loop data and perform the mirror
for (uint32 y = 0; y < height; ++y)
{
uint32 f = mHeight - 1 - y;
for (uint32 x = 0; x < mWidth; ++x)
{
uint32 a = mData[x + (y * mWidth)];
uint32 b = mData[x + (f * mWidth)];
mData[x + (y * mWidth)] = b;
mData[x + (f * mWidth)] = a;
}
}
}
//----------------------------------------------------------------------------//
// Operators Image //
//----------------------------------------------------------------------------//
////////////////////////////////////////////////////////////////////////////////
Image& Image::operator = (const Image& image)
{
if (this != &image)
{
Destroy();
Create (image.mWidth, image.mHeight);
if (mLength != 0) memcpy (mData, image.
mData, mLength * sizeof (uint32));
}
return *this;
}
////////////////////////////////////////////////////////////////////////////////
Image& Image::operator = (Image&& image)
{
if (this != &image)
{
Destroy();
mWidth = image.mWidth;
mHeight = image.mHeight;
mLength = image.mLength;
mData = image.mData;
mLimit = image.mLimit;
RESET (image);
}
return *this;
}
////////////////////////////////////////////////////////////////////////////////
bool Image::operator == (const Image& image) const
{
return mWidth == image.mWidth &&
mHeight == image.mHeight &&
memcmp (mData, image.mData, mLength * sizeof (uint32)) == 0;
}
////////////////////////////////////////////////////////////////////////////////
bool Image::operator != (const Image& image) const
{
return mWidth != image.mWidth ||
mHeight != image.mHeight ||
memcmp (mData, image.mData, mLength * sizeof (uint32)) != 0;
}
ROBOT_NS_END