| 
									
										
										
										
											2015-03-23 23:25:32 +08:00
										 |  |  | // Aseprite Document Library
 | 
					
						
							| 
									
										
										
										
											2016-03-04 06:18:46 +08:00
										 |  |  | // Copyright (c) 2001-2016 David Capello
 | 
					
						
							| 
									
										
										
										
											2015-03-23 23:25:32 +08:00
										 |  |  | //
 | 
					
						
							|  |  |  | // This file is released under the terms of the MIT license.
 | 
					
						
							|  |  |  | // Read LICENSE.txt for more information.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef HAVE_CONFIG_H
 | 
					
						
							|  |  |  | #include "config.h"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "doc/remap.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-04 06:18:46 +08:00
										 |  |  | #include "base/base.h"
 | 
					
						
							| 
									
										
										
										
											2015-07-29 04:16:32 +08:00
										 |  |  | #include "doc/palette.h"
 | 
					
						
							| 
									
										
										
										
											2015-05-09 23:20:58 +08:00
										 |  |  | #include "doc/palette_picks.h"
 | 
					
						
							| 
									
										
										
										
											2015-07-29 04:16:32 +08:00
										 |  |  | #include "doc/rgbmap.h"
 | 
					
						
							| 
									
										
										
										
											2015-05-09 23:20:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 23:25:32 +08:00
										 |  |  | namespace doc { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-10 02:57:46 +08:00
										 |  |  | Remap create_remap_to_move_picks(const PalettePicks& picks, int beforeIndex) | 
					
						
							| 
									
										
										
										
											2015-03-23 23:25:32 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-05-09 23:20:58 +08:00
										 |  |  |   Remap map(picks.size()); | 
					
						
							| 
									
										
										
										
											2015-03-23 23:25:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   int selectedTotal = 0; | 
					
						
							|  |  |  |   int selectedBeforeIndex = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (int i=0; i<map.size(); ++i) { | 
					
						
							| 
									
										
										
										
											2015-05-09 23:20:58 +08:00
										 |  |  |     if (picks[i]) { | 
					
						
							| 
									
										
										
										
											2015-03-23 23:25:32 +08:00
										 |  |  |       ++selectedTotal; | 
					
						
							|  |  |  |       if (i < beforeIndex) | 
					
						
							|  |  |  |         ++selectedBeforeIndex; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (int i=0, j=0, k=0; i<map.size(); ++i) { | 
					
						
							|  |  |  |     if (k == beforeIndex - selectedBeforeIndex) | 
					
						
							|  |  |  |       k += selectedTotal; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-09 23:20:58 +08:00
										 |  |  |     if (picks[i]) { | 
					
						
							| 
									
										
										
										
											2015-03-23 23:25:32 +08:00
										 |  |  |       map.map(i, beforeIndex - selectedBeforeIndex + j); | 
					
						
							|  |  |  |       ++j; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       map.map(i, k++); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return map; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-10 02:57:46 +08:00
										 |  |  | Remap create_remap_to_expand_palette(int size, int count, int beforeIndex) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Remap map(size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   int j, k = 0; | 
					
						
							|  |  |  |   for (int i=0; i<size; ++i) { | 
					
						
							|  |  |  |     if (i < beforeIndex) | 
					
						
							|  |  |  |       j = i; | 
					
						
							|  |  |  |     else if (i + count < size) | 
					
						
							|  |  |  |       j = i + count; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       j = beforeIndex + (k++); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     map.map(i, j); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return map; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-29 04:16:32 +08:00
										 |  |  | Remap create_remap_to_change_palette( | 
					
						
							|  |  |  |   const Palette* oldPalette, const Palette* newPalette, | 
					
						
							| 
									
										
										
										
											2015-08-01 00:32:23 +08:00
										 |  |  |   const int oldMaskIndex, | 
					
						
							|  |  |  |   const bool remapMaskIndex) | 
					
						
							| 
									
										
										
										
											2015-07-29 04:16:32 +08:00
										 |  |  | { | 
					
						
							|  |  |  |   Remap remap(MAX(oldPalette->size(), newPalette->size())); | 
					
						
							|  |  |  |   int maskIndex = oldMaskIndex; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (maskIndex >= 0) { | 
					
						
							| 
									
										
										
										
											2015-08-01 00:32:23 +08:00
										 |  |  |     if (remapMaskIndex && | 
					
						
							|  |  |  |         oldPalette->getEntry(maskIndex) != | 
					
						
							|  |  |  |         newPalette->getEntry(maskIndex)) { | 
					
						
							|  |  |  |       color_t maskColor = oldPalette->getEntry(maskIndex); | 
					
						
							|  |  |  |       int r = rgba_getr(maskColor); | 
					
						
							|  |  |  |       int g = rgba_getg(maskColor); | 
					
						
							|  |  |  |       int b = rgba_getb(maskColor); | 
					
						
							|  |  |  |       int a = rgba_geta(maskColor); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Find the new mask color
 | 
					
						
							|  |  |  |       maskIndex = newPalette->findExactMatch(r, g, b, a, -1); | 
					
						
							|  |  |  |       if (maskIndex >= 0) | 
					
						
							|  |  |  |         remap.map(oldMaskIndex, maskIndex); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       remap.map(maskIndex, maskIndex); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-07-29 04:16:32 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   RgbMap rgbmap; | 
					
						
							|  |  |  |   rgbmap.regenerate(newPalette, maskIndex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (int i=0; i<oldPalette->size(); ++i) { | 
					
						
							|  |  |  |     if (i == oldMaskIndex) | 
					
						
							|  |  |  |       continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const color_t color = oldPalette->getEntry(i); | 
					
						
							| 
									
										
										
										
											2016-03-25 04:37:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // If in both palettes, it's the same color, we don't need to
 | 
					
						
							|  |  |  |     // remap this entry.
 | 
					
						
							|  |  |  |     if (color == newPalette->getEntry(i)) { | 
					
						
							|  |  |  |       remap.map(i, i); | 
					
						
							|  |  |  |       continue; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-29 04:16:32 +08:00
										 |  |  |     int j = newPalette->findExactMatch( | 
					
						
							|  |  |  |       rgba_getr(color), | 
					
						
							|  |  |  |       rgba_getg(color), | 
					
						
							|  |  |  |       rgba_getb(color), | 
					
						
							|  |  |  |       rgba_geta(color), maskIndex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (j < 0) | 
					
						
							|  |  |  |       j = newPalette->findBestfit( | 
					
						
							|  |  |  |         rgba_getr(color), | 
					
						
							|  |  |  |         rgba_getg(color), | 
					
						
							|  |  |  |         rgba_getb(color), | 
					
						
							|  |  |  |         rgba_geta(color), maskIndex); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     remap.map(i, j); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return remap; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 23:57:59 +08:00
										 |  |  | void Remap::merge(const Remap& other) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   for (int i=0; i<size(); ++i) { | 
					
						
							|  |  |  |     m_map[i] = other[m_map[i]]; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Remap Remap::invert() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Remap inv(size()); | 
					
						
							|  |  |  |   for (int i=0; i<size(); ++i) | 
					
						
							|  |  |  |     inv.map(operator[](i), i); | 
					
						
							|  |  |  |   return inv; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-07 03:15:54 +08:00
										 |  |  | bool Remap::isFor8bit() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   for (int i=0; i<size(); ++i) { | 
					
						
							|  |  |  |     // Moving entries between [0,255] range to or from [256,+inf)
 | 
					
						
							|  |  |  |     // range are invalid for 8-bit images.
 | 
					
						
							|  |  |  |     if ((i <  256 && m_map[i] >= 256) || | 
					
						
							|  |  |  |         (i >= 256 && m_map[i] <  256)) | 
					
						
							|  |  |  |       return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-29 04:16:32 +08:00
										 |  |  | bool Remap::isInvertible(const PalettePicks& usedEntries) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   PalettePicks picks(size()); | 
					
						
							|  |  |  |   for (int i=0; i<size(); ++i) { | 
					
						
							|  |  |  |     if (!usedEntries[i]) | 
					
						
							|  |  |  |       continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int j = m_map[i]; | 
					
						
							|  |  |  |     if (picks[j]) | 
					
						
							|  |  |  |       return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     picks[j] = true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 23:25:32 +08:00
										 |  |  | } // namespace doc
 |