 |
Gorgon Game Engine
|
Go to the documentation of this file.
6 #include "../Geometry/Point.h"
7 #include "../Geometry/Size.h"
8 #include "../Geometry/Bounds.h"
9 #include "../Graphics/Color.h"
10 #include "../IO/Stream.h"
13 namespace Containers {
48 if(
this == &other)
return *
this;
74 throw std::runtime_error(
"basic_Image size cannot be negative");
103 throw std::runtime_error(
"basic_Image size cannot be negative");
142 throw std::runtime_error(
"basic_Image size cannot be negative");
180 throw std::runtime_error(
"basic_Image data is empty");
225 case Graphics::ColorMode::BGRA:
236 data[i*4+0] = pdata[i*2+0];
237 data[i*4+1] = pdata[i*2+0];
238 data[i*4+2] = pdata[i*2+0];
239 data[i*4+3] = pdata[i*2+1];
250 data[i*4+0] = pdata[i+0];
251 data[i*4+1] = pdata[i+0];
252 data[i*4+2] = pdata[i+0];
267 data[i*4+3] = pdata[i+0];
278 data[i*4+0] = pdata[i*3+0];
279 data[i*4+1] = pdata[i*3+1];
280 data[i*4+2] = pdata[i*3+2];
287 case Graphics::ColorMode::BGR: {
292 data[i*4+0] = pdata[i*3+2];
293 data[i*4+1] = pdata[i*3+1];
294 data[i*4+2] = pdata[i*3+0];
306 throw std::runtime_error(
"Invalid color mode");
322 if(target.X > dest.
GetWidth())
return false;
324 if(target.Y > dest.
GetHeight())
return false;
336 int di = (y+target.Y) *
cpp * dw + target.X *
cpp;
340 memcpy(dd + di, sd + si, cs);
356 source.
Left -= target.X;
361 source.
Top -= target.Y;
372 if(source.
Left >= source.
Right)
return false;
374 if(source.
Top >= source.
Bottom)
return false;
377 int sw = source.
Width();
381 for(
int y=source.
Top; y<source.
Bottom; y++) {
383 int di = ((y - source.
Top + target.Y) * dw + target.X) *
cpp;
387 memcpy(dd + di, sd + si, cs);
404 case Graphics::ColorMode::BGRA:
406 buffer[i*4+0] =
data[i*4+2];
407 buffer[i*4+1] =
data[i*4+1];
408 buffer[i*4+2] =
data[i*4+0];
409 buffer[i*4+3] =
data[i*4+3];
415 buffer[i*4+0] =
data[i*2+0];
416 buffer[i*4+1] =
data[i*2+0];
417 buffer[i*4+2] =
data[i*2+0];
418 buffer[i*4+3] =
data[i*2+1];
424 buffer[i*4+0] =
data[i+0];
425 buffer[i*4+1] =
data[i+0];
426 buffer[i*4+2] =
data[i+0];
436 buffer[i*4+3] =
data[i+0];
442 buffer[i*4+0] =
data[i*3+0];
443 buffer[i*4+1] =
data[i*3+1];
444 buffer[i*4+2] =
data[i*3+2];
449 case Graphics::ColorMode::BGR:
451 buffer[i*4+0] =
data[i*3+2];
452 buffer[i*4+1] =
data[i*3+1];
453 buffer[i*4+2] =
data[i*3+0];
459 throw std::runtime_error(
"Invalid mode");
471 case Graphics::ColorMode::BGRA:
477 buffer[i*4+0] =
data[i*4+2];
478 buffer[i*4+1] =
data[i*4+1];
479 buffer[i*4+2] =
data[i*4+0];
480 buffer[i*4+3] =
data[i*4+3];
486 buffer[i*4+0] =
data[i*2+0];
487 buffer[i*4+1] =
data[i*2+0];
488 buffer[i*4+2] =
data[i*2+0];
489 buffer[i*4+3] =
data[i*2+1];
495 buffer[i*4+0] =
data[i+0];
496 buffer[i*4+1] =
data[i+0];
497 buffer[i*4+2] =
data[i+0];
507 buffer[i*4+3] =
data[i+0];
511 case Graphics::ColorMode::BGR:
513 buffer[i*4+0] =
data[i*3+0];
514 buffer[i*4+1] =
data[i*3+1];
515 buffer[i*4+2] =
data[i*3+2];
522 buffer[i*4+0] =
data[i*3+2];
523 buffer[i*4+1] =
data[i*3+1];
524 buffer[i*4+2] =
data[i*3+0];
530 throw std::runtime_error(
"Invalid mode");
542 case Graphics::ColorMode::BGRA:
544 buffer[i] = (
data[i*4+0]<<0) | (
data[i*4+1]<<8) | (
data[i*4+2]<<16) | (
data[i*4+3]<<24);
550 buffer[i] = (
data[i*4+2]<<0) | (
data[i*4+1]<<8) | (
data[i*4+0]<<16) | (
data[i*4+3]<<24);
556 buffer[i] = (
data[i*2+0]<<0) | (
data[i*2+0]<<8) | (
data[i*2+0]<<16) | (
data[i*2+1]<<24);
562 buffer[i] = (
data[i*1+0]<<0) | (
data[i*1+0]<<8) | (
data[i*1+0]<<16) | (255<<24);
568 buffer[i] = (255<<0) | (255<<8) | (255<<16) | (
data[i*1+0]<<24);
572 case Graphics::ColorMode::BGR:
574 buffer[i] = (
data[i*3+0]<<0) | (
data[i*3+1]<<8) | (
data[i*3+2]<<16) | (255<<24);
580 buffer[i] = (
data[i*3+2]<<0) | (
data[i*3+1]<<8) | (
data[i*3+0]<<16) | (255<<24);
585 throw std::runtime_error(
"Invalid mode");
591 bool ImportBMP(
const std::string &filename,
bool dib =
false) {
592 std::ifstream file(filename, std::ios::binary);
594 if(!file.is_open())
return false;
603 unsigned long off = 0;
618 int width = 0, height = 0;
620 bool upsidedown =
false;
621 bool grayscalepalette =
true;
624 int redshift, greenshift, blueshift, alphashift;
625 float redmult = 1, greenmult = 1, bluemult = 1, alphamult = 1;
626 uint32_t redmask = 0, greenmask = 0, bluemask = 0, alphamask = 0;
628 std::vector<Graphics::RGBA> palette;
630 auto shiftcalc=[](uint32_t v) {
641 if(headersize == 12) {
648 if(headersize >= 40) {
656 if(compress != 0 && compress != 3)
return false;
658 bool bitcompress = compress != 0;
668 if(bitcompress && headersize == 40) {
679 redmask = 0x00ff0000;
680 greenmask = 0x0000ff00;
681 bluemask = 0x000000ff;
685 if(headersize >= 108) {
691 file.seekg(13*4, std::ios::cur);
694 redshift = shiftcalc(redmask);
695 greenshift = shiftcalc(greenmask);
696 blueshift = shiftcalc(bluemask);
697 alphashift = shiftcalc(alphamask);
700 redmult = 255.f / (redmask>>redshift);
703 greenmult = 255.f / (greenmask>>greenshift);
706 bluemult = 255.f / (bluemask>>blueshift);
709 alphamult = 255.f / (alphamask>>alphashift);
712 if(headersize > 108) {
713 file.seekg(headersize - 108, std::ios::cur);
723 colorsused = 1 << bpp;
725 palette.reserve(colorsused);
727 for(
int i=0; i<colorsused; i++) {
728 Byte r, g, b, a = 255;
734 if(r!=b || b!=g) grayscalepalette =
false;
736 if(headersize > 12) {
740 palette.emplace_back(r, g, b, a);
743 for(
int i=0; i<colorsused; i++) {
752 file.seekg(off, std::ios::beg);
754 if((bpp == 32 || bpp == 16) && alphamask != 0) {
758 else if(bpp <= 8 && grayscalepalette) {
765 if(redmask == 0 && greenmask == 0 && bluemask == 0) {
790 for(
int y = ys; y!=ye; y += yc) {
792 for(
int x=0; x<width; x++) {
801 file.seekg(4-bytes%4, std::ios::cur);
805 else if(bpp == 16 || bpp == 32) {
806 for(
int y = ys; y!=ye; y += yc) {
808 for(
int x=0; x<width; x++) {
816 if(redmask != 0 || greenmask != 0 || bluemask != 0) {
817 this->
operator ()({x, y}, 0) = (
Byte)std::round(((pix&redmask)>>redshift) * redmult);
818 this->
operator ()({x, y}, 1) = (
Byte)std::round(((pix&greenmask)>>greenshift) * greenmult);
819 this->
operator ()({x, y}, 2) = (
Byte)std::round(((pix&bluemask)>>blueshift) * bluemult);
823 if(redmask != 0 || greenmask != 0 || bluemask != 0) {
824 this->
operator ()({x, y}, 3) = (
Byte)std::round(((pix&alphamask)>>alphashift) * alphamult);
827 this->
operator ()({x, y}, 0) = (
Byte)std::round(((pix&alphamask)>>alphashift) * alphamult);
835 file.seekg(4-bytes%4, std::ios::cur);
840 Byte bitmask = (1 << bpp) - 1;
841 bitmask = bitmask << (8-bpp);
842 for(
int y = ys; y!=ye; y += yc) {
846 for(
int x=0; x<width; x++) {
854 ind = (v&bitmask)>>(8-bpp);
855 if(ind >= colorsused)
858 auto col = palette[ind];
860 if(grayscalepalette) {
868 this->operator ()({x, y}, 1) = col.G;
869 this->operator ()({x, y}, 2) = col.B;
882 file.seekg(4-bytes%4, std::ios::cur);
893 bool ExportBMP(
const std::string &filename,
bool usev4 =
false,
bool dib =
false) {
894 std::ofstream file(filename, std::ios::binary);
896 if(!file.is_open())
return false;
904 bool ExportBMP(std::ostream &file,
bool usev4 =
false,
bool dib =
false) {
919 if(stride%4) stride += (4-(stride%4));
927 case ColorMode::RGBA:
928 case ColorMode::BGRA:
929 case ColorMode::Grayscale_Alpha:
931 if(stride%4) stride += (4-(stride%4));
940 case ColorMode::Grayscale:
942 if(stride%4) stride += (4-(stride%4));
947 extraspace = 256 * 4;
951 case ColorMode::Alpha:
953 if(stride%4) stride += (4-(stride%4));
964 throw std::runtime_error(
"Unsupported color mode");
971 WriteUInt32(file, 14 + headersize + extraspace + datasize);
989 if(compression == 3) {
990 if(
mode == ColorMode::Alpha) {
995 else if(
mode == ColorMode::BGRA) {
1007 if(headersize == 108 || usev4) {
1008 if(compression != 3) {
1013 if(
mode == ColorMode::Alpha) {
1020 for(
int i=0; i<12; i++)
1026 case ColorMode::RGB:
1031 for(
int j=0; j<stride-ostride; j++)
1036 case ColorMode::BGR:
1042 for(
int j=0; j<stride-ostride; j++)
1048 case ColorMode::RGBA:
1049 case ColorMode::BGRA:
1056 case ColorMode::Grayscale:
1058 for(
int i=0; i<256; i++) {
1070 for(
int j=0; j<stride-ostride; j++)
1078 case ColorMode::Grayscale_Alpha:
1092 case ColorMode::Alpha:
1101 for(
int j=0; j<stride-ostride*2; j++)
1107 throw std::runtime_error(
"Invalid mode");
1118 throw std::runtime_error(
"Index out of bounds");
1129 throw std::runtime_error(
"Index out of bounds");
1162 throw std::runtime_error(
"Index out of bounds");
1173 throw std::runtime_error(
"Index out of bounds");
1182 Byte Get(
int x,
int y,
unsigned component=0)
const {
1214 return {255, 255, 255,
Byte((*
this)(x, y, 0))};
1216 return {
Byte((*
this)(x, y, 0)),
Byte((*
this)(x, y, 0)),
Byte((*
this)(x, y, 0)),
Byte((*
this)(x, y, 1))};
1218 return {
Byte((*
this)(x, y, 0)),
Byte((*
this)(x, y, 0)),
Byte((*
this)(x, y, 0)), 255};
1220 return {
Byte((*
this)(x, y, 0)),
Byte((*
this)(x, y, 1)),
Byte((*
this)(x, y, 2)), 255};
1221 case Graphics::ColorMode::BGR:
1222 return {
Byte((*
this)(x, y, 2)),
Byte((*
this)(x, y, 1)),
Byte((*
this)(x, y, 0)), 255};
1224 return {
Byte((*
this)(x, y, 0)),
Byte((*
this)(x, y, 1)),
Byte((*
this)(x, y, 2)),
Byte((*
this)(x, y, 3))};
1225 case Graphics::ColorMode::BGRA:
1226 return {
Byte((*
this)(x, y, 2)),
Byte((*
this)(x, y, 1)),
Byte((*
this)(x, y, 0)),
Byte((*
this)(x, y, 3))};
1248 (*this)(x, y, 0) = color.
A;
1252 (*this)(x, y, 1) = color.
A;
1258 (*this)(x, y, 0) = color.
R;
1259 (*
this)(x, y, 1) = color.
G;
1260 (*
this)(x, y, 2) = color.
B;
1262 case Graphics::ColorMode::BGR:
1263 (*
this)(x, y, 2) = color.
R;
1264 (*
this)(x, y, 1) = color.
G;
1265 (*
this)(x, y, 0) = color.
B;
1268 (*
this)(x, y, 0) = color.
R;
1269 (*
this)(x, y, 1) = color.
G;
1270 (*
this)(x, y, 2) = color.
B;
1271 (*
this)(x, y, 3) = color.
A;
1273 case Graphics::ColorMode::BGRA:
1274 (*
this)(x, y, 2) = color.
R;
1275 (*
this)(x, y, 1) = color.
G;
1276 (*
this)(x, y, 0) = color.
B;
1277 (*
this)(x, y, 3) = color.
A;
1319 throw std::runtime_error(
"Modes differ in number of bits/pixel");
basic_Image(const basic_Image &)=delete
Copy constructor is disabled.
This class represents boundaries of 2D objects.
Definition: Bounds.h:27
Geometry::Size size
Width of the image.
Definition: Image.h:1345
This class represents a color information.
Definition: Color.h:91
Graphics::RGBA GetRGBAAt(Geometry::Point p) const
Returns the alpha at the given location.
Definition: Image.h:1235
void SetRGBAAt(Geometry::Point p, Graphics::RGBA color)
Sets the color at the given location to the specified RGBA value.
Definition: Image.h:1286
Graphics::ColorMode GetMode() const
Returns the color mode of the image.
Definition: Image.h:1311
bool HasAlpha() const
Returns if this image has alpha channel.
Definition: Image.h:1331
void Resize(const Geometry::Size &size, Graphics::ColorMode mode)
Resizes the image to the given size and color mode.
Definition: Image.h:71
int GetAlphaIndex() const
Returns the index of alpha channel. Value of -1 denotes no alpha channel.
Definition: Image.h:1336
bool ImportBMP(const std::string &filename, bool dib=false)
Imports a given bitmap file. BMP RLE compression and colorspaces are not supported.
Definition: Image.h:591
int alphaloc
Location of the alpha channel, -1 means it does not exits.
Definition: Image.h:1354
ColorMode
Color modes for images.
Definition: Color.h:16
Byte operator()(int x, int y, unsigned component=0) const
Provides access to the given component in x and y coordinates.
Definition: Image.h:1170
void swap(Collection< T_ > &l, Collection< T_ > &r)
Swaps two collections.
Definition: Collection.h:707
void WriteInt32(std::ostream &stream, long value)
Writes a 32-bit integer to the stream.
Definition: Stream.h:197
@ RGB
24bit red, green, blue color mode that has red component in the lowest byte order
@ Invalid
This is used to mark invalid color data.
bool ExportBMP(std::ostream &file, bool usev4=false, bool dib=false)
Exports the image as a bitmap.
Definition: Image.h:904
T_ X
X coordinate.
Definition: Point.h:368
Byte Get(const Geometry::Point &p, Byte def, unsigned component=0) const
Provides access to the given component in x and y coordinates.
Definition: Image.h:1149
Byte * Release()
Returns and disowns the current data buffer. If image is empty, this method will return a nullptr.
Definition: Image.h:168
void CopyToBGRABufferLong(unsigned long *buffer) const
Copies this image to a RGBA buffer, buffer should be resize before calling this function.
Definition: Image.h:536
Byte * RawData()
Returns the raw data pointer.
Definition: Image.h:211
bool IsValid() const
Returns whether the size is valid, i.e. both dimensions are positive.
Definition: Size.h:245
void WriteUInt16(std::ostream &stream, unsigned value)
Writes a 16-bit unsigned integer from the stream.
Definition: Stream.h:218
void ChangeMode(Graphics::ColorMode value)
Changes the color mode of the image.
Definition: Image.h:1317
T_ Height
Height of this size object.
Definition: Size.h:261
T_ Width() const
Calculates and returns the width of the bounds.
Definition: Bounds.h:130
@ RGBA
32bit red, green, blue and alpha channel image. Red component is in the lowest byte order and
Byte operator()(const Geometry::Point &p, unsigned component=0) const
Provides access to the given component in x and y coordinates.
Definition: Image.h:1126
Byte GetAlphaAt(int x, int y) const
Returns the alpha at the given location.
Definition: Image.h:1193
basic_Image()
Constructs an empty image data.
Definition: Image.h:23
bool CopyTo(basic_Image &dest, Geometry::Bounds source, Geometry::Point target={0, 0}) const
Copies data from one image to another.
Definition: Image.h:351
T_ Height() const
Calculates and returns the height of the bounds.
Definition: Bounds.h:135
void CopyToRGBABuffer(Byte *buffer) const
Copies this image to a RGBA buffer, buffer should be resize before calling this function.
Definition: Image.h:394
void WriteArray(std::ostream &stream, const T_ *data, unsigned long size)
Writes an array to the stream.
Definition: Stream.h:294
int GetWidth() const
Returns the width of the image.
Definition: Image.h:1296
Byte A
Alpha channel.
Definition: Color.h:312
Graphics::ColorMode mode
Color mode of the image.
Definition: Image.h:1348
void Assume(Byte *newdata)
Assumes the ownership of the given data.
Definition: Image.h:159
Byte Get(const Geometry::Point &p, unsigned component=0) const
Provides access to the given component in x and y coordinates.
Definition: Image.h:1138
long ReadInt32(std::istream &stream)
Reads a 32-bit integer from the stream.
Definition: Stream.h:26
@ Grayscale
8bit gray scale color mode
basic_Image(basic_Image &&data)
Move constructor.
Definition: Image.h:39
T_ Left
Left-most boundary.
Definition: Bounds.h:399
unsigned long GetTotalSize() const
Total size of this image in number units.
Definition: Image.h:1306
Root namespace for Gorgon Game Engine.
Definition: Any.h:19
This class represents a 2D geometric size.
Definition: Size.h:23
const Byte * RawData() const
Returns the raw data pointer.
Definition: Image.h:216
void Clear()
Cleans the contents of the buffer by setting every byte it contains to 0.
Definition: Image.h:177
void WriteUInt32(std::ostream &stream, unsigned long value)
Writes a 32-bit unsigned integer from the stream.
Definition: Stream.h:204
Byte Get(int x, int y, unsigned component=0) const
Provides access to the given component in x and y coordinates.
Definition: Image.h:1182
int ReadInt16(std::istream &stream)
Reads a 16-bit integer from the stream.
Definition: Stream.h:44
unsigned long ReadUInt32(std::istream &stream)
Reads a 32-bit unsigned integer from the stream.
Definition: Stream.h:35
bool ImportBMP(std::istream &file, bool dib=false)
Imports a given bitmap file. BMP RLE compression and colorspaces are not supported.
Definition: Image.h:600
int GetAlphaIndex(ColorMode mode)
Returns the index of alpha channel. If alpha channel does not exists, this function returns -1.
Definition: Color.h:74
void Destroy()
Destroys this image by setting width and height to 0 and freeing the memory used by its data.
Definition: Image.h:189
unsigned ReadUInt16(std::istream &stream)
Reads a 16-bit unsigned integer from the stream.
Definition: Stream.h:53
bool ExportBMP(const std::string &filename, bool usev4=false, bool dib=false)
Exports the image as a bitmap.
Definition: Image.h:893
Byte & operator()(int x, int y, unsigned component=0)
Provides access to the given component in x and y coordinates.
Definition: Image.h:1159
bool HasAlpha(ColorMode mode)
Returns if the given color mode has alpha channel.
Definition: Color.h:69
Byte & operator()(const Geometry::Point &p, unsigned component=0)
Provides access to the given component in x and y coordinates.
Definition: Image.h:1115
void WriteUInt8(std::ostream &stream, Byte value)
Writes an 8-bit unsigned integer from the stream.
Definition: Stream.h:231
basic_Image Duplicate() const
Duplicates this image, essentially performing the work of copy constructor.
Definition: Image.h:62
Byte Luminance() const
Returns the luminance of this color as a single byte number.
Definition: Color.h:227
basic_Image(const Geometry::Size &size, Graphics::ColorMode mode)
Constructs a new image data with the given width, height and color mode.
Definition: Image.h:28
@ Alpha
8bit alpha only color mode
void Assign(Byte *newdata, const Geometry::Size &size, Graphics::ColorMode mode)
Assigns the image to the copy of the given data.
Definition: Image.h:100
Byte B
Blue channel.
Definition: Color.h:309
This class represents a 2D point.
Definition: Point.h:32
basic_Image & operator=(basic_Image &&other)
Move assignment.
Definition: Image.h:47
void swap(basic_Image< T_ > &l, basic_Image< T_ > &r)
Swaps two images. Should be used unqualified for ADL.
Definition: Image.h:1359
void SetRGBAAt(int x, int y, Graphics::RGBA color)
Sets the color at the given location to the specified RGBA value.
Definition: Image.h:1241
Byte G
Green channel.
Definition: Color.h:306
unsigned char Byte
Represents smallest cell in memory.
Definition: Types.h:9
unsigned long GetChannelsPerPixel(ColorMode mode)
Returns bytes per pixel for the given color mode.
Definition: Color.h:47
T_ Right
Right-most boundary.
Definition: Bounds.h:405
void Assign(Byte *newdata)
Assigns the image to the copy of the given data.
Definition: Image.h:128
bool CopyTo(basic_Image &dest, Geometry::Point target={0, 0}) const
Copies data from one image to another.
Definition: Image.h:318
void CopyToBGRABuffer(Byte *buffer) const
Copies this image to a RGBA buffer, buffer should be resize before calling this function.
Definition: Image.h:465
T_ Bottom
Bottom-most boundary.
Definition: Bounds.h:408
T_ Area() const
Returns the exact area of the rectangle has the size of this object.
Definition: Size.h:240
This class is a container for image data.
Definition: Image.h:19
T_ Y
Y coordinate.
Definition: Point.h:371
T_ Width
Width of this size object.
Definition: Size.h:258
Byte R
Red channel.
Definition: Color.h:303
void Assume(Byte *newdata, const Geometry::Size &size, Graphics::ColorMode mode)
Assumes the ownership of the given data.
Definition: Image.h:139
int GetHeight() const
Returns the height of the image.
Definition: Image.h:1301
void Swap(basic_Image &other)
Swaps this image with another. This function is used to implement move semantics.
Definition: Image.h:200
~basic_Image()
Destructor.
Definition: Image.h:57
basic_Image & operator=(const basic_Image &)=delete
Copy assignment is disabled.
unsigned cpp
Channels per pixel information.
Definition: Image.h:1351
void ConvertToRGBA()
Converts this image data to RGBA buffer.
Definition: Image.h:221
T_ * data
Data that stores pixels of the image.
Definition: Image.h:1342
Graphics::RGBA GetRGBAAt(int x, int y) const
Returns the alpha at the given location.
Definition: Image.h:1207
Geometry::Size GetSize() const
Returns the size of the image.
Definition: Image.h:1291
T_ Top
Top-most boundary.
Definition: Bounds.h:402
void WriteString(std::ostream &stream, const std::string &value)
Writes a string without its size.
Definition: Stream.h:285
Byte ReadUInt8(std::istream &stream)
Reads an 8-bit unsigned integer from the stream.
Definition: Stream.h:71
unsigned GetChannelsPerPixel() const
Returns the number units occupied by a single pixel of this image.
Definition: Image.h:1326
std::string ReadString(std::istream &stream)
Reads a string from a given stream.
Definition: Stream.h:135