Bitmap.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. /*
  2. * Copyright (c) 2018-2024, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2022, Timothy Slater <tslater2006@gmail.com>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/Bitmap.h>
  8. #include <AK/ByteString.h>
  9. #include <AK/Checked.h>
  10. #include <AK/LexicalPath.h>
  11. #include <AK/Memory.h>
  12. #include <AK/MemoryStream.h>
  13. #include <LibCore/File.h>
  14. #include <LibCore/MappedFile.h>
  15. #include <LibCore/MimeData.h>
  16. #include <LibGfx/Bitmap.h>
  17. #include <LibGfx/ImageFormats/ImageDecoder.h>
  18. #include <LibGfx/ShareableBitmap.h>
  19. #include <errno.h>
  20. namespace Gfx {
  21. struct BackingStore {
  22. void* data { nullptr };
  23. size_t pitch { 0 };
  24. size_t size_in_bytes { 0 };
  25. };
  26. size_t Bitmap::minimum_pitch(size_t width, BitmapFormat format)
  27. {
  28. size_t element_size;
  29. switch (determine_storage_format(format)) {
  30. case StorageFormat::BGRx8888:
  31. case StorageFormat::BGRA8888:
  32. case StorageFormat::RGBA8888:
  33. element_size = 4;
  34. break;
  35. default:
  36. VERIFY_NOT_REACHED();
  37. }
  38. return width * element_size;
  39. }
  40. static bool size_would_overflow(BitmapFormat format, IntSize size)
  41. {
  42. if (size.width() < 0 || size.height() < 0)
  43. return true;
  44. // This check is a bit arbitrary, but should protect us from most shenanigans:
  45. if (size.width() >= INT16_MAX || size.height() >= INT16_MAX)
  46. return true;
  47. // In contrast, this check is absolutely necessary:
  48. size_t pitch = Bitmap::minimum_pitch(size.width(), format);
  49. return Checked<size_t>::multiplication_would_overflow(pitch, size.height());
  50. }
  51. ErrorOr<NonnullRefPtr<Bitmap>> Bitmap::create(BitmapFormat format, IntSize size)
  52. {
  53. auto backing_store = TRY(Bitmap::allocate_backing_store(format, size));
  54. return AK::adopt_nonnull_ref_or_enomem(new (nothrow) Bitmap(format, size, backing_store));
  55. }
  56. ErrorOr<NonnullRefPtr<Bitmap>> Bitmap::create_shareable(BitmapFormat format, IntSize size)
  57. {
  58. if (size_would_overflow(format, size))
  59. return Error::from_string_literal("Gfx::Bitmap::create_shareable size overflow");
  60. auto const pitch = minimum_pitch(size.width(), format);
  61. auto const data_size = size_in_bytes(pitch, size.height());
  62. auto buffer = TRY(Core::AnonymousBuffer::create_with_size(round_up_to_power_of_two(data_size, PAGE_SIZE)));
  63. auto bitmap = TRY(Bitmap::create_with_anonymous_buffer(format, buffer, size));
  64. return bitmap;
  65. }
  66. Bitmap::Bitmap(BitmapFormat format, IntSize size, BackingStore const& backing_store)
  67. : m_size(size)
  68. , m_data(backing_store.data)
  69. , m_pitch(backing_store.pitch)
  70. , m_format(format)
  71. {
  72. VERIFY(!m_size.is_empty());
  73. VERIFY(!size_would_overflow(format, size));
  74. VERIFY(m_data);
  75. VERIFY(backing_store.size_in_bytes == size_in_bytes());
  76. m_destruction_callback = [data = m_data, size_in_bytes = this->size_in_bytes()] {
  77. kfree_sized(data, size_in_bytes);
  78. };
  79. }
  80. ErrorOr<NonnullRefPtr<Bitmap>> Bitmap::create_wrapper(BitmapFormat format, IntSize size, size_t pitch, void* data, Function<void()>&& destruction_callback)
  81. {
  82. if (size_would_overflow(format, size))
  83. return Error::from_string_literal("Gfx::Bitmap::create_wrapper size overflow");
  84. return adopt_ref(*new Bitmap(format, size, pitch, data, move(destruction_callback)));
  85. }
  86. ErrorOr<NonnullRefPtr<Bitmap>> Bitmap::load_from_file(StringView path, Optional<IntSize> ideal_size)
  87. {
  88. auto file = TRY(Core::File::open(path, Core::File::OpenMode::Read));
  89. return load_from_file(move(file), path, ideal_size);
  90. }
  91. ErrorOr<NonnullRefPtr<Bitmap>> Bitmap::load_from_file(NonnullOwnPtr<Core::File> file, StringView path, Optional<IntSize> ideal_size)
  92. {
  93. auto mapped_file = TRY(Core::MappedFile::map_from_file(move(file), path));
  94. auto mime_type = Core::guess_mime_type_based_on_filename(path);
  95. return load_from_bytes(mapped_file->bytes(), ideal_size, mime_type);
  96. }
  97. ErrorOr<NonnullRefPtr<Bitmap>> Bitmap::load_from_bytes(ReadonlyBytes bytes, Optional<IntSize> ideal_size, Optional<ByteString> mine_type)
  98. {
  99. if (auto decoder = TRY(ImageDecoder::try_create_for_raw_bytes(bytes, mine_type))) {
  100. auto frame = TRY(decoder->frame(0, ideal_size));
  101. if (auto& bitmap = frame.image)
  102. return bitmap.release_nonnull();
  103. }
  104. return Error::from_string_literal("Gfx::Bitmap unable to load from file");
  105. }
  106. Bitmap::Bitmap(BitmapFormat format, IntSize size, size_t pitch, void* data, Function<void()>&& destruction_callback)
  107. : m_size(size)
  108. , m_data(data)
  109. , m_pitch(pitch)
  110. , m_format(format)
  111. , m_destruction_callback(move(destruction_callback))
  112. {
  113. VERIFY(pitch >= minimum_pitch(size.width(), format));
  114. VERIFY(!size_would_overflow(format, size));
  115. // FIXME: assert that `data` is actually long enough!
  116. }
  117. ErrorOr<NonnullRefPtr<Bitmap>> Bitmap::create_with_anonymous_buffer(BitmapFormat format, Core::AnonymousBuffer buffer, IntSize size)
  118. {
  119. if (size_would_overflow(format, size))
  120. return Error::from_string_literal("Gfx::Bitmap::create_with_anonymous_buffer size overflow");
  121. return adopt_nonnull_ref_or_enomem(new (nothrow) Bitmap(format, move(buffer), size));
  122. }
  123. Bitmap::Bitmap(BitmapFormat format, Core::AnonymousBuffer buffer, IntSize size)
  124. : m_size(size)
  125. , m_data(buffer.data<void>())
  126. , m_pitch(minimum_pitch(size.width(), format))
  127. , m_format(format)
  128. , m_buffer(move(buffer))
  129. {
  130. VERIFY(!size_would_overflow(format, size));
  131. }
  132. ErrorOr<NonnullRefPtr<Gfx::Bitmap>> Bitmap::clone() const
  133. {
  134. auto new_bitmap = TRY(Bitmap::create(format(), size()));
  135. VERIFY(size_in_bytes() == new_bitmap->size_in_bytes());
  136. memcpy(new_bitmap->scanline(0), scanline(0), size_in_bytes());
  137. return new_bitmap;
  138. }
  139. void Bitmap::apply_mask(Gfx::Bitmap const& mask, MaskKind mask_kind)
  140. {
  141. VERIFY(size() == mask.size());
  142. for (int y = 0; y < height(); y++) {
  143. for (int x = 0; x < width(); x++) {
  144. auto color = get_pixel(x, y);
  145. auto mask_color = mask.get_pixel(x, y);
  146. if (mask_kind == MaskKind::Luminance) {
  147. color = color.with_alpha(color.alpha() * mask_color.alpha() * mask_color.luminosity() / (255 * 255));
  148. } else {
  149. VERIFY(mask_kind == MaskKind::Alpha);
  150. color = color.with_alpha(color.alpha() * mask_color.alpha() / 255);
  151. }
  152. set_pixel(x, y, color);
  153. }
  154. }
  155. }
  156. ErrorOr<NonnullRefPtr<Gfx::Bitmap>> Bitmap::scaled(int sx, int sy) const
  157. {
  158. VERIFY(sx >= 0 && sy >= 0);
  159. if (sx == 1 && sy == 1)
  160. return clone();
  161. auto new_bitmap = TRY(Gfx::Bitmap::create(format(), { width() * sx, height() * sy }));
  162. auto old_width = width();
  163. auto old_height = height();
  164. for (int y = 0; y < old_height; y++) {
  165. for (int x = 0; x < old_width; x++) {
  166. auto color = get_pixel(x, y);
  167. auto base_x = x * sx;
  168. auto base_y = y * sy;
  169. for (int new_y = base_y; new_y < base_y + sy; new_y++) {
  170. for (int new_x = base_x; new_x < base_x + sx; new_x++) {
  171. new_bitmap->set_pixel(new_x, new_y, color);
  172. }
  173. }
  174. }
  175. }
  176. return new_bitmap;
  177. }
  178. ErrorOr<NonnullRefPtr<Gfx::Bitmap>> Bitmap::scaled(float sx, float sy) const
  179. {
  180. VERIFY(sx >= 0.0f && sy >= 0.0f);
  181. if (floorf(sx) == sx && floorf(sy) == sy)
  182. return scaled(static_cast<int>(sx), static_cast<int>(sy));
  183. int scaled_width = (int)ceilf(sx * (float)width());
  184. int scaled_height = (int)ceilf(sy * (float)height());
  185. return scaled_to_size({ scaled_width, scaled_height });
  186. }
  187. // http://fourier.eng.hmc.edu/e161/lectures/resize/node3.html
  188. ErrorOr<NonnullRefPtr<Gfx::Bitmap>> Bitmap::scaled_to_size(Gfx::IntSize size) const
  189. {
  190. auto new_bitmap = TRY(Gfx::Bitmap::create(format(), size));
  191. auto old_width = width();
  192. auto old_height = height();
  193. auto new_width = new_bitmap->width();
  194. auto new_height = new_bitmap->height();
  195. if (old_width == 1 && old_height == 1) {
  196. new_bitmap->fill(get_pixel(0, 0));
  197. return new_bitmap;
  198. }
  199. if (old_width > 1 && old_height > 1) {
  200. // The interpolation goes out of bounds on the bottom- and right-most edges.
  201. // We handle those in two specialized loops not only to make them faster, but
  202. // also to avoid four branch checks for every pixel.
  203. for (int y = 0; y < new_height - 1; y++) {
  204. for (int x = 0; x < new_width - 1; x++) {
  205. auto p = static_cast<float>(x) * static_cast<float>(old_width - 1) / static_cast<float>(new_width - 1);
  206. auto q = static_cast<float>(y) * static_cast<float>(old_height - 1) / static_cast<float>(new_height - 1);
  207. int i = floorf(p);
  208. int j = floorf(q);
  209. float u = p - static_cast<float>(i);
  210. float v = q - static_cast<float>(j);
  211. auto a = get_pixel(i, j);
  212. auto b = get_pixel(i + 1, j);
  213. auto c = get_pixel(i, j + 1);
  214. auto d = get_pixel(i + 1, j + 1);
  215. auto e = a.mixed_with(b, u);
  216. auto f = c.mixed_with(d, u);
  217. auto color = e.mixed_with(f, v);
  218. new_bitmap->set_pixel(x, y, color);
  219. }
  220. }
  221. // Bottom strip (excluding last pixel)
  222. auto old_bottom_y = old_height - 1;
  223. auto new_bottom_y = new_height - 1;
  224. for (int x = 0; x < new_width - 1; x++) {
  225. auto p = static_cast<float>(x) * static_cast<float>(old_width - 1) / static_cast<float>(new_width - 1);
  226. int i = floorf(p);
  227. float u = p - static_cast<float>(i);
  228. auto a = get_pixel(i, old_bottom_y);
  229. auto b = get_pixel(i + 1, old_bottom_y);
  230. auto color = a.mixed_with(b, u);
  231. new_bitmap->set_pixel(x, new_bottom_y, color);
  232. }
  233. // Right strip (excluding last pixel)
  234. auto old_right_x = old_width - 1;
  235. auto new_right_x = new_width - 1;
  236. for (int y = 0; y < new_height - 1; y++) {
  237. auto q = static_cast<float>(y) * static_cast<float>(old_height - 1) / static_cast<float>(new_height - 1);
  238. int j = floorf(q);
  239. float v = q - static_cast<float>(j);
  240. auto c = get_pixel(old_right_x, j);
  241. auto d = get_pixel(old_right_x, j + 1);
  242. auto color = c.mixed_with(d, v);
  243. new_bitmap->set_pixel(new_right_x, y, color);
  244. }
  245. // Bottom-right pixel
  246. new_bitmap->set_pixel(new_width - 1, new_height - 1, get_pixel(width() - 1, height() - 1));
  247. return new_bitmap;
  248. } else if (old_height == 1) {
  249. // Copy horizontal strip multiple times (excluding last pixel to out of bounds).
  250. auto old_bottom_y = old_height - 1;
  251. for (int x = 0; x < new_width - 1; x++) {
  252. auto p = static_cast<float>(x) * static_cast<float>(old_width - 1) / static_cast<float>(new_width - 1);
  253. int i = floorf(p);
  254. float u = p - static_cast<float>(i);
  255. auto a = get_pixel(i, old_bottom_y);
  256. auto b = get_pixel(i + 1, old_bottom_y);
  257. auto color = a.mixed_with(b, u);
  258. for (int new_bottom_y = 0; new_bottom_y < new_height; new_bottom_y++) {
  259. // Interpolate color only once and then copy into all columns.
  260. new_bitmap->set_pixel(x, new_bottom_y, color);
  261. }
  262. }
  263. for (int new_bottom_y = 0; new_bottom_y < new_height; new_bottom_y++) {
  264. // Copy last pixel of horizontal strip
  265. new_bitmap->set_pixel(new_width - 1, new_bottom_y, get_pixel(width() - 1, old_bottom_y));
  266. }
  267. return new_bitmap;
  268. } else if (old_width == 1) {
  269. // Copy vertical strip multiple times (excluding last pixel to avoid out of bounds).
  270. auto old_right_x = old_width - 1;
  271. for (int y = 0; y < new_height - 1; y++) {
  272. auto q = static_cast<float>(y) * static_cast<float>(old_height - 1) / static_cast<float>(new_height - 1);
  273. int j = floorf(q);
  274. float v = q - static_cast<float>(j);
  275. auto c = get_pixel(old_right_x, j);
  276. auto d = get_pixel(old_right_x, j + 1);
  277. auto color = c.mixed_with(d, v);
  278. for (int new_right_x = 0; new_right_x < new_width; new_right_x++) {
  279. // Interpolate color only once and copy into all rows.
  280. new_bitmap->set_pixel(new_right_x, y, color);
  281. }
  282. }
  283. for (int new_right_x = 0; new_right_x < new_width; new_right_x++) {
  284. // Copy last pixel of vertical strip
  285. new_bitmap->set_pixel(new_right_x, new_height - 1, get_pixel(old_right_x, height() - 1));
  286. }
  287. }
  288. return new_bitmap;
  289. }
  290. ErrorOr<NonnullRefPtr<Gfx::Bitmap>> Bitmap::cropped(Gfx::IntRect crop, Optional<BitmapFormat> new_bitmap_format) const
  291. {
  292. auto new_bitmap = TRY(Gfx::Bitmap::create(new_bitmap_format.value_or(format()), { crop.width(), crop.height() }));
  293. for (int y = 0; y < crop.height(); ++y) {
  294. for (int x = 0; x < crop.width(); ++x) {
  295. int global_x = x + crop.left();
  296. int global_y = y + crop.top();
  297. if (global_x >= width() || global_y >= height() || global_x < 0 || global_y < 0) {
  298. new_bitmap->set_pixel(x, y, Gfx::Color::Black);
  299. } else {
  300. new_bitmap->set_pixel(x, y, get_pixel(global_x, global_y));
  301. }
  302. }
  303. }
  304. return new_bitmap;
  305. }
  306. ErrorOr<NonnullRefPtr<Bitmap>> Bitmap::to_bitmap_backed_by_anonymous_buffer() const
  307. {
  308. if (m_buffer.is_valid()) {
  309. // FIXME: The const_cast here is awkward.
  310. return NonnullRefPtr { const_cast<Bitmap&>(*this) };
  311. }
  312. auto buffer = TRY(Core::AnonymousBuffer::create_with_size(round_up_to_power_of_two(size_in_bytes(), PAGE_SIZE)));
  313. auto bitmap = TRY(Bitmap::create_with_anonymous_buffer(m_format, move(buffer), size()));
  314. memcpy(bitmap->scanline(0), scanline(0), size_in_bytes());
  315. return bitmap;
  316. }
  317. Bitmap::~Bitmap()
  318. {
  319. if (m_destruction_callback)
  320. m_destruction_callback();
  321. m_data = nullptr;
  322. }
  323. void Bitmap::strip_alpha_channel()
  324. {
  325. VERIFY(m_format == BitmapFormat::BGRA8888 || m_format == BitmapFormat::BGRx8888);
  326. for (ARGB32& pixel : *this)
  327. pixel = 0xff000000 | (pixel & 0xffffff);
  328. m_format = BitmapFormat::BGRx8888;
  329. }
  330. void Bitmap::fill(Color color)
  331. {
  332. for (int y = 0; y < height(); ++y) {
  333. auto* scanline = this->scanline(y);
  334. fast_u32_fill(scanline, color.value(), width());
  335. }
  336. }
  337. Gfx::ShareableBitmap Bitmap::to_shareable_bitmap() const
  338. {
  339. auto bitmap_or_error = to_bitmap_backed_by_anonymous_buffer();
  340. if (bitmap_or_error.is_error())
  341. return {};
  342. return Gfx::ShareableBitmap { bitmap_or_error.release_value_but_fixme_should_propagate_errors(), Gfx::ShareableBitmap::ConstructWithKnownGoodBitmap };
  343. }
  344. ErrorOr<BackingStore> Bitmap::allocate_backing_store(BitmapFormat format, IntSize size)
  345. {
  346. if (size.is_empty())
  347. return Error::from_string_literal("Gfx::Bitmap backing store size is empty");
  348. if (size_would_overflow(format, size))
  349. return Error::from_string_literal("Gfx::Bitmap backing store size overflow");
  350. auto const pitch = minimum_pitch(size.width(), format);
  351. auto const data_size_in_bytes = size_in_bytes(pitch, size.height());
  352. void* data = kcalloc(1, data_size_in_bytes);
  353. if (data == nullptr)
  354. return Error::from_errno(errno);
  355. return BackingStore { data, pitch, data_size_in_bytes };
  356. }
  357. bool Bitmap::visually_equals(Bitmap const& other) const
  358. {
  359. auto own_width = width();
  360. auto own_height = height();
  361. if (other.width() != own_width || other.height() != own_height)
  362. return false;
  363. for (auto y = 0; y < own_height; ++y) {
  364. for (auto x = 0; x < own_width; ++x) {
  365. if (get_pixel(x, y) != other.get_pixel(x, y))
  366. return false;
  367. }
  368. }
  369. return true;
  370. }
  371. }