Gorgon Game Engine
Image.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <vector>
4 
5 #include "../Types.h"
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"
11 
12 namespace Gorgon {
13  namespace Containers {
14 
18  template<class T_>
19  class basic_Image {
20  public:
21 
24  }
25 
30  data=(Byte*)malloc(size.Area()*cpp*sizeof(T_));
31 
33  }
34 
36  basic_Image(const basic_Image &) = delete;
37 
40  Swap(data);
41  }
42 
44  basic_Image &operator=(const basic_Image &) = delete;
45 
48  if(this == &other) return *this;
49 
50  Destroy();
51  Swap(other);
52 
53  return *this;
54  }
55 
58  Destroy();
59  }
60 
63  basic_Image n;
64  n.Assign(data, size, mode);
65 
66  return n;
67  }
68 
72 #ifndef NDEBUG
73  if(!size.IsValid())
74  throw std::runtime_error("basic_Image size cannot be negative");
75 #endif
76 
77  // Check if resize is really necessary
78  if(this->size==size && this->cpp==Graphics::GetChannelsPerPixel(mode))
79  return;
80 
81  this->size = size;
82  this->mode = mode;
83  this->cpp = Graphics::GetChannelsPerPixel(mode);
85 
86  if(data) {
87  free(data);
88  }
89 
90  data=(Byte*)malloc(size.Area()*cpp*sizeof(T_));
91  }
92 
101 #ifndef NDEBUG
102  if(!size.IsValid())
103  throw std::runtime_error("basic_Image size cannot be negative");
104 #endif
105  this->size = size;
106  this->mode = mode;
107  this->cpp = Graphics::GetChannelsPerPixel(mode);
109 
110  if(data && data!=newdata) {
111  free(data);
112  }
113 
114  if(size.Area()*cpp>0) {
115  data=(Byte*)malloc(size.Area()*cpp*sizeof(T_));
116  memcpy(data, newdata, size.Area()*cpp*sizeof(T_));
117  }
118  else {
119  data=nullptr;
120  }
121  }
122 
128  void Assign(Byte *newdata) {
129  memcpy(data, newdata, size.Area()*cpp*sizeof(T_));
130  }
131 
140 #ifndef NDEBUG
141  if(!size.IsValid())
142  throw std::runtime_error("basic_Image size cannot be negative");
143 #endif
144  this->size = size;
145  this->mode = mode;
146  this->cpp = Graphics::GetChannelsPerPixel(mode);
148 
149  if(data && data!=newdata) {
150  free(data);
151  }
152 
153  data=newdata;
154  }
155 
159  void Assume(Byte *newdata) {
160  if(data && data!=newdata) {
161  free(data);
162  }
163 
164  data=newdata;
165  }
166 
169  auto temp=data;
170  data=nullptr;
171  Destroy();
172 
173  return temp;
174  }
175 
177  void Clear() {
178 #ifndef NDEBUG
179  if(!data) {
180  throw std::runtime_error("basic_Image data is empty");
181  }
182 #endif
183 
184  memset(data, 0, size.Area()*cpp*sizeof(T_));
185  }
186 
189  void Destroy() {
190  if(data) {
191  free(data);
192  data=nullptr;
193  }
194  size = {0, 0};
195  cpp = 0;
197  }
198 
200  void Swap(basic_Image &other) {
201  using std::swap;
202 
203  swap(data, other.data);
204  swap(size, other.size);
205  swap(mode, other.mode);
206  swap(cpp, other.cpp);
207  swap(alphaloc, other.alphaloc);
208  }
209 
212  return data;
213  }
214 
216  const Byte *RawData() const {
217  return data;
218  }
219 
221  void ConvertToRGBA() {
222  if(!data) return;
223 
224  switch(mode) {
225  case Graphics::ColorMode::BGRA:
226  for(int i=0; i<size.Area(); i++) {
227  std::swap(data[i*4+2], data[i*4+0]);
228  }
229  break;
230 
232  auto pdata = data;
233  data = (Byte*)malloc(size.Area()*4*sizeof(T_));
234 
235  for(int i=0; i<size.Area(); i++) {
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];
240  }
241  delete pdata;
242  }
243  break;
244 
246  auto pdata = data;
247  data = (Byte*)malloc(size.Area()*4*sizeof(T_));
248 
249  for(int i=0; i<size.Area(); i++) {
250  data[i*4+0] = pdata[i+0];
251  data[i*4+1] = pdata[i+0];
252  data[i*4+2] = pdata[i+0];
253  data[i*4+3] = 255;
254  }
255  delete pdata;
256  }
257  break;
258 
260  auto pdata = data;
261  data = (Byte*)malloc(size.Area()*4*sizeof(T_));
262 
263  for(int i=0; i<size.Area(); i++) {
264  data[i*4+0] = 255;
265  data[i*4+1] = 255;
266  data[i*4+2] = 255;
267  data[i*4+3] = pdata[i+0];
268  }
269  delete pdata;
270  }
271  break;
272 
274  auto pdata = data;
275  data = (Byte*)malloc(size.Area()*4*sizeof(T_));
276 
277  for(int i=0; i<size.Area(); i++) {
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];
281  data[i*4+3] = 255;
282  }
283  delete pdata;
284  }
285  break;
286 
287  case Graphics::ColorMode::BGR: {
288  auto pdata = data;
289  data = (Byte*)malloc(size.Area()*4*sizeof(T_));
290 
291  for(int i=0; i<size.Area(); i++) {
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];
295  data[i*4+3] = 255;
296  }
297  delete pdata;
298  }
299  break;
300 
302  //do nothing
303  break;
304 
305  default:
306  throw std::runtime_error("Invalid color mode");
307 
308  }
309 
311  }
312 
313  // cppcheck-suppress constParameter
318  bool CopyTo(basic_Image &dest, Geometry::Point target = {0, 0}) const {
319  if(dest.GetMode() != mode || size.Area() == 0 || dest.GetSize().Area() == 0)
320  return false;
321 
322  if(target.X > dest.GetWidth()) return false;
323 
324  if(target.Y > dest.GetHeight()) return false;
325 
326  int dw = dest.GetWidth(), dh = dest.GetHeight();
327  Byte *dd = dest.RawData();
328  const Byte *sd = RawData();
329 
330  for(int y=0; y<GetHeight(); y++) {
331  //out of pixels to copy
332  if(y+target.Y >= dh)
333  break;
334 
335  int si = y * cpp * size.Width;
336  int di = (y+target.Y) * cpp * dw + target.X * cpp;
337 
338  int cs = std::min(size.Width, dw - target.X) * cpp;
339 
340  memcpy(dd + di, sd + si, cs);
341  }
342 
343  return true;
344  }
345 
346  // cppcheck-suppress constParameter
351  bool CopyTo(basic_Image &dest, Geometry::Bounds source, Geometry::Point target = {0, 0}) const {
352  if(dest.GetMode() != mode || size.Area() == 0 || dest.GetSize().Area() == 0)
353  return false;
354 
355  if(target.X < 0) {
356  source.Left -= target.X;
357  target.X = 0;
358  }
359 
360  if(target.Y < 0) {
361  source.Top -= target.Y;
362  target.Y = 0;
363  }
364 
365  if(target.X + source.Width() > dest.GetWidth()) {
366  source.Right -= target.X + source.Width() - dest.GetWidth();
367  }
368  if(target.Y + source.Height() > dest.GetHeight()) {
369  source.Bottom -= target.Y + source.Height() - dest.GetHeight();
370  }
371 
372  if(source.Left >= source.Right) return false;
373 
374  if(source.Top >= source.Bottom) return false;
375 
376  int dw = dest.GetWidth();
377  int sw = source.Width();
378  Byte *dd = dest.RawData();
379  const Byte *sd = RawData();
380 
381  for(int y=source.Top; y<source.Bottom; y++) {
382  int si = (y * size.Width + source.Left) * cpp;
383  int di = ((y - source.Top + target.Y) * dw + target.X) * cpp;
384 
385  int cs = sw * cpp;
386 
387  memcpy(dd + di, sd + si, cs);
388  }
389 
390  return true;
391  }
392 
394  void CopyToRGBABuffer(Byte *buffer) const {
395  if(!data) return;
396 
397  int i;
398 
399  switch(mode) {
401  memcpy(buffer, data, size.Area()*4);
402  break;
403 
404  case Graphics::ColorMode::BGRA:
405  for(i=0; i<size.Area(); i++) {
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];
410  }
411  break;
412 
414  for(i=0; i<size.Area(); i++) {
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];
419  }
420  break;
421 
423  for(i=0; i<size.Area(); i++) {
424  buffer[i*4+0] = data[i+0];
425  buffer[i*4+1] = data[i+0];
426  buffer[i*4+2] = data[i+0];
427  buffer[i*4+3] = 255;
428  }
429  break;
430 
432  for(i=0; i<size.Area(); i++) {
433  buffer[i*4+0] = 255;
434  buffer[i*4+1] = 255;
435  buffer[i*4+2] = 255;
436  buffer[i*4+3] = data[i+0];
437  }
438  break;
439 
441  for(i=0; i<size.Area(); i++) {
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];
445  buffer[i*4+3] = 255;
446  }
447  break;
448 
449  case Graphics::ColorMode::BGR:
450  for(i=0; i<size.Area(); i++) {
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];
454  buffer[i*4+3] = 255;
455  }
456  break;
457 
458  default:
459  throw std::runtime_error("Invalid mode");
460  }
461  }
462 
465  void CopyToBGRABuffer(Byte *buffer) const {
466  if(!data) return;
467 
468  int i;
469 
470  switch(mode) {
471  case Graphics::ColorMode::BGRA:
472  memcpy(buffer, data, size.Area()*4);
473  break;
474 
476  for(i=0; i<size.Area(); i++) {
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];
481  }
482  break;
483 
485  for(i=0; i<size.Area(); i++) {
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];
490  }
491  break;
492 
494  for(i=0; i<size.Area(); i++) {
495  buffer[i*4+0] = data[i+0];
496  buffer[i*4+1] = data[i+0];
497  buffer[i*4+2] = data[i+0];
498  buffer[i*4+3] = 255;
499  }
500  break;
501 
503  for(i=0; i<size.Area(); i++) {
504  buffer[i*4+0] = 255;
505  buffer[i*4+1] = 255;
506  buffer[i*4+2] = 255;
507  buffer[i*4+3] = data[i+0];
508  }
509  break;
510 
511  case Graphics::ColorMode::BGR:
512  for(i=0; i<size.Area(); i++) {
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];
516  buffer[i*4+3] = 255;
517  }
518  break;
519 
521  for(i=0; i<size.Area(); i++) {
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];
525  buffer[i*4+3] = 255;
526  }
527  break;
528 
529  default:
530  throw std::runtime_error("Invalid mode");
531 
532  }
533  }
536  void CopyToBGRABufferLong(unsigned long *buffer) const {
537  if(!data) return;
538 
539  int i;
540 
541  switch(mode) {
542  case Graphics::ColorMode::BGRA:
543  for(i=0; i<size.Area(); i++) {
544  buffer[i] = (data[i*4+0]<<0) | (data[i*4+1]<<8) | (data[i*4+2]<<16) | (data[i*4+3]<<24);
545  }
546  break;
547 
549  for(i=0; i<size.Area(); i++) {
550  buffer[i] = (data[i*4+2]<<0) | (data[i*4+1]<<8) | (data[i*4+0]<<16) | (data[i*4+3]<<24);
551  }
552  break;
553 
555  for(i=0; i<size.Area(); i++) {
556  buffer[i] = (data[i*2+0]<<0) | (data[i*2+0]<<8) | (data[i*2+0]<<16) | (data[i*2+1]<<24);
557  }
558  break;
559 
561  for(i=0; i<size.Area(); i++) {
562  buffer[i] = (data[i*1+0]<<0) | (data[i*1+0]<<8) | (data[i*1+0]<<16) | (255<<24);
563  }
564  break;
565 
567  for(i=0; i<size.Area(); i++) {
568  buffer[i] = (255<<0) | (255<<8) | (255<<16) | (data[i*1+0]<<24);
569  }
570  break;
571 
572  case Graphics::ColorMode::BGR:
573  for(i=0; i<size.Area(); i++) {
574  buffer[i] = (data[i*3+0]<<0) | (data[i*3+1]<<8) | (data[i*3+2]<<16) | (255<<24);
575  }
576  break;
577 
579  for(i=0; i<size.Area(); i++) {
580  buffer[i] = (data[i*3+2]<<0) | (data[i*3+1]<<8) | (data[i*3+0]<<16) | (255<<24);
581  }
582  break;
583 
584  default:
585  throw std::runtime_error("Invalid mode");
586 
587  }
588  }
589 
591  bool ImportBMP(const std::string &filename, bool dib = false) {
592  std::ifstream file(filename, std::ios::binary);
593 
594  if(!file.is_open()) return false;
595 
596  return ImportBMP(file, dib);
597  }
598 
600  bool ImportBMP(std::istream &file, bool dib = false) {
601  using namespace IO;
602 
603  unsigned long off = 0;
604 
605  if(!dib) {
606  if(ReadString(file, 2) != "BM") return false;
607 
608  IO::ReadUInt32(file);
609 
610  ReadUInt16(file); //reserved 1
611  ReadUInt16(file); //reserved 2
612 
613  off = ReadUInt32(file);
614  }
615 
616  auto headersize = IO::ReadUInt32(file);
617 
618  int width = 0, height = 0;
619  int bpp = 0;
620  bool upsidedown = false;
621  bool grayscalepalette = true;
622  int colorsused = 0;
623  bool alpha = false;
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;
627 
628  std::vector<Graphics::RGBA> palette;
629 
630  auto shiftcalc=[](uint32_t v) {
631  int pos = 0;
632  while(v) {
633  if(v&1) return pos;
634  v=v>>1;
635  pos++;
636  }
637 
638  return pos;
639  };
640 
641  if(headersize == 12) { //2x bmp
642  width = ReadInt16(file);
643  height = ReadInt16(file);
644  ReadUInt16(file); //planes
645  bpp = ReadUInt16(file);
646  }
647 
648  if(headersize >= 40) { //3x
649  width = ReadInt32(file);
650  height = ReadInt32(file);
651  ReadUInt16(file); //planes
652  bpp = ReadUInt16(file);
653 
654  auto compress = ReadUInt32(file);
655 
656  if(compress != 0 && compress != 3) return false;
657 
658  bool bitcompress = compress != 0;
659 
660  ReadUInt32(file); //size of bitmap
661 
662  ReadInt32(file); //horz resolution
663  ReadInt32(file); //vert resolution
664 
665  colorsused = ReadUInt32(file);
666  ReadUInt32(file); //colors important
667 
668  if(bitcompress && headersize == 40) {
669  redmask = (uint32_t)ReadUInt32(file);
670  greenmask = (uint32_t)ReadUInt32(file);
671  bluemask = (uint32_t)ReadUInt32(file);
672  }
673  else if(bpp == 16) {
674  redmask = 0x7c00;
675  greenmask = 0x03e0;
676  bluemask = 0x001f;
677  }
678  else if(bpp == 32) {
679  redmask = 0x00ff0000;
680  greenmask = 0x0000ff00;
681  bluemask = 0x000000ff;
682  }
683  }
684 
685  if(headersize >= 108) {
686  redmask = (uint32_t)ReadUInt32(file);
687  greenmask = (uint32_t)ReadUInt32(file);
688  bluemask = (uint32_t)ReadUInt32(file);
689  alphamask = (uint32_t)ReadUInt32(file);
690 
691  file.seekg(13*4, std::ios::cur); //colorspace information
692  }
693 
694  redshift = shiftcalc(redmask);
695  greenshift = shiftcalc(greenmask);
696  blueshift = shiftcalc(bluemask);
697  alphashift = shiftcalc(alphamask);
698 
699  if(redmask) {
700  redmult = 255.f / (redmask>>redshift);
701  }
702  if(greenmask) {
703  greenmult = 255.f / (greenmask>>greenshift);
704  }
705  if(bluemask) {
706  bluemult = 255.f / (bluemask>>blueshift);
707  }
708  if(alphamask) {
709  alphamult = 255.f / (alphamask>>alphashift);
710  }
711 
712  if(headersize > 108) {
713  file.seekg(headersize - 108, std::ios::cur);
714  }
715 
716  if(height > 0)
717  upsidedown = true;
718  else
719  height *= -1;
720 
721  if(bpp <= 8) { //paletted
722  if(colorsused == 0)
723  colorsused = 1 << bpp;
724 
725  palette.reserve(colorsused);
726 
727  for(int i=0; i<colorsused; i++) {
728  Byte r, g, b, a = 255;
729 
730  b = ReadUInt8(file);
731  g = ReadUInt8(file);
732  r = ReadUInt8(file);
733 
734  if(r!=b || b!=g) grayscalepalette = false;
735 
736  if(headersize > 12) {
737  a = ReadUInt8(file); //reserved
738  }
739 
740  palette.emplace_back(r, g, b, a);
741  }
742 
743  for(int i=0; i<colorsused; i++) {
744  if(palette[i].A) {
745  alpha = true;
746  break;
747  }
748  }
749  }
750 
751  if(!dib)
752  file.seekg(off, std::ios::beg);
753 
754  if((bpp == 32 || bpp == 16) && alphamask != 0) {
755  Resize({width, height}, Graphics::ColorMode::RGBA);
756  alpha = true;
757  }
758  else if(bpp <= 8 && grayscalepalette) {
759  if(alpha)
761  else
762  Resize({width, height}, Graphics::ColorMode::Grayscale);
763  }
764  else if(alpha) {
765  if(redmask == 0 && greenmask == 0 && bluemask == 0) {
766  Resize({width, height}, Graphics::ColorMode::Alpha);
767  }
768  else {
769  Resize({width, height}, Graphics::ColorMode::RGBA);
770  }
771  }
772  else {
773  Resize({width, height}, Graphics::ColorMode::RGB);
774  }
775 
776  int ys, ye, yc;
777 
778  if(upsidedown) {
779  ys = height-1;
780  ye = -1;
781  yc = -1;
782  }
783  else {
784  ys = 0;
785  ye = height;
786  yc = 1;
787  }
788 
789  if(bpp == 24) {
790  for(int y = ys; y!=ye; y += yc) {
791  int bytes = 0;
792  for(int x=0; x<width; x++) {
793  this->operator ()({x, y}, 0) = ReadUInt8(file);
794  this->operator ()({x, y}, 1) = ReadUInt8(file);
795  this->operator ()({x, y}, 2) = ReadUInt8(file);
796 
797  bytes += 3;
798  }
799 
800  if(bytes%4) {
801  file.seekg(4-bytes%4, std::ios::cur);
802  }
803  }
804  }
805  else if(bpp == 16 || bpp == 32) {
806  for(int y = ys; y!=ye; y += yc) {
807  int bytes = 0;
808  for(int x=0; x<width; x++) {
809  uint32_t pix;
810 
811  if(bpp == 16)
812  pix = ReadUInt16(file);
813  else
814  pix = ReadUInt32(file);
815 
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);
820  }
821 
822  if(alpha) {
823  if(redmask != 0 || greenmask != 0 || bluemask != 0) {
824  this->operator ()({x, y}, 3) = (Byte)std::round(((pix&alphamask)>>alphashift) * alphamult);
825  }
826  else {
827  this->operator ()({x, y}, 0) = (Byte)std::round(((pix&alphamask)>>alphashift) * alphamult);
828  }
829  }
830 
831  bytes += bpp/8;
832  }
833 
834  if(bytes%4) {
835  file.seekg(4-bytes%4, std::ios::cur);
836  }
837  }
838  }
839  else if(bpp < 8) {
840  Byte bitmask = (1 << bpp) - 1;
841  bitmask = bitmask << (8-bpp);
842  for(int y = ys; y!=ye; y += yc) {
843  int bytes = 0;
844  int bits = 0;
845  Byte v = 0;
846  for(int x=0; x<width; x++) {
847  int ind;
848  if(bits == 0) {
849  v = ReadUInt8(file);
850  bits = 8;
851  bytes++;
852  }
853 
854  ind = (v&bitmask)>>(8-bpp);
855  if(ind >= colorsused)
856  continue;
857 
858  auto col = palette[ind];
859 
860  if(grayscalepalette) {
861  this->operator ()({x, y}, 0) = col.R;
862 
863  if(alpha)
864  this->operator ()({x, y}, 1) = col.A;
865  }
866  else {
867  this->operator ()({x, y}, 0) = col.R;
868  this->operator ()({x, y}, 1) = col.G;
869  this->operator ()({x, y}, 2) = col.B;
870 
871 
872  if(alpha) {
873  this->operator ()({x, y}, 3) = col.A;
874  }
875  }
876 
877  v = v<<bpp;
878  bits -= bpp;
879  }
880 
881  if(bytes%4) {
882  file.seekg(4-bytes%4, std::ios::cur);
883  }
884  }
885  }
886 
887  return true;
888  }
889 
893  bool ExportBMP(const std::string &filename, bool usev4 = false, bool dib = false) {
894  std::ofstream file(filename, std::ios::binary);
895 
896  if(!file.is_open()) return false;
897 
898  return ExportBMP(file, usev4, dib);
899  }
900 
904  bool ExportBMP(std::ostream &file, bool usev4 = false, bool dib = false) {
905  using namespace IO;
906  using Graphics::ColorMode;
907 
908  long datasize = 0;
909  long headersize = 0;
910  long extraspace = 0;
911  int bpp = 0;
912  int compression = 0;
913  int stride = 0;
914 
915  switch(mode) {
916  case ColorMode::RGB:
917  case ColorMode::BGR:
918  stride = 3 * size.Width;
919  if(stride%4) stride += (4-(stride%4));
920 
921  datasize = stride * size.Height;
922 
923  headersize = 40;
924  bpp = 24;
925  break;
926 
927  case ColorMode::RGBA:
928  case ColorMode::BGRA:
929  case ColorMode::Grayscale_Alpha:
930  stride = 4 * size.Width;
931  if(stride%4) stride += (4-(stride%4));
932 
933  datasize = stride * size.Height;
934 
935  headersize = 108;
936  bpp = 32;
937  compression = 3;
938  break;
939 
940  case ColorMode::Grayscale:
941  stride = size.Width;
942  if(stride%4) stride += (4-(stride%4));
943 
944  datasize = stride * size.Height;
945 
946  headersize = 40;
947  extraspace = 256 * 4; //palette
948  bpp = 8;
949  break;
950 
951  case ColorMode::Alpha:
952  stride = 2 * size.Width;
953  if(stride%4) stride += (4-(stride%4));
954 
955  datasize = stride * size.Height;
956 
957  headersize = 108;
958 
959  compression = 3;
960  bpp = 16;
961  break;
962 
963  default:
964  throw std::runtime_error("Unsupported color mode");
965  }
966 
967 
968  //header
969  if(!dib) {
970  WriteString(file, "BM");
971  WriteUInt32(file, 14 + headersize + extraspace + datasize);
972  WriteUInt16(file, 0); //reserved 1
973  WriteUInt16(file, 0); //reserved 2
974  WriteUInt32(file, 14 + headersize + extraspace);
975  }
976 
977  WriteUInt32(file, headersize);
978  WriteInt32 (file, size.Width);
979  WriteInt32 (file, size.Height);
980  WriteUInt16(file, 1);
981  WriteUInt16(file, bpp);
982  WriteUInt32(file, compression);
983  WriteUInt32(file, datasize);
984  WriteInt32 (file, 2834);
985  WriteInt32 (file, 2834);
986  WriteInt32(file, 0); //colors used
987  WriteInt32(file, 0); //colors important
988 
989  if(compression == 3) {
990  if(mode == ColorMode::Alpha) {
991  WriteUInt32(file, 0x00000001);
992  WriteUInt32(file, 0x00000002);
993  WriteUInt32(file, 0x00000004);
994  }
995  else if(mode == ColorMode::BGRA) {
996  WriteUInt32(file, 0x00ff0000);
997  WriteUInt32(file, 0x0000ff00);
998  WriteUInt32(file, 0x000000ff);
999  }
1000  else {
1001  WriteUInt32(file, 0x000000ff);
1002  WriteUInt32(file, 0x0000ff00);
1003  WriteUInt32(file, 0x00ff0000);
1004  }
1005  }
1006 
1007  if(headersize == 108 || usev4) {
1008  if(compression != 3) {
1009  WriteUInt32(file, 0x00000001);
1010  WriteUInt32(file, 0x00000002);
1011  WriteUInt32(file, 0x00000004);
1012  }
1013  if(mode == ColorMode::Alpha) {
1014  WriteUInt32(file, 0x0000ff00);
1015  }
1016  else {
1017  WriteUInt32(file, 0xff000000);
1018  }
1019  WriteUInt32(file, 1); //device dependent RGB
1020  for(int i=0; i<12; i++) //color profile settings, all 0
1021  WriteUInt32(file, 0);
1022  }
1023 
1024  int ostride;
1025  switch(mode) {
1026  case ColorMode::RGB:
1027  ostride = size.Width*3;
1028  for(int y=size.Height-1; y>=0; y--) {
1029  WriteArray(file, data+y*ostride, ostride);
1030 
1031  for(int j=0; j<stride-ostride; j++)
1032  WriteUInt8(file, 0);
1033  }
1034  break;
1035 
1036  case ColorMode::BGR:
1037  ostride = size.Width*3;
1038 
1039  for(int y=size.Height-1; y>=0; y--) {
1040  WriteArray(file, data+y*ostride, ostride);
1041 
1042  for(int j=0; j<stride-ostride; j++)
1043  WriteUInt8(file, 0);
1044  }
1045  break;
1046 
1047 
1048  case ColorMode::RGBA:
1049  case ColorMode::BGRA:
1050  ostride = size.Width*4;
1051  for(int y=size.Height-1; y>=0; y--) {
1052  WriteArray(file, data+y*ostride, ostride);
1053  }
1054  break;
1055 
1056  case ColorMode::Grayscale:
1057  //write palette
1058  for(int i=0; i<256; i++) {
1059  WriteUInt8(file, (Byte)i);
1060  WriteUInt8(file, (Byte)i);
1061  WriteUInt8(file, (Byte)i);
1062  WriteUInt8(file, 0);
1063  }
1064 
1065  //write data
1066  ostride = size.Width;
1067  for(int y=size.Height-1; y>=0; y--) {
1068  WriteArray(file, data+y*ostride, ostride);
1069 
1070  for(int j=0; j<stride-ostride; j++)
1071  WriteUInt8(file, 0);
1072  }
1073 
1074 
1075  break;
1076 
1077 
1078  case ColorMode::Grayscale_Alpha:
1079  ostride = size.Width*2;
1080 
1081  for(int y=size.Height-1; y>=0; y--) {
1082  for(int x=0; x<size.Width; x++) {
1083  WriteUInt8(file, data[y*ostride+x*2]);
1084  WriteUInt8(file, data[y*ostride+x*2]);
1085  WriteUInt8(file, data[y*ostride+x*2]);
1086  WriteUInt8(file, data[y*ostride+x*2+1]);
1087  }
1088  }
1089  break;
1090 
1091 
1092  case ColorMode::Alpha:
1093  ostride = size.Width;
1094 
1095  for(int y=size.Height-1; y>=0; y--) {
1096  for(int x=0; x<size.Width; x++) {
1097  WriteUInt8(file, 0xff);
1098  WriteUInt8(file, data[y*ostride+x]);
1099  }
1100 
1101  for(int j=0; j<stride-ostride*2; j++)
1102  WriteUInt8(file, 0);
1103  }
1104  break;
1105 
1106  default:
1107  throw std::runtime_error("Invalid mode");
1108  }
1109 
1110  return true;
1111  }
1112 
1115  Byte &operator()(const Geometry::Point &p, unsigned component=0) {
1116 #ifndef NDEBUG
1117  if(p.X<0 || p.Y<0 || p.X>=size.Width || p.Y>=size.Height || component>=cpp) {
1118  throw std::runtime_error("Index out of bounds");
1119  }
1120 #endif
1121  return data[cpp*(size.Width*p.Y+p.X)+component];
1122  }
1123 
1126  Byte operator()(const Geometry::Point &p, unsigned component=0) const {
1127 #ifndef NDEBUG
1128  if(p.X<0 || p.Y<0 || p.X>=size.Width || p.Y>=size.Height || component>=cpp) {
1129  throw std::runtime_error("Index out of bounds");
1130  }
1131 #endif
1132  return data[cpp*(size.Width*p.Y+p.X)+component];
1133  }
1134 
1138  Byte Get(const Geometry::Point &p, unsigned component = 0) const {
1139  if (p.X < 0 || p.Y < 0 || p.X >= size.Width || p.Y >= size.Height || component >= cpp) {
1140  return 0;
1141  }
1142 
1143  return data[cpp*(size.Width*p.Y + p.X) + component];
1144  }
1145 
1149  Byte Get(const Geometry::Point &p, Byte def, unsigned component = 0) const {
1150  if (p.X < 0 || p.Y < 0 || p.X >= size.Width || p.Y >= size.Height || component >= cpp) {
1151  return def;
1152  }
1153 
1154  return data[cpp*(size.Width*p.Y + p.X) + component];
1155  }
1156 
1159  Byte &operator()(int x, int y, unsigned component=0) {
1160 #ifndef NDEBUG
1161  if(x<0 || y<0 || x>=size.Width || y>=size.Height || component>=cpp) {
1162  throw std::runtime_error("Index out of bounds");
1163  }
1164 #endif
1165  return data[cpp*(size.Width*y+x)+component];
1166  }
1167 
1170  Byte operator()(int x, int y, unsigned component=0) const {
1171 #ifndef NDEBUG
1172  if(x<0 || y<0 || x>=size.Width || y>=size.Height || component>=cpp) {
1173  throw std::runtime_error("Index out of bounds");
1174  }
1175 #endif
1176  return data[cpp*(size.Width*y+x)+component];
1177  }
1178 
1182  Byte Get(int x, int y, unsigned component=0) const {
1183  if(x<0 || y<0 || x>=size.Width || y>=size.Height || component>=cpp) {
1184  return 0;
1185  }
1186 
1187  return data[cpp*(size.Width*y+x)+component];
1188  }
1189 
1193  Byte GetAlphaAt(int x, int y) const {
1194  if(x<0 || y<0 || x>=size.Width || y>=size.Height) {
1195  return 0;
1196  }
1197 
1198  if(alphaloc == -1)
1199  return 255;
1200 
1201  return data[cpp*(size.Width*y+x)+alphaloc];
1202  }
1203 
1207  Graphics::RGBA GetRGBAAt(int x, int y) const {
1208  if(x<0 || y<0 || x>=size.Width || y>=size.Height) {
1209  return 0;
1210  }
1211 
1212  switch(mode) {
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))};
1227  default:
1228  return 0;
1229  }
1230  }
1231 
1236  return GetRGBAAt(p.X, p.Y);
1237  }
1238 
1241  void SetRGBAAt(int x, int y, Graphics::RGBA color) {
1242  if(x<0 || y<0 || x>=size.Width || y>=size.Height) {
1243  return;
1244  }
1245 
1246  switch(mode) {
1248  (*this)(x, y, 0) = color.A;
1249  break;
1251  (*this)(x, y, 0) = color.Luminance();
1252  (*this)(x, y, 1) = color.A;
1253  break;
1255  (*this)(x, y, 0) = color.Luminance();
1256  break;
1258  (*this)(x, y, 0) = color.R;
1259  (*this)(x, y, 1) = color.G;
1260  (*this)(x, y, 2) = color.B;
1261  break;
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;
1266  break;
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;
1272  break;
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;
1278  break;
1279  default:
1280  ;
1281  }
1282  }
1283 
1287  SetRGBAAt(p.X, p.Y, color);
1288  }
1289 
1292  return size;
1293  }
1294 
1296  int GetWidth() const {
1297  return size.Width;
1298  }
1299 
1301  int GetHeight() const {
1302  return size.Height;
1303  }
1304 
1306  unsigned long GetTotalSize() const {
1307  return size.Area()*cpp;
1308  }
1309 
1312  return mode;
1313  }
1314 
1319  throw std::runtime_error("Modes differ in number of bits/pixel");
1320 
1321  mode = value;
1323  }
1324 
1326  unsigned GetChannelsPerPixel() const {
1327  return cpp;
1328  }
1329 
1331  bool HasAlpha() const {
1332  return alphaloc != -1;
1333  }
1334 
1336  int GetAlphaIndex() const {
1337  return alphaloc;
1338  }
1339 
1340  protected:
1342  T_ *data = nullptr;
1343 
1346 
1349 
1351  unsigned cpp = 0;
1352 
1354  int alphaloc = -1;
1355  };
1356 
1358  template <class T_>
1359  inline void swap(basic_Image<T_> &l, basic_Image<T_> &r) {
1360  l.Swap(r);
1361  }
1362 
1363 
1365 
1366  }
1367 }
Gorgon::Containers::basic_Image::basic_Image
basic_Image(const basic_Image &)=delete
Copy constructor is disabled.
Gorgon::Geometry::basic_Bounds
This class represents boundaries of 2D objects.
Definition: Bounds.h:27
Gorgon::Containers::basic_Image::size
Geometry::Size size
Width of the image.
Definition: Image.h:1345
Gorgon::Graphics::RGBA
This class represents a color information.
Definition: Color.h:91
Gorgon::Containers::basic_Image::GetRGBAAt
Graphics::RGBA GetRGBAAt(Geometry::Point p) const
Returns the alpha at the given location.
Definition: Image.h:1235
Gorgon::Containers::basic_Image::SetRGBAAt
void SetRGBAAt(Geometry::Point p, Graphics::RGBA color)
Sets the color at the given location to the specified RGBA value.
Definition: Image.h:1286
Gorgon::Containers::basic_Image::GetMode
Graphics::ColorMode GetMode() const
Returns the color mode of the image.
Definition: Image.h:1311
Gorgon::Containers::basic_Image::HasAlpha
bool HasAlpha() const
Returns if this image has alpha channel.
Definition: Image.h:1331
Gorgon::Containers::basic_Image::Resize
void Resize(const Geometry::Size &size, Graphics::ColorMode mode)
Resizes the image to the given size and color mode.
Definition: Image.h:71
Gorgon::Containers::basic_Image::GetAlphaIndex
int GetAlphaIndex() const
Returns the index of alpha channel. Value of -1 denotes no alpha channel.
Definition: Image.h:1336
Gorgon::Containers::basic_Image::ImportBMP
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
Gorgon::Containers::basic_Image::alphaloc
int alphaloc
Location of the alpha channel, -1 means it does not exits.
Definition: Image.h:1354
Gorgon::Graphics::ColorMode
ColorMode
Color modes for images.
Definition: Color.h:16
Gorgon::Containers::basic_Image::operator()
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
Gorgon::Containers::swap
void swap(Collection< T_ > &l, Collection< T_ > &r)
Swaps two collections.
Definition: Collection.h:707
Gorgon::IO::WriteInt32
void WriteInt32(std::ostream &stream, long value)
Writes a 32-bit integer to the stream.
Definition: Stream.h:197
Gorgon::Graphics::ColorMode::RGB
@ RGB
24bit red, green, blue color mode that has red component in the lowest byte order
Gorgon::Graphics::ColorMode::Invalid
@ Invalid
This is used to mark invalid color data.
Gorgon::Containers::basic_Image::ExportBMP
bool ExportBMP(std::ostream &file, bool usev4=false, bool dib=false)
Exports the image as a bitmap.
Definition: Image.h:904
Gorgon::Geometry::basic_Point::X
T_ X
X coordinate.
Definition: Point.h:368
Gorgon::Containers::basic_Image::Get
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
Gorgon::Containers::basic_Image::Release
Byte * Release()
Returns and disowns the current data buffer. If image is empty, this method will return a nullptr.
Definition: Image.h:168
Gorgon::Containers::basic_Image::CopyToBGRABufferLong
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
Gorgon::Containers::basic_Image::RawData
Byte * RawData()
Returns the raw data pointer.
Definition: Image.h:211
Gorgon::Geometry::basic_Size::IsValid
bool IsValid() const
Returns whether the size is valid, i.e. both dimensions are positive.
Definition: Size.h:245
Gorgon::IO::WriteUInt16
void WriteUInt16(std::ostream &stream, unsigned value)
Writes a 16-bit unsigned integer from the stream.
Definition: Stream.h:218
Gorgon::Containers::basic_Image::ChangeMode
void ChangeMode(Graphics::ColorMode value)
Changes the color mode of the image.
Definition: Image.h:1317
Gorgon::Geometry::basic_Size::Height
T_ Height
Height of this size object.
Definition: Size.h:261
Gorgon::Geometry::basic_Bounds::Width
T_ Width() const
Calculates and returns the width of the bounds.
Definition: Bounds.h:130
Gorgon::Graphics::ColorMode::RGBA
@ RGBA
32bit red, green, blue and alpha channel image. Red component is in the lowest byte order and
Gorgon::Containers::basic_Image::operator()
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
Gorgon::Containers::basic_Image::GetAlphaAt
Byte GetAlphaAt(int x, int y) const
Returns the alpha at the given location.
Definition: Image.h:1193
Gorgon::Containers::basic_Image::basic_Image
basic_Image()
Constructs an empty image data.
Definition: Image.h:23
Gorgon::Containers::basic_Image::CopyTo
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
Gorgon::Geometry::basic_Bounds::Height
T_ Height() const
Calculates and returns the height of the bounds.
Definition: Bounds.h:135
Gorgon::Containers::basic_Image::CopyToRGBABuffer
void CopyToRGBABuffer(Byte *buffer) const
Copies this image to a RGBA buffer, buffer should be resize before calling this function.
Definition: Image.h:394
Gorgon::IO::WriteArray
void WriteArray(std::ostream &stream, const T_ *data, unsigned long size)
Writes an array to the stream.
Definition: Stream.h:294
Gorgon::Containers::basic_Image::GetWidth
int GetWidth() const
Returns the width of the image.
Definition: Image.h:1296
Gorgon::Graphics::RGBA::A
Byte A
Alpha channel.
Definition: Color.h:312
Gorgon::Containers::basic_Image::mode
Graphics::ColorMode mode
Color mode of the image.
Definition: Image.h:1348
Gorgon::Containers::basic_Image::Assume
void Assume(Byte *newdata)
Assumes the ownership of the given data.
Definition: Image.h:159
Gorgon::Containers::basic_Image::Get
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
Gorgon::IO::ReadInt32
long ReadInt32(std::istream &stream)
Reads a 32-bit integer from the stream.
Definition: Stream.h:26
Gorgon::Graphics::ColorMode::Grayscale
@ Grayscale
8bit gray scale color mode
Gorgon::Containers::basic_Image::basic_Image
basic_Image(basic_Image &&data)
Move constructor.
Definition: Image.h:39
Gorgon::Geometry::basic_Bounds::Left
T_ Left
Left-most boundary.
Definition: Bounds.h:399
Gorgon::Containers::basic_Image::GetTotalSize
unsigned long GetTotalSize() const
Total size of this image in number units.
Definition: Image.h:1306
Gorgon
Root namespace for Gorgon Game Engine.
Definition: Any.h:19
Gorgon::Geometry::basic_Size
This class represents a 2D geometric size.
Definition: Size.h:23
Gorgon::Containers::basic_Image::RawData
const Byte * RawData() const
Returns the raw data pointer.
Definition: Image.h:216
Gorgon::Containers::basic_Image::Clear
void Clear()
Cleans the contents of the buffer by setting every byte it contains to 0.
Definition: Image.h:177
Gorgon::IO::WriteUInt32
void WriteUInt32(std::ostream &stream, unsigned long value)
Writes a 32-bit unsigned integer from the stream.
Definition: Stream.h:204
Gorgon::Containers::basic_Image::Get
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
Gorgon::IO::ReadInt16
int ReadInt16(std::istream &stream)
Reads a 16-bit integer from the stream.
Definition: Stream.h:44
Gorgon::IO::ReadUInt32
unsigned long ReadUInt32(std::istream &stream)
Reads a 32-bit unsigned integer from the stream.
Definition: Stream.h:35
Gorgon::Containers::basic_Image::ImportBMP
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
Gorgon::Graphics::GetAlphaIndex
int GetAlphaIndex(ColorMode mode)
Returns the index of alpha channel. If alpha channel does not exists, this function returns -1.
Definition: Color.h:74
Gorgon::Containers::basic_Image::Destroy
void Destroy()
Destroys this image by setting width and height to 0 and freeing the memory used by its data.
Definition: Image.h:189
Gorgon::IO::ReadUInt16
unsigned ReadUInt16(std::istream &stream)
Reads a 16-bit unsigned integer from the stream.
Definition: Stream.h:53
Gorgon::Containers::basic_Image::ExportBMP
bool ExportBMP(const std::string &filename, bool usev4=false, bool dib=false)
Exports the image as a bitmap.
Definition: Image.h:893
Gorgon::Containers::basic_Image::operator()
Byte & operator()(int x, int y, unsigned component=0)
Provides access to the given component in x and y coordinates.
Definition: Image.h:1159
Gorgon::Graphics::HasAlpha
bool HasAlpha(ColorMode mode)
Returns if the given color mode has alpha channel.
Definition: Color.h:69
Gorgon::Containers::basic_Image::operator()
Byte & operator()(const Geometry::Point &p, unsigned component=0)
Provides access to the given component in x and y coordinates.
Definition: Image.h:1115
Gorgon::IO::WriteUInt8
void WriteUInt8(std::ostream &stream, Byte value)
Writes an 8-bit unsigned integer from the stream.
Definition: Stream.h:231
Gorgon::Containers::basic_Image::Duplicate
basic_Image Duplicate() const
Duplicates this image, essentially performing the work of copy constructor.
Definition: Image.h:62
Gorgon::Graphics::RGBA::Luminance
Byte Luminance() const
Returns the luminance of this color as a single byte number.
Definition: Color.h:227
Gorgon::Containers::basic_Image::basic_Image
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
Gorgon::Graphics::ColorMode::Alpha
@ Alpha
8bit alpha only color mode
Gorgon::Containers::basic_Image::Assign
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
Gorgon::Graphics::RGBA::B
Byte B
Blue channel.
Definition: Color.h:309
Gorgon::Geometry::basic_Point
This class represents a 2D point.
Definition: Point.h:32
Gorgon::Containers::basic_Image::operator=
basic_Image & operator=(basic_Image &&other)
Move assignment.
Definition: Image.h:47
Gorgon::Containers::swap
void swap(basic_Image< T_ > &l, basic_Image< T_ > &r)
Swaps two images. Should be used unqualified for ADL.
Definition: Image.h:1359
Gorgon::Containers::basic_Image::SetRGBAAt
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
Gorgon::Graphics::RGBA::G
Byte G
Green channel.
Definition: Color.h:306
Gorgon::Byte
unsigned char Byte
Represents smallest cell in memory.
Definition: Types.h:9
Gorgon::Graphics::GetChannelsPerPixel
unsigned long GetChannelsPerPixel(ColorMode mode)
Returns bytes per pixel for the given color mode.
Definition: Color.h:47
Gorgon::Geometry::basic_Bounds::Right
T_ Right
Right-most boundary.
Definition: Bounds.h:405
Gorgon::Containers::basic_Image::Assign
void Assign(Byte *newdata)
Assigns the image to the copy of the given data.
Definition: Image.h:128
Gorgon::Containers::basic_Image::CopyTo
bool CopyTo(basic_Image &dest, Geometry::Point target={0, 0}) const
Copies data from one image to another.
Definition: Image.h:318
Gorgon::Containers::basic_Image::CopyToBGRABuffer
void CopyToBGRABuffer(Byte *buffer) const
Copies this image to a RGBA buffer, buffer should be resize before calling this function.
Definition: Image.h:465
Gorgon::Geometry::basic_Bounds::Bottom
T_ Bottom
Bottom-most boundary.
Definition: Bounds.h:408
Gorgon::Geometry::basic_Size::Area
T_ Area() const
Returns the exact area of the rectangle has the size of this object.
Definition: Size.h:240
Gorgon::Containers::basic_Image
This class is a container for image data.
Definition: Image.h:19
Gorgon::Geometry::basic_Point::Y
T_ Y
Y coordinate.
Definition: Point.h:371
Gorgon::Geometry::basic_Size::Width
T_ Width
Width of this size object.
Definition: Size.h:258
Gorgon::Graphics::RGBA::R
Byte R
Red channel.
Definition: Color.h:303
Gorgon::Containers::basic_Image::Assume
void Assume(Byte *newdata, const Geometry::Size &size, Graphics::ColorMode mode)
Assumes the ownership of the given data.
Definition: Image.h:139
Gorgon::Containers::basic_Image::GetHeight
int GetHeight() const
Returns the height of the image.
Definition: Image.h:1301
Gorgon::Containers::basic_Image::Swap
void Swap(basic_Image &other)
Swaps this image with another. This function is used to implement move semantics.
Definition: Image.h:200
Gorgon::Containers::basic_Image::~basic_Image
~basic_Image()
Destructor.
Definition: Image.h:57
Gorgon::Containers::basic_Image::operator=
basic_Image & operator=(const basic_Image &)=delete
Copy assignment is disabled.
Gorgon::Containers::basic_Image::cpp
unsigned cpp
Channels per pixel information.
Definition: Image.h:1351
Gorgon::Containers::basic_Image::ConvertToRGBA
void ConvertToRGBA()
Converts this image data to RGBA buffer.
Definition: Image.h:221
Gorgon::Input::Keyboard::Keycodes::A
constexpr Key A
Definition: Keyboard.h:80
Gorgon::Containers::basic_Image::data
T_ * data
Data that stores pixels of the image.
Definition: Image.h:1342
Gorgon::Containers::basic_Image::GetRGBAAt
Graphics::RGBA GetRGBAAt(int x, int y) const
Returns the alpha at the given location.
Definition: Image.h:1207
Gorgon::Containers::basic_Image::GetSize
Geometry::Size GetSize() const
Returns the size of the image.
Definition: Image.h:1291
Gorgon::Geometry::basic_Bounds::Top
T_ Top
Top-most boundary.
Definition: Bounds.h:402
Gorgon::IO::WriteString
void WriteString(std::ostream &stream, const std::string &value)
Writes a string without its size.
Definition: Stream.h:285
Gorgon::IO::ReadUInt8
Byte ReadUInt8(std::istream &stream)
Reads an 8-bit unsigned integer from the stream.
Definition: Stream.h:71
Gorgon::Containers::basic_Image::GetChannelsPerPixel
unsigned GetChannelsPerPixel() const
Returns the number units occupied by a single pixel of this image.
Definition: Image.h:1326
Gorgon::IO::ReadString
std::string ReadString(std::istream &stream)
Reads a string from a given stream.
Definition: Stream.h:135