core.hpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. #pragma once
  2. namespace nall {
  3. inline image::image(const image& source) {
  4. operator=(source);
  5. }
  6. inline image::image(image&& source) {
  7. operator=(forward<image>(source));
  8. }
  9. inline image::image(bool endian, uint depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask) {
  10. _endian = endian;
  11. _depth = depth;
  12. _alpha = {alphaMask, bitDepth(alphaMask), bitShift(alphaMask)};
  13. _red = {redMask, bitDepth(redMask), bitShift(redMask )};
  14. _green = {greenMask, bitDepth(greenMask), bitShift(greenMask)};
  15. _blue = {blueMask, bitDepth(blueMask), bitShift(blueMask )};
  16. }
  17. inline image::image(const string& filename) {
  18. load(filename);
  19. }
  20. inline image::image(const void* data_, uint size) {
  21. auto data = (const uint8_t*)data_;
  22. if(size < 4);
  23. else if(data[0] == 'B' && data[1] == 'M') loadBMP(data, size);
  24. else if(data[1] == 'P' && data[2] == 'N' && data[3] == 'G') loadPNG(data, size);
  25. }
  26. inline image::image(const vector<uint8_t>& buffer) : image(buffer.data(), buffer.size()) {
  27. }
  28. template<uint Size> inline image::image(const uint8_t (&Name)[Size]) : image(Name, Size) {
  29. }
  30. inline image::image() {
  31. }
  32. inline image::~image() {
  33. free();
  34. }
  35. inline auto image::operator=(const image& source) -> image& {
  36. if(this == &source) return *this;
  37. free();
  38. _width = source._width;
  39. _height = source._height;
  40. _endian = source._endian;
  41. _depth = source._depth;
  42. _alpha = source._alpha;
  43. _red = source._red;
  44. _green = source._green;
  45. _blue = source._blue;
  46. _data = allocate(_width, _height, stride());
  47. memory::copy(_data, source._data, source.size());
  48. return *this;
  49. }
  50. inline auto image::operator=(image&& source) -> image& {
  51. if(this == &source) return *this;
  52. free();
  53. _width = source._width;
  54. _height = source._height;
  55. _endian = source._endian;
  56. _depth = source._depth;
  57. _alpha = source._alpha;
  58. _red = source._red;
  59. _green = source._green;
  60. _blue = source._blue;
  61. _data = source._data;
  62. source._data = nullptr;
  63. return *this;
  64. }
  65. inline image::operator bool() const {
  66. return _data && _width && _height;
  67. }
  68. inline auto image::operator==(const image& source) const -> bool {
  69. if(_width != source._width) return false;
  70. if(_height != source._height) return false;
  71. if(_endian != source._endian) return false;
  72. if(_depth != source._depth) return false;
  73. if(_alpha != source._alpha) return false;
  74. if(_red != source._red) return false;
  75. if(_green != source._green) return false;
  76. if(_blue != source._blue) return false;
  77. return memory::compare(_data, source._data, size()) == 0;
  78. }
  79. inline auto image::operator!=(const image& source) const -> bool {
  80. return !operator==(source);
  81. }
  82. inline auto image::read(const uint8_t* data) const -> uint64_t {
  83. uint64_t result = 0;
  84. if(_endian == 0) {
  85. for(int n = stride() - 1; n >= 0; n--) result = (result << 8) | data[n];
  86. } else {
  87. for(int n = 0; n < stride(); n++) result = (result << 8) | data[n];
  88. }
  89. return result;
  90. }
  91. inline auto image::write(uint8_t* data, uint64_t value) const -> void {
  92. if(_endian == 0) {
  93. for(int n = 0; n < stride(); n++) {
  94. data[n] = value;
  95. value >>= 8;
  96. }
  97. } else {
  98. for(int n = stride() - 1; n >= 0; n--) {
  99. data[n] = value;
  100. value >>= 8;
  101. }
  102. }
  103. }
  104. inline auto image::free() -> void {
  105. if(_data) delete[] _data;
  106. _data = nullptr;
  107. }
  108. inline auto image::load(const string& filename) -> bool {
  109. if(loadBMP(filename) == true) return true;
  110. if(loadPNG(filename) == true) return true;
  111. return false;
  112. }
  113. //assumes image and data are in the same format; pitch is adapted to image
  114. inline auto image::copy(const void* data, uint pitch, uint width, uint height) -> void {
  115. allocate(width, height);
  116. for(uint y : range(height)) {
  117. auto input = (const uint8_t*)data + y * pitch;
  118. auto output = (uint8_t*)_data + y * this->pitch();
  119. memory::copy(output, input, width * stride());
  120. }
  121. }
  122. inline auto image::allocate(uint width, uint height) -> void {
  123. if(_data && _width == width && _height == height) return;
  124. free();
  125. _width = width;
  126. _height = height;
  127. _data = allocate(_width, _height, stride());
  128. }
  129. //private
  130. inline auto image::allocate(uint width, uint height, uint stride) -> uint8_t* {
  131. //allocate 1x1 larger than requested; so that linear interpolation does not require bounds-checking
  132. uint size = width * height * stride;
  133. uint padding = width * stride + stride;
  134. auto data = new uint8_t[size + padding];
  135. memory::fill(data + size, padding);
  136. return data;
  137. }
  138. }