1 // Aseprite
2 // Copyright (C) 2016 Carlo Caputo
3 //
4 // This program is distributed under the terms of
5 // the End-User License Agreement for Aseprite.
6
7 #include "app/color_utils.h"
8 #include "app/doc.h"
9 #include "app/pref/preferences.h"
10 #include "app/thumbnails.h"
11 #include "doc/algorithm/resize_image.h"
12 #include "doc/cel.h"
13 #include "doc/conversion_she.h"
14 #include "doc/doc.h"
15 #include "doc/frame.h"
16 #include "doc/object.h"
17 #include "doc/object_id.h"
18 #include "render/render.h"
19 #include "she/surface.h"
20 #include "she/system.h"
21
22 namespace app {
23 namespace thumb {
24
get_cel_thumbnail(const doc::Cel * cel,const gfx::Size & thumb_size,gfx::Rect cel_image_on_thumb)25 she::Surface* get_cel_thumbnail(const doc::Cel* cel,
26 const gfx::Size& thumb_size,
27 gfx::Rect cel_image_on_thumb)
28 {
29 Doc* document = static_cast<Doc*>(cel->sprite()->document());
30 doc::frame_t frame = cel->frame();
31 doc::Image* image = cel->image();
32
33 DocumentPreferences& docPref = Preferences::instance().document(document);
34
35 doc::color_t bg1 = color_utils::color_for_image(docPref.bg.color1(), image->pixelFormat());
36 doc::color_t bg2 = color_utils::color_for_image(docPref.bg.color2(), image->pixelFormat());
37
38 gfx::Size image_size = image->size();
39
40 if (cel_image_on_thumb.isEmpty()) {
41 double zw = thumb_size.w / (double)image_size.w;
42 double zh = thumb_size.h / (double)image_size.h;
43 double zoom = MIN(1.0, MIN(zw, zh));
44
45 cel_image_on_thumb = gfx::Rect(
46 (int)(thumb_size.w * 0.5 - image_size.w * zoom * 0.5),
47 (int)(thumb_size.h * 0.5 - image_size.h * zoom * 0.5),
48 MAX(1, (int)(image_size.w * zoom)),
49 MAX(1, (int)(image_size.h * zoom)));
50 }
51
52 const doc::Sprite* sprite = document->sprite();
53 // TODO doc::Image::createCopy() from pre-rendered checkered background
54 base::UniquePtr<doc::Image> thumb_img(doc::Image::create(
55 image->pixelFormat(), thumb_size.w, thumb_size.h));
56
57 int block_size = MID(4, thumb_size.w/8, 16);
58 for (int dst_y = 0; dst_y < thumb_size.h; dst_y++) {
59 for (int dst_x = 0; dst_x < thumb_size.w; dst_x++) {
60 thumb_img->putPixel(dst_x, dst_y,
61 (((dst_x / block_size) % 2) ^
62 ((dst_y / block_size) % 2)) ? bg2: bg1);
63 }
64 }
65
66 base::UniquePtr<doc::Image> scale_img;
67 const doc::Image* source = image;
68
69 if (cel_image_on_thumb.w != image_size.w || cel_image_on_thumb.h != image_size.h) {
70 scale_img.reset(doc::Image::create(
71 image->pixelFormat(), cel_image_on_thumb.w, cel_image_on_thumb.h));
72
73 doc::algorithm::resize_image(
74 image, scale_img,
75 doc::algorithm::ResizeMethod::RESIZE_METHOD_NEAREST_NEIGHBOR,
76 sprite->palette(frame),
77 sprite->rgbMap(frame),
78 sprite->transparentColor());
79
80 source = scale_img.get();
81 }
82
83 render::composite_image(
84 thumb_img, source,
85 sprite->palette(frame),
86 cel_image_on_thumb.x,
87 cel_image_on_thumb.y,
88 255, BlendMode::NORMAL);
89
90 she::Surface* thumb_surf = she::instance()->createRgbaSurface(
91 thumb_img->width(), thumb_img->height());
92
93 convert_image_to_surface(thumb_img, sprite->palette(frame), thumb_surf,
94 0, 0, 0, 0, thumb_img->width(), thumb_img->height());
95
96 return thumb_surf;
97 }
98
99 } // thumb
100 } // app
101