1 // Aseprite Document Library
2 // Copyright (c) 2001-2016 David Capello
3 //
4 // This file is released under the terms of the MIT license.
5 // Read LICENSE.txt for more information.
6
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10
11 #include "doc/remap.h"
12
13 #include "base/base.h"
14 #include "doc/palette.h"
15 #include "doc/palette_picks.h"
16 #include "doc/rgbmap.h"
17
18 namespace doc {
19
create_remap_to_move_picks(const PalettePicks & picks,int beforeIndex)20 Remap create_remap_to_move_picks(const PalettePicks& picks, int beforeIndex)
21 {
22 Remap map(picks.size());
23
24 int selectedTotal = 0;
25 int selectedBeforeIndex = 0;
26
27 for (int i=0; i<map.size(); ++i) {
28 if (picks[i]) {
29 ++selectedTotal;
30 if (i < beforeIndex)
31 ++selectedBeforeIndex;
32 }
33 }
34
35 for (int i=0, j=0, k=0; i<map.size(); ++i) {
36 if (k == beforeIndex - selectedBeforeIndex)
37 k += selectedTotal;
38
39 if (picks[i]) {
40 map.map(i, beforeIndex - selectedBeforeIndex + j);
41 ++j;
42 }
43 else {
44 map.map(i, k++);
45 }
46 }
47
48 return map;
49 }
50
create_remap_to_expand_palette(int size,int count,int beforeIndex)51 Remap create_remap_to_expand_palette(int size, int count, int beforeIndex)
52 {
53 Remap map(size);
54
55 int j, k = 0;
56 for (int i=0; i<size; ++i) {
57 if (i < beforeIndex)
58 j = i;
59 else if (i + count < size)
60 j = i + count;
61 else
62 j = beforeIndex + (k++);
63
64 map.map(i, j);
65 }
66 return map;
67 }
68
create_remap_to_change_palette(const Palette * oldPalette,const Palette * newPalette,const int oldMaskIndex,const bool remapMaskIndex)69 Remap create_remap_to_change_palette(
70 const Palette* oldPalette, const Palette* newPalette,
71 const int oldMaskIndex,
72 const bool remapMaskIndex)
73 {
74 Remap remap(MAX(oldPalette->size(), newPalette->size()));
75 int maskIndex = oldMaskIndex;
76
77 if (maskIndex >= 0) {
78 if (remapMaskIndex &&
79 oldPalette->getEntry(maskIndex) !=
80 newPalette->getEntry(maskIndex)) {
81 color_t maskColor = oldPalette->getEntry(maskIndex);
82 int r = rgba_getr(maskColor);
83 int g = rgba_getg(maskColor);
84 int b = rgba_getb(maskColor);
85 int a = rgba_geta(maskColor);
86
87 // Find the new mask color
88 maskIndex = newPalette->findExactMatch(r, g, b, a, -1);
89 if (maskIndex >= 0)
90 remap.map(oldMaskIndex, maskIndex);
91 }
92 else {
93 remap.map(maskIndex, maskIndex);
94 }
95 }
96
97 RgbMap rgbmap;
98 rgbmap.regenerate(newPalette, maskIndex);
99
100 for (int i=0; i<oldPalette->size(); ++i) {
101 if (i == oldMaskIndex)
102 continue;
103
104 const color_t color = oldPalette->getEntry(i);
105
106 // If in both palettes, it's the same color, we don't need to
107 // remap this entry.
108 if (color == newPalette->getEntry(i)) {
109 remap.map(i, i);
110 continue;
111 }
112
113 int j = newPalette->findExactMatch(
114 rgba_getr(color),
115 rgba_getg(color),
116 rgba_getb(color),
117 rgba_geta(color), maskIndex);
118
119 if (j < 0)
120 j = newPalette->findBestfit(
121 rgba_getr(color),
122 rgba_getg(color),
123 rgba_getb(color),
124 rgba_geta(color), maskIndex);
125
126 remap.map(i, j);
127 }
128 return remap;
129 }
130
merge(const Remap & other)131 void Remap::merge(const Remap& other)
132 {
133 for (int i=0; i<size(); ++i) {
134 m_map[i] = other[m_map[i]];
135 }
136 }
137
invert() const138 Remap Remap::invert() const
139 {
140 Remap inv(size());
141 for (int i=0; i<size(); ++i)
142 inv.map(operator[](i), i);
143 return inv;
144 }
145
isFor8bit() const146 bool Remap::isFor8bit() const
147 {
148 for (int i=0; i<size(); ++i) {
149 // Moving entries between [0,255] range to or from [256,+inf)
150 // range are invalid for 8-bit images.
151 if ((i < 256 && m_map[i] >= 256) ||
152 (i >= 256 && m_map[i] < 256))
153 return false;
154 }
155 return true;
156 }
157
isInvertible(const PalettePicks & usedEntries) const158 bool Remap::isInvertible(const PalettePicks& usedEntries) const
159 {
160 PalettePicks picks(size());
161 for (int i=0; i<size(); ++i) {
162 if (!usedEntries[i])
163 continue;
164
165 int j = m_map[i];
166 if (picks[j])
167 return false;
168
169 picks[j] = true;
170 }
171 return true;
172 }
173
174 } // namespace doc
175