PersistentImage.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. // zlib open source license
  2. //
  3. // Copyright (c) 2021 David Forsgren Piuva
  4. //
  5. // This software is provided 'as-is', without any express or implied
  6. // warranty. In no event will the authors be held liable for any damages
  7. // arising from the use of this software.
  8. //
  9. // Permission is granted to anyone to use this software for any purpose,
  10. // including commercial applications, and to alter it and redistribute it
  11. // freely, subject to the following restrictions:
  12. //
  13. // 1. The origin of this software must not be misrepresented; you must not
  14. // claim that you wrote the original software. If you use this software
  15. // in a product, an acknowledgment in the product documentation would be
  16. // appreciated but is not required.
  17. //
  18. // 2. Altered source versions must be plainly marked as such, and must not be
  19. // misrepresented as being the original software.
  20. //
  21. // 3. This notice may not be removed or altered from any source
  22. // distribution.
  23. #include "PersistentImage.h"
  24. #include "../../../api/fileAPI.h"
  25. using namespace dsr;
  26. PERSISTENT_DEFINITION(PersistentImage)
  27. static uint8_t readHexaDecimal(const ReadableString &text, int &readFrom) {
  28. uint8_t result = 0u;
  29. for (int i = 0; i < 2; i++) {
  30. result = result << 4;
  31. DsrChar c = text[readFrom];
  32. if (U'0' <= c && c <= U'9') {
  33. result = result | (c - U'0');
  34. } else if (U'a' <= c && c <= U'f') {
  35. result = result | (c - U'a' + 10);
  36. } else if (U'A' <= c && c <= U'F') {
  37. result = result | (c - U'A' + 10);
  38. }
  39. readFrom++;
  40. }
  41. return result;
  42. }
  43. bool PersistentImage::assignValue(const ReadableString &text, const ReadableString &fromPath) {
  44. if (string_caseInsensitiveMatch(text, U"NONE")) {
  45. // Set the handle to null
  46. this->value = OrderedImageRgbaU8();
  47. } else {
  48. // Create an image from the text
  49. int colonIndex = string_findFirst(text, U':');
  50. if (colonIndex == -1) {
  51. printText("Missing colon when creating PersistentImage from text!\n");
  52. return false;
  53. }
  54. ReadableString leftSide = string_before(text, colonIndex);
  55. if (string_caseInsensitiveMatch(leftSide, U"FILE")) {
  56. // Read image from the file path
  57. String absolutePath = file_getTheoreticalAbsolutePath(string_after(text, colonIndex), fromPath);
  58. this->value = image_load_RgbaU8(absolutePath);
  59. } else {
  60. // Read dimensions and a sequence of pixels as hexadecimals
  61. int xIndex = string_findFirst(text, U'x');
  62. if (xIndex == -1 || xIndex > colonIndex) {
  63. printText("Missing x when parsing embedded PersistentImage from text!\n");
  64. return false;
  65. }
  66. int width = string_toInteger(string_before(leftSide, xIndex));
  67. int height = string_toInteger(string_after(leftSide, xIndex));
  68. if (width <= 0 || height <= 0) {
  69. // No pixels found
  70. this->value = OrderedImageRgbaU8();
  71. } else {
  72. this->value = image_create_RgbaU8(width, height);
  73. int readIndex = colonIndex + 1;
  74. for (int y = 0; y < height; y++) {
  75. for (int x = 0; x < width; x++) {
  76. int red = readHexaDecimal(text, readIndex);
  77. int green = readHexaDecimal(text, readIndex);
  78. int blue = readHexaDecimal(text, readIndex);
  79. int alpha = readHexaDecimal(text, readIndex);
  80. image_writePixel(this->value, x, y, ColorRgbaI32(red, green, blue, alpha));
  81. }
  82. }
  83. }
  84. }
  85. }
  86. return true;
  87. }
  88. static const String hexadecimals = U"0123456789ABCDEF";
  89. static void writeHexaDecimal(String &out, uint8_t value) {
  90. string_appendChar(out, hexadecimals[(value & 0b11110000) >> 4]);
  91. string_appendChar(out, hexadecimals[value & 0b00001111]);
  92. }
  93. String& PersistentImage::toStreamIndented(String &out, const ReadableString &indentation) const {
  94. string_append(out, indentation);
  95. if (string_length(this->path)) {
  96. string_append(out, "File:", this->path);
  97. } else if (image_exists(this->value)) {
  98. int width = image_getWidth(this->value);
  99. int height = image_getHeight(this->value);
  100. string_append(out, width, U"x", height, U":");
  101. for (int y = 0; y < height; y++) {
  102. for (int x = 0; x < width; x++) {
  103. ColorRgbaI32 color = image_readPixel_clamp(this->value, x, y);
  104. writeHexaDecimal(out, color.red);
  105. writeHexaDecimal(out, color.green);
  106. writeHexaDecimal(out, color.blue);
  107. writeHexaDecimal(out, color.alpha);
  108. }
  109. }
  110. } else {
  111. string_append(out, U"None");
  112. }
  113. return out;
  114. }