1 // Aseprite
2 // Copyright (C) 2001-2017 David Capello
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 "base/unique_ptr.h"
12 #include "doc/algorithm/resize_image.h"
13 #include "doc/cel.h"
14 #include "doc/image.h"
15 #include "doc/layer.h"
16 #include "doc/palette.h"
17 #include "doc/primitives.h"
18 #include "doc/sprite.h"
19 #include "render/ordered_dither.h"
20 #include "render/quantization.h"
21 #include "render/render.h"
22
23 #include <cmath>
24
25 namespace app {
26
27 using namespace doc;
28
create_cel_copy(const Cel * srcCel,const Sprite * dstSprite,const Layer * dstLayer,const frame_t dstFrame)29 Cel* create_cel_copy(const Cel* srcCel,
30 const Sprite* dstSprite,
31 const Layer* dstLayer,
32 const frame_t dstFrame)
33 {
34 const Image* celImage = srcCel->image();
35
36 base::UniquePtr<Cel> dstCel(
37 new Cel(dstFrame,
38 ImageRef(Image::create(dstSprite->pixelFormat(),
39 celImage->width(),
40 celImage->height()))));
41
42 if ((dstSprite->pixelFormat() != celImage->pixelFormat()) ||
43 // If both images are indexed but with different palette, we can
44 // convert the source cel to RGB first.
45 (dstSprite->pixelFormat() == IMAGE_INDEXED &&
46 celImage->pixelFormat() == IMAGE_INDEXED &&
47 srcCel->sprite()->palette(srcCel->frame())->countDiff(
48 dstSprite->palette(dstFrame), nullptr, nullptr))) {
49 ImageRef tmpImage(Image::create(IMAGE_RGB, celImage->width(), celImage->height()));
50 tmpImage->clear(0);
51
52 render::convert_pixel_format(
53 celImage,
54 tmpImage.get(),
55 IMAGE_RGB,
56 render::DitheringAlgorithm::None,
57 render::DitheringMatrix(),
58 srcCel->sprite()->rgbMap(srcCel->frame()),
59 srcCel->sprite()->palette(srcCel->frame()),
60 srcCel->layer()->isBackground(),
61 0);
62
63 render::convert_pixel_format(
64 tmpImage.get(),
65 dstCel->image(),
66 IMAGE_INDEXED,
67 render::DitheringAlgorithm::None,
68 render::DitheringMatrix(),
69 dstSprite->rgbMap(dstFrame),
70 dstSprite->palette(dstFrame),
71 srcCel->layer()->isBackground(),
72 dstSprite->transparentColor());
73 }
74 else {
75 render::composite_image(
76 dstCel->image(),
77 celImage,
78 srcCel->sprite()->palette(srcCel->frame()),
79 0, 0, 255, BlendMode::SRC);
80 }
81
82 // Resize a referecen cel to a non-reference layer
83 if (srcCel->layer()->isReference() && !dstLayer->isReference()) {
84 gfx::RectF srcBounds = srcCel->boundsF();
85
86 base::UniquePtr<Cel> dstCel2(
87 new Cel(dstFrame,
88 ImageRef(Image::create(dstSprite->pixelFormat(),
89 std::ceil(srcBounds.w),
90 std::ceil(srcBounds.h)))));
91 algorithm::resize_image(
92 dstCel->image(), dstCel2->image(),
93 algorithm::RESIZE_METHOD_NEAREST_NEIGHBOR,
94 nullptr, nullptr, 0);
95
96 dstCel.reset(dstCel2.release());
97 dstCel->setPosition(gfx::Point(srcBounds.origin()));
98 }
99 // Copy original cel bounds
100 else {
101 if (srcCel->layer() &&
102 srcCel->layer()->isReference()) {
103 dstCel->setBoundsF(srcCel->boundsF());
104 }
105 else {
106 dstCel->setPosition(srcCel->position());
107 }
108 }
109
110 dstCel->setOpacity(srcCel->opacity());
111 dstCel->data()->setUserData(srcCel->data()->userData());
112
113 return dstCel.release();
114 }
115
116 } // namespace app
117