1// Aseprite
2// Copyright (c) 2019-2022 Igara Studio S.A.
3//
4// This program is distributed under the terms of
5// the End-User License Agreement for Aseprite.
6
7#ifdef HAVE_CONFIG_H
8#include "config.h"
9#endif
10
11#include "app/util/resize_image.h"
12
13#include "app/cmd/replace_image.h"
14#include "app/cmd/set_cel_bounds.h"
15#include "app/cmd/set_cel_position.h"
16#include "app/tx.h"
17#include "doc/cel.h"
18#include "doc/image.h"
19#include "doc/image_ref.h"
20#include "doc/layer.h"
21#include "doc/sprite.h"
22
23#include <algorithm>
24#include <memory>
25
26namespace app {
27
28doc::Image* resize_image(
29 const doc::Image* image,
30 const gfx::SizeF& scale,
31 const doc::algorithm::ResizeMethod method,
32 const Palette* pal,
33 const RgbMap* rgbmap)
34{
35 doc::ImageSpec spec = image->spec();
36 spec.setWidth(std::max(1, int(scale.w*image->width())));
37 spec.setHeight(std::max(1, int(scale.h*image->height())));
38 std::unique_ptr<doc::Image> newImage(
39 doc::Image::create(spec));
40 newImage->setMaskColor(image->maskColor());
41
42 doc::algorithm::fixup_image_transparent_colors(newImage.get());
43 doc::algorithm::resize_image(
44 image, newImage.get(),
45 method,
46 pal,
47 rgbmap,
48 newImage->maskColor());
49
50 return newImage.release();
51}
52
53void resize_cel_image(
54 Tx& tx, doc::Cel* cel,
55 const gfx::SizeF& scale,
56 const doc::algorithm::ResizeMethod method,
57 const gfx::PointF& pivot)
58{
59 // Get cel's image
60 doc::Image* image = cel->image();
61 if (image && !cel->link()) {
62 doc::Sprite* sprite = cel->sprite();
63
64 // Resize the cel bounds only if it's from a reference layer
65 if (cel->layer()->isReference()) {
66 gfx::RectF newBounds = cel->boundsF();
67 newBounds.offset(pivot - gfx::PointF(scale.w*pivot.x, scale.h*pivot.y));
68 newBounds.w *= scale.w;
69 newBounds.h *= scale.h;
70 tx(new cmd::SetCelBoundsF(cel, newBounds));
71 }
72 else {
73 // Change cel location
74 const int x = cel->x() + pivot.x - scale.w*pivot.x;
75 const int y = cel->y() + pivot.y - scale.h*pivot.y;
76 if (cel->x() != x || cel->y() != y)
77 tx(new cmd::SetCelPosition(cel, x, y));
78
79 // Resize the image
80 const int w = std::max(1, int(scale.w*image->width()));
81 const int h = std::max(1, int(scale.h*image->height()));
82 doc::ImageRef newImage(
83 doc::Image::create(
84 image->pixelFormat(), std::max(1, w), std::max(1, h)));
85 newImage->setMaskColor(image->maskColor());
86
87 doc::algorithm::fixup_image_transparent_colors(image);
88 doc::algorithm::resize_image(
89 image, newImage.get(),
90 method,
91 sprite->palette(cel->frame()),
92 sprite->rgbMap(cel->frame()),
93 (cel->layer()->isBackground() ? -1: sprite->transparentColor()));
94
95 tx(new cmd::ReplaceImage(sprite, cel->imageRef(), newImage));
96 }
97 }
98}
99
100} // namespace app
101