123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- /*
- * Copyright (c) 2023-2024, Lucas Chollet <lucas.chollet@serenityos.org>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
- #pragma once
- #include <AK/Concepts.h>
- #include <AK/NonnullOwnPtr.h>
- #include <LibGfx/Bitmap.h>
- #include <LibGfx/ImageFormats/TIFFMetadata.h>
- namespace Gfx {
- namespace Detail {
- template<typename BitmapLike>
- class ExifOrientedBitmap {
- public:
- static ErrorOr<ExifOrientedBitmap> create(TIFF::Orientation orientation, IntSize size, BitmapFormat format)
- requires(SameAs<BitmapLike, Bitmap>)
- {
- auto bitmap = TRY(Bitmap::create(format, oriented_size(size, orientation)));
- return ExifOrientedBitmap(move(bitmap), size, orientation);
- }
- static ErrorOr<ExifOrientedBitmap> create(TIFF::Orientation orientation, IntSize size)
- requires(SameAs<BitmapLike, CMYKBitmap>)
- {
- auto bitmap = TRY(CMYKBitmap::create_with_size(oriented_size(size, orientation)));
- return ExifOrientedBitmap(move(bitmap), size, orientation);
- }
- template<OneOf<ARGB32, CMYK> Value>
- void set_pixel(u32 x, u32 y, Value color)
- {
- auto const new_position = oriented_position(IntPoint(x, y));
- m_bitmap->scanline(new_position.y())[new_position.x()] = color;
- }
- NonnullRefPtr<BitmapLike>& bitmap()
- {
- return m_bitmap;
- }
- static IntSize oriented_size(IntSize size, TIFF::Orientation orientation)
- {
- switch (orientation) {
- case Orientation::Default:
- case Orientation::FlipHorizontally:
- case Orientation::Rotate180:
- case Orientation::FlipVertically:
- return size;
- case Orientation::Rotate90ClockwiseThenFlipHorizontally:
- case Orientation::Rotate90Clockwise:
- case Orientation::FlipHorizontallyThenRotate90Clockwise:
- case Orientation::Rotate90CounterClockwise:
- return { size.height(), size.width() };
- }
- VERIFY_NOT_REACHED();
- }
- private:
- using Orientation = TIFF::Orientation;
- ExifOrientedBitmap(NonnullRefPtr<BitmapLike> bitmap, IntSize size, Orientation orientation)
- : m_bitmap(move(bitmap))
- , m_orientation(orientation)
- , m_width(size.width())
- , m_height(size.height())
- {
- }
- IntPoint oriented_position(IntPoint point)
- {
- auto const flip_horizontally = [this](IntPoint point) {
- return IntPoint(m_width - point.x() - 1, point.y());
- };
- auto const rotate_90_clockwise = [this](IntPoint point) {
- return IntPoint(m_height - point.y() - 1, point.x());
- };
- switch (m_orientation) {
- case Orientation::Default:
- return point;
- case Orientation::FlipHorizontally:
- return flip_horizontally(point);
- case Orientation::Rotate180:
- return IntPoint(m_width - point.x() - 1, m_height - point.y() - 1);
- case Orientation::FlipVertically:
- return IntPoint(point.x(), m_height - point.y() - 1);
- case Orientation::Rotate90ClockwiseThenFlipHorizontally:
- return flip_horizontally(rotate_90_clockwise(point));
- case Orientation::Rotate90Clockwise:
- return rotate_90_clockwise(point);
- case Orientation::FlipHorizontallyThenRotate90Clockwise:
- return rotate_90_clockwise(flip_horizontally(point));
- case Orientation::Rotate90CounterClockwise:
- return IntPoint(point.y(), m_width - point.x() - 1);
- }
- VERIFY_NOT_REACHED();
- }
- NonnullRefPtr<BitmapLike> m_bitmap;
- Orientation m_orientation;
- u32 m_width {};
- u32 m_height {};
- };
- }
- using ExifOrientedBitmap = Detail::ExifOrientedBitmap<Bitmap>;
- using ExifOrientedCMYKBitmap = Detail::ExifOrientedBitmap<CMYKBitmap>;
- }
|