test_image.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. /**************************************************************************/
  2. /* test_image.h */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #pragma once
  31. #include "core/io/image.h"
  32. #include "core/os/os.h"
  33. #include "tests/test_utils.h"
  34. #include "modules/modules_enabled.gen.h"
  35. #include "thirdparty/doctest/doctest.h"
  36. namespace TestImage {
  37. TEST_CASE("[Image] Instantiation") {
  38. Ref<Image> image = memnew(Image(8, 4, false, Image::FORMAT_RGBA8));
  39. CHECK_MESSAGE(
  40. !image->is_empty(),
  41. "An image created with specified size and format should not be empty at first.");
  42. CHECK_MESSAGE(
  43. image->is_invisible(),
  44. "A newly created image should be invisible.");
  45. CHECK_MESSAGE(
  46. !image->is_compressed(),
  47. "A newly created image should not be compressed.");
  48. CHECK(!image->has_mipmaps());
  49. PackedByteArray image_data = image->get_data();
  50. for (int i = 0; i < image_data.size(); i++) {
  51. CHECK_MESSAGE(
  52. image_data[i] == 0,
  53. "An image created without data specified should have its data zeroed out.");
  54. }
  55. Ref<Image> image_copy = memnew(Image());
  56. CHECK_MESSAGE(
  57. image_copy->is_empty(),
  58. "An image created without any specified size and format be empty at first.");
  59. image_copy->copy_internals_from(image);
  60. CHECK_MESSAGE(
  61. image->get_data() == image_copy->get_data(),
  62. "Duplicated images should have the same data.");
  63. image_data = image->get_data();
  64. Ref<Image> image_from_data = memnew(Image(8, 4, false, Image::FORMAT_RGBA8, image_data));
  65. CHECK_MESSAGE(
  66. image->get_data() == image_from_data->get_data(),
  67. "An image created from data of another image should have the same data of the original image.");
  68. }
  69. TEST_CASE("[Image] Saving and loading") {
  70. Ref<Image> image = memnew(Image(4, 4, false, Image::FORMAT_RGBA8));
  71. const String save_path_png = TestUtils::get_temp_path("image.png");
  72. const String save_path_exr = TestUtils::get_temp_path("image.exr");
  73. // Save PNG
  74. Error err;
  75. err = image->save_png(save_path_png);
  76. CHECK_MESSAGE(
  77. err == OK,
  78. "The image should be saved successfully as a .png file.");
  79. // Only available on editor builds.
  80. #ifdef TOOLS_ENABLED
  81. // Save EXR
  82. err = image->save_exr(save_path_exr, false);
  83. CHECK_MESSAGE(
  84. err == OK,
  85. "The image should be saved successfully as an .exr file.");
  86. #endif // TOOLS_ENABLED
  87. // Load using load()
  88. Ref<Image> image_load = memnew(Image());
  89. err = image_load->load(save_path_png);
  90. CHECK_MESSAGE(
  91. err == OK,
  92. "The image should load successfully using load().");
  93. CHECK_MESSAGE(
  94. image->get_data() == image_load->get_data(),
  95. "The loaded image should have the same data as the one that got saved.");
  96. #ifdef MODULE_BMP_ENABLED
  97. // Load BMP
  98. Ref<Image> image_bmp = memnew(Image());
  99. Ref<FileAccess> f_bmp = FileAccess::open(TestUtils::get_data_path("images/icon.bmp"), FileAccess::READ, &err);
  100. REQUIRE(f_bmp.is_valid());
  101. PackedByteArray data_bmp;
  102. data_bmp.resize(f_bmp->get_length() + 1);
  103. f_bmp->get_buffer(data_bmp.ptrw(), f_bmp->get_length());
  104. CHECK_MESSAGE(
  105. image_bmp->load_bmp_from_buffer(data_bmp) == OK,
  106. "The BMP image should load successfully.");
  107. #endif // MODULE_BMP_ENABLED
  108. #ifdef MODULE_JPG_ENABLED
  109. // Load JPG
  110. Ref<Image> image_jpg = memnew(Image());
  111. Ref<FileAccess> f_jpg = FileAccess::open(TestUtils::get_data_path("images/icon.jpg"), FileAccess::READ, &err);
  112. REQUIRE(f_jpg.is_valid());
  113. PackedByteArray data_jpg;
  114. data_jpg.resize(f_jpg->get_length() + 1);
  115. f_jpg->get_buffer(data_jpg.ptrw(), f_jpg->get_length());
  116. CHECK_MESSAGE(
  117. image_jpg->load_jpg_from_buffer(data_jpg) == OK,
  118. "The JPG image should load successfully.");
  119. Ref<Image> image_grayscale_jpg = memnew(Image());
  120. Ref<FileAccess> f_grayscale_jpg = FileAccess::open(TestUtils::get_data_path("images/grayscale.jpg"), FileAccess::READ, &err);
  121. REQUIRE(f_grayscale_jpg.is_valid());
  122. PackedByteArray data_grayscale_jpg;
  123. data_grayscale_jpg.resize(f_grayscale_jpg->get_length() + 1);
  124. f_grayscale_jpg->get_buffer(data_grayscale_jpg.ptrw(), f_grayscale_jpg->get_length());
  125. CHECK_MESSAGE(
  126. image_jpg->load_jpg_from_buffer(data_grayscale_jpg) == OK,
  127. "The grayscale JPG image should load successfully.");
  128. // Save JPG
  129. const String save_path_jpg = TestUtils::get_temp_path("image.jpg");
  130. CHECK_MESSAGE(image->save_jpg(save_path_jpg) == OK,
  131. "The image should be saved successfully as a .jpg file.");
  132. #ifdef MODULE_SVG_ENABLED
  133. // Load SVG with embedded jpg image
  134. Ref<Image> image_svg = memnew(Image());
  135. Ref<FileAccess> f_svg = FileAccess::open(TestUtils::get_data_path("images/embedded_jpg.svg"), FileAccess::READ, &err);
  136. REQUIRE(f_svg.is_valid());
  137. PackedByteArray data_svg;
  138. data_svg.resize(f_svg->get_length() + 1);
  139. f_svg->get_buffer(data_svg.ptrw(), f_svg->get_length());
  140. CHECK_MESSAGE(
  141. image_svg->load_svg_from_buffer(data_svg) == OK,
  142. "The SVG image should load successfully.");
  143. #endif // MODULE_SVG_ENABLED
  144. #endif // MODULE_JPG_ENABLED
  145. #ifdef MODULE_WEBP_ENABLED
  146. // Load WebP
  147. Ref<Image> image_webp = memnew(Image());
  148. Ref<FileAccess> f_webp = FileAccess::open(TestUtils::get_data_path("images/icon.webp"), FileAccess::READ, &err);
  149. REQUIRE(f_webp.is_valid());
  150. PackedByteArray data_webp;
  151. data_webp.resize(f_webp->get_length() + 1);
  152. f_webp->get_buffer(data_webp.ptrw(), f_webp->get_length());
  153. CHECK_MESSAGE(
  154. image_webp->load_webp_from_buffer(data_webp) == OK,
  155. "The WebP image should load successfully.");
  156. #endif // MODULE_WEBP_ENABLED
  157. // Load PNG
  158. Ref<Image> image_png = memnew(Image());
  159. Ref<FileAccess> f_png = FileAccess::open(TestUtils::get_data_path("images/icon.png"), FileAccess::READ, &err);
  160. REQUIRE(f_png.is_valid());
  161. PackedByteArray data_png;
  162. data_png.resize(f_png->get_length() + 1);
  163. f_png->get_buffer(data_png.ptrw(), f_png->get_length());
  164. CHECK_MESSAGE(
  165. image_png->load_png_from_buffer(data_png) == OK,
  166. "The PNG image should load successfully.");
  167. #ifdef MODULE_TGA_ENABLED
  168. // Load TGA
  169. Ref<Image> image_tga = memnew(Image());
  170. Ref<FileAccess> f_tga = FileAccess::open(TestUtils::get_data_path("images/icon.tga"), FileAccess::READ, &err);
  171. REQUIRE(f_tga.is_valid());
  172. PackedByteArray data_tga;
  173. data_tga.resize(f_tga->get_length() + 1);
  174. f_tga->get_buffer(data_tga.ptrw(), f_tga->get_length());
  175. CHECK_MESSAGE(
  176. image_tga->load_tga_from_buffer(data_tga) == OK,
  177. "The TGA image should load successfully.");
  178. #endif // MODULE_TGA_ENABLED
  179. }
  180. TEST_CASE("[Image] Basic getters") {
  181. Ref<Image> image = memnew(Image(8, 4, false, Image::FORMAT_LA8));
  182. CHECK(image->get_width() == 8);
  183. CHECK(image->get_height() == 4);
  184. CHECK(image->get_size() == Vector2(8, 4));
  185. CHECK(image->get_format() == Image::FORMAT_LA8);
  186. CHECK(image->get_used_rect() == Rect2i(0, 0, 0, 0));
  187. Ref<Image> image_get_rect = image->get_region(Rect2i(0, 0, 2, 1));
  188. CHECK(image_get_rect->get_size() == Vector2(2, 1));
  189. }
  190. TEST_CASE("[Image] Resizing") {
  191. Ref<Image> image = memnew(Image(8, 8, false, Image::FORMAT_RGBA8));
  192. // Crop
  193. image->crop(4, 4);
  194. CHECK_MESSAGE(
  195. image->get_size() == Vector2(4, 4),
  196. "get_size() should return the correct size after cropping.");
  197. image->set_pixel(0, 0, Color(1, 1, 1, 1));
  198. // Resize
  199. for (int i = 0; i < 5; i++) {
  200. Ref<Image> image_resized = memnew(Image());
  201. image_resized->copy_internals_from(image);
  202. Image::Interpolation interpolation = static_cast<Image::Interpolation>(i);
  203. image_resized->resize(8, 8, interpolation);
  204. CHECK_MESSAGE(
  205. image_resized->get_size() == Vector2(8, 8),
  206. "get_size() should return the correct size after resizing.");
  207. CHECK_MESSAGE(
  208. image_resized->get_pixel(1, 1).a > 0,
  209. "Resizing an image should also affect its content.");
  210. }
  211. // shrink_x2()
  212. image->shrink_x2();
  213. CHECK_MESSAGE(
  214. image->get_size() == Vector2(2, 2),
  215. "get_size() should return the correct size after shrink_x2().");
  216. // resize_to_po2()
  217. Ref<Image> image_po_2 = memnew(Image(14, 28, false, Image::FORMAT_RGBA8));
  218. image_po_2->resize_to_po2();
  219. CHECK_MESSAGE(
  220. image_po_2->get_size() == Vector2(16, 32),
  221. "get_size() should return the correct size after resize_to_po2().");
  222. }
  223. TEST_CASE("[Image] Modifying pixels of an image") {
  224. Ref<Image> image = memnew(Image(3, 3, false, Image::FORMAT_RGBA8));
  225. image->set_pixel(0, 0, Color(1, 1, 1, 1));
  226. CHECK_MESSAGE(
  227. !image->is_invisible(),
  228. "Image should not be invisible after drawing on it.");
  229. CHECK_MESSAGE(
  230. image->get_pixelv(Vector2(0, 0)).is_equal_approx(Color(1, 1, 1, 1)),
  231. "Image's get_pixel() should return the same color value as the one being set with set_pixel() in the same position.");
  232. CHECK_MESSAGE(
  233. image->get_used_rect() == Rect2i(0, 0, 1, 1),
  234. "Image's get_used_rect should return the expected value, larger than Rect2i(0, 0, 0, 0) if it's visible.");
  235. image->set_pixelv(Vector2(0, 0), Color(0.5, 0.5, 0.5, 0.5));
  236. Ref<Image> image2 = memnew(Image(3, 3, false, Image::FORMAT_RGBA8));
  237. // Fill image with color
  238. image2->fill(Color(0.5, 0.5, 0.5, 0.5));
  239. for (int y = 0; y < image2->get_height(); y++) {
  240. for (int x = 0; x < image2->get_width(); x++) {
  241. CHECK_MESSAGE(
  242. image2->get_pixel(x, y).r > 0.49,
  243. "fill() should colorize all pixels of the image.");
  244. }
  245. }
  246. // Fill rect with color
  247. {
  248. const int img_width = 3;
  249. const int img_height = 3;
  250. Vector<Rect2i> rects;
  251. rects.push_back(Rect2i());
  252. rects.push_back(Rect2i(-5, -5, 3, 3));
  253. rects.push_back(Rect2i(img_width, 0, 12, 12));
  254. rects.push_back(Rect2i(0, img_height, 12, 12));
  255. rects.push_back(Rect2i(img_width + 1, img_height + 2, 12, 12));
  256. rects.push_back(Rect2i(1, 1, 1, 1));
  257. rects.push_back(Rect2i(0, 1, 2, 3));
  258. rects.push_back(Rect2i(-5, 0, img_width + 10, 2));
  259. rects.push_back(Rect2i(0, -5, 2, img_height + 10));
  260. rects.push_back(Rect2i(-1, -1, img_width + 1, img_height + 1));
  261. for (const Rect2i &rect : rects) {
  262. Ref<Image> img = memnew(Image(img_width, img_height, false, Image::FORMAT_RGBA8));
  263. img->fill_rect(rect, Color(1, 1, 1, 1));
  264. for (int y = 0; y < img->get_height(); y++) {
  265. for (int x = 0; x < img->get_width(); x++) {
  266. if (rect.abs().has_point(Point2(x, y))) {
  267. CHECK_MESSAGE(
  268. img->get_pixel(x, y).is_equal_approx(Color(1, 1, 1, 1)),
  269. "fill_rect() should colorize all image pixels within rect bounds.");
  270. } else {
  271. CHECK_MESSAGE(
  272. !img->get_pixel(x, y).is_equal_approx(Color(1, 1, 1, 1)),
  273. "fill_rect() shouldn't colorize any image pixel out of rect bounds.");
  274. }
  275. }
  276. }
  277. }
  278. }
  279. // Blend two images together
  280. image->blend_rect(image2, Rect2i(Vector2i(0, 0), image2->get_size()), Vector2i(0, 0));
  281. CHECK_MESSAGE(
  282. image->get_pixel(0, 0).a > 0.7,
  283. "blend_rect() should blend the alpha values of the two images.");
  284. CHECK_MESSAGE(
  285. image->get_used_rect().size == image->get_size(),
  286. "get_used_rect() should return the expected value, its Rect size should be the same as get_size() if there are no transparent pixels.");
  287. Ref<Image> image3 = memnew(Image(2, 2, false, Image::FORMAT_RGBA8));
  288. image3->set_pixel(0, 0, Color(0, 1, 0, 1));
  289. //blit_rect() two images together
  290. image->blit_rect(image3, Rect2i(Vector2i(0, 0), image3->get_size()), Vector2i(0, 0));
  291. CHECK_MESSAGE(
  292. image->get_pixel(0, 0).is_equal_approx(Color(0, 1, 0, 1)),
  293. "blit_rect() should replace old colors and not blend them.");
  294. CHECK_MESSAGE(
  295. !image->get_pixel(2, 2).is_equal_approx(Color(0, 1, 0, 1)),
  296. "blit_rect() should not affect the area of the image that is outside src_rect.");
  297. // Flip image
  298. image3->flip_x();
  299. CHECK(image3->get_pixel(1, 0).is_equal_approx(Color(0, 1, 0, 1)));
  300. CHECK_MESSAGE(
  301. image3->get_pixel(0, 0).is_equal_approx(Color(0, 0, 0, 0)),
  302. "flip_x() should not leave old pixels behind.");
  303. image3->flip_y();
  304. CHECK(image3->get_pixel(1, 1).is_equal_approx(Color(0, 1, 0, 1)));
  305. CHECK_MESSAGE(
  306. image3->get_pixel(1, 0).is_equal_approx(Color(0, 0, 0, 0)),
  307. "flip_y() should not leave old pixels behind.");
  308. // Pre-multiply Alpha then Convert from RGBA to L8, checking alpha
  309. {
  310. Ref<Image> gray_image = memnew(Image(3, 3, false, Image::FORMAT_RGBA8));
  311. gray_image->fill_rect(Rect2i(0, 0, 3, 3), Color(1, 1, 1, 0));
  312. gray_image->set_pixel(1, 1, Color(1, 1, 1, 1));
  313. gray_image->set_pixel(1, 2, Color(0.5, 0.5, 0.5, 0.5));
  314. gray_image->set_pixel(2, 1, Color(0.25, 0.05, 0.5, 1.0));
  315. gray_image->set_pixel(2, 2, Color(0.5, 0.25, 0.95, 0.75));
  316. gray_image->premultiply_alpha();
  317. gray_image->convert(Image::FORMAT_L8);
  318. CHECK_MESSAGE(gray_image->get_pixel(0, 0).is_equal_approx(Color(0, 0, 0, 1)), "convert() RGBA to L8 should be black.");
  319. CHECK_MESSAGE(gray_image->get_pixel(0, 1).is_equal_approx(Color(0, 0, 0, 1)), "convert() RGBA to L8 should be black.");
  320. CHECK_MESSAGE(gray_image->get_pixel(0, 2).is_equal_approx(Color(0, 0, 0, 1)), "convert() RGBA to L8 should be black.");
  321. CHECK_MESSAGE(gray_image->get_pixel(1, 0).is_equal_approx(Color(0, 0, 0, 1)), "convert() RGBA to L8 should be black.");
  322. CHECK_MESSAGE(gray_image->get_pixel(1, 1).is_equal_approx(Color(1, 1, 1, 1)), "convert() RGBA to L8 should be white.");
  323. CHECK_MESSAGE(gray_image->get_pixel(1, 2).is_equal_approx(Color(0.250980407, 0.250980407, 0.250980407, 1)), "convert() RGBA to L8 should be around 0.250980407 (64).");
  324. CHECK_MESSAGE(gray_image->get_pixel(2, 0).is_equal_approx(Color(0, 0, 0, 1)), "convert() RGBA to L8 should be black.");
  325. CHECK_MESSAGE(gray_image->get_pixel(2, 1).is_equal_approx(Color(0.121568628, 0.121568628, 0.121568628, 1)), "convert() RGBA to L8 should be around 0.121568628 (31).");
  326. CHECK_MESSAGE(gray_image->get_pixel(2, 2).is_equal_approx(Color(0.266666681, 0.266666681, 0.266666681, 1)), "convert() RGBA to L8 should be around 0.266666681 (68).");
  327. }
  328. }
  329. TEST_CASE("[Image] Custom mipmaps") {
  330. Ref<Image> image = memnew(Image(100, 100, false, Image::FORMAT_RGBA8));
  331. REQUIRE(!image->has_mipmaps());
  332. image->generate_mipmaps();
  333. REQUIRE(image->has_mipmaps());
  334. const int mipmaps = image->get_mipmap_count() + 1;
  335. REQUIRE(mipmaps == 7);
  336. // Initialize reference mipmap data.
  337. // Each byte is given value "mipmap_index * 5".
  338. {
  339. PackedByteArray data = image->get_data();
  340. uint8_t *data_ptr = data.ptrw();
  341. for (int mip = 0; mip < mipmaps; mip++) {
  342. int64_t mip_offset = 0;
  343. int64_t mip_size = 0;
  344. image->get_mipmap_offset_and_size(mip, mip_offset, mip_size);
  345. for (int i = 0; i < mip_size; i++) {
  346. data_ptr[mip_offset + i] = mip * 5;
  347. }
  348. }
  349. image->set_data(image->get_width(), image->get_height(), image->has_mipmaps(), image->get_format(), data);
  350. }
  351. // Byte format conversion.
  352. for (int format = Image::FORMAT_L8; format <= Image::FORMAT_RGBA8; format++) {
  353. Ref<Image> image_bytes = memnew(Image());
  354. image_bytes->copy_internals_from(image);
  355. image_bytes->convert((Image::Format)format);
  356. REQUIRE(image_bytes->has_mipmaps());
  357. PackedByteArray data = image_bytes->get_data();
  358. const uint8_t *data_ptr = data.ptr();
  359. for (int mip = 0; mip < mipmaps; mip++) {
  360. int64_t mip_offset = 0;
  361. int64_t mip_size = 0;
  362. image_bytes->get_mipmap_offset_and_size(mip, mip_offset, mip_size);
  363. for (int i = 0; i < mip_size; i++) {
  364. if (data_ptr[mip_offset + i] != mip * 5) {
  365. REQUIRE_MESSAGE(false, "Byte format conversion error.");
  366. }
  367. }
  368. }
  369. }
  370. // Floating point format conversion.
  371. for (int format = Image::FORMAT_RF; format <= Image::FORMAT_RGBAF; format++) {
  372. Ref<Image> image_rgbaf = memnew(Image());
  373. image_rgbaf->copy_internals_from(image);
  374. image_rgbaf->convert((Image::Format)format);
  375. REQUIRE(image_rgbaf->has_mipmaps());
  376. PackedByteArray data = image_rgbaf->get_data();
  377. const uint8_t *data_ptr = data.ptr();
  378. for (int mip = 0; mip < mipmaps; mip++) {
  379. int64_t mip_offset = 0;
  380. int64_t mip_size = 0;
  381. image_rgbaf->get_mipmap_offset_and_size(mip, mip_offset, mip_size);
  382. for (int i = 0; i < mip_size; i += 4) {
  383. float value = *(float *)(data_ptr + mip_offset + i);
  384. if (!Math::is_equal_approx(value * 255.0f, mip * 5)) {
  385. REQUIRE_MESSAGE(false, "Floating point conversion error.");
  386. }
  387. }
  388. }
  389. }
  390. }
  391. TEST_CASE("[Image] Convert image") {
  392. for (int format = Image::FORMAT_RF; format < Image::FORMAT_RGBE9995; format++) {
  393. for (int new_format = Image::FORMAT_RF; new_format < Image::FORMAT_RGBE9995; new_format++) {
  394. Ref<Image> image = memnew(Image(4, 4, false, (Image::Format)format));
  395. image->convert((Image::Format)new_format);
  396. String format_string = Image::format_names[(Image::Format)format];
  397. String new_format_string = Image::format_names[(Image::Format)new_format];
  398. format_string = "Error converting from " + format_string + " to " + new_format_string + ".";
  399. CHECK_MESSAGE(image->get_format() == new_format, format_string);
  400. }
  401. }
  402. Ref<Image> image = memnew(Image(4, 4, false, Image::FORMAT_RGBA8));
  403. PackedByteArray image_data = image->get_data();
  404. ERR_PRINT_OFF;
  405. image->convert((Image::Format)-1);
  406. ERR_PRINT_ON;
  407. CHECK_MESSAGE(image->get_data() == image_data, "Image conversion to invalid type (-1) should not alter image.");
  408. Ref<Image> image2 = memnew(Image(4, 4, false, Image::FORMAT_RGBA8));
  409. image_data = image2->get_data();
  410. ERR_PRINT_OFF;
  411. image2->convert((Image::Format)(Image::FORMAT_MAX + 1));
  412. ERR_PRINT_ON;
  413. CHECK_MESSAGE(image2->get_data() == image_data, "Image conversion to invalid type (Image::FORMAT_MAX + 1) should not alter image.");
  414. }
  415. } // namespace TestImage