From bbb6b83905e769fd283a150c7ca7aba550a1f019 Mon Sep 17 00:00:00 2001 From: David Capello Date: Fri, 10 Apr 2020 08:58:59 -0300 Subject: [PATCH 1/9] Make doc::RgbMap a regular object (don't need to be an doc::Object) --- src/doc/object_type.h | 35 ++++++++++++++++++++--------------- src/doc/rgbmap.cpp | 4 ++-- src/doc/rgbmap.h | 3 ++- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/doc/object_type.h b/src/doc/object_type.h index 31f897375..d09084500 100644 --- a/src/doc/object_type.h +++ b/src/doc/object_type.h @@ -1,5 +1,5 @@ // Aseprite Document Library -// Copyright (C) 2019 Igara Studio S.A. +// Copyright (C) 2019-2020 Igara Studio S.A. // Copyright (C) 2001-2017 David Capello // // This file is released under the terms of the MIT license. @@ -12,20 +12,25 @@ namespace doc { enum class ObjectType { - Unknown, - Image, - Palette, - RgbMap, - Path, - Mask, - Cel, - CelData, - LayerImage, - LayerGroup, - Sprite, - Document, - Tag, - Slice, + Unknown = 0, + Image = 1, + Palette = 2, + + // Deprecated values, we cannot re-use these indexes because + // backup sessions use them (check readLayer() function in + // src/app/crash/read_document.cpp). + //RgbMap = 3, + //Path = 4, + + Mask = 5, + Cel = 6, + CelData = 7, + LayerImage = 8, + LayerGroup = 9, + Sprite = 10, + Document = 11, + Tag = 12, + Slice = 13, }; } // namespace doc diff --git a/src/doc/rgbmap.cpp b/src/doc/rgbmap.cpp index 4a39dffb7..1d56fba18 100644 --- a/src/doc/rgbmap.cpp +++ b/src/doc/rgbmap.cpp @@ -1,4 +1,5 @@ // Aseprite Document Library +// Copyright (c) 2020 Igara Studio S.A. // Copyright (c) 2001-2015 David Capello // // This file is released under the terms of the MIT license. @@ -22,8 +23,7 @@ namespace doc { #define MAPSIZE (RSIZE*GSIZE*BSIZE*ASIZE) RgbMap::RgbMap() - : Object(ObjectType::RgbMap) - , m_map(MAPSIZE) + : m_map(MAPSIZE) , m_palette(NULL) , m_modifications(0) , m_maskIndex(0) diff --git a/src/doc/rgbmap.h b/src/doc/rgbmap.h index 6fa7bcd79..30ab666a3 100644 --- a/src/doc/rgbmap.h +++ b/src/doc/rgbmap.h @@ -1,4 +1,5 @@ // Aseprite Document Library +// Copyright (c) 2020 Igara Studio S.A. // Copyright (c) 2001-2016 David Capello // // This file is released under the terms of the MIT license. @@ -19,7 +20,7 @@ namespace doc { class Palette; // It acts like a cache for Palette:findBestfit() calls. - class RgbMap : public Object { + class RgbMap { // Bit activated on m_map entries that aren't yet calculated. const int INVALID = 256; From ad31c9b7a85b42bb9221bae2e4a8f0e8ce55bab1 Mon Sep 17 00:00:00 2001 From: David Capello Date: Fri, 10 Apr 2020 10:15:04 -0300 Subject: [PATCH 2/9] Convert RgbMap into an interface and rename the old class to RgbMapRGB53A --- src/app/file/gif_format.cpp | 13 +++-- src/app/tools/ink_processing.h | 31 +++-------- src/doc/CMakeLists.txt | 3 +- src/doc/LICENSE.txt | 2 +- src/doc/doc.h | 3 +- src/doc/rgbmap.h | 40 ++++---------- src/doc/{rgbmap.cpp => rgbmap_rgb5a3.cpp} | 10 ++-- src/doc/rgbmap_rgb5a3.h | 61 ++++++++++++++++++++++ src/doc/sprite.cpp | 4 +- src/doc/sprite.h | 5 +- src/filters/brightness_contrast_filter.cpp | 5 +- src/filters/hue_saturation_filter.cpp | 5 +- src/render/quantization.cpp | 2 +- 13 files changed, 102 insertions(+), 82 deletions(-) rename src/doc/{rgbmap.cpp => rgbmap_rgb5a3.cpp} (80%) create mode 100644 src/doc/rgbmap_rgb5a3.h diff --git a/src/app/file/gif_format.cpp b/src/app/file/gif_format.cpp index c89a64b3e..f398187d6 100644 --- a/src/app/file/gif_format.cpp +++ b/src/app/file/gif_format.cpp @@ -1171,7 +1171,7 @@ private: const DisposalMethod disposal, const bool fixDuration) { std::unique_ptr framePaletteRef; - std::unique_ptr rgbmapRef; + std::unique_ptr rgbmapRef; Palette* framePalette = m_sprite->palette(frame); RgbMap* rgbmap = m_sprite->rgbMap(frame); @@ -1180,9 +1180,9 @@ private: framePaletteRef.reset(createOptimizedPalette(frameBounds)); framePalette = framePaletteRef.get(); - rgbmapRef.reset(new RgbMap); + rgbmapRef.reset(new RgbMapRGB5A3); + rgbmapRef->regenerate(framePalette, m_transparentIndex); rgbmap = rgbmapRef.get(); - rgbmap->regenerate(framePalette, m_transparentIndex); } // We will store the frameBounds pixels in frameImage, with the @@ -1228,6 +1228,8 @@ private: int i; if (rgba_geta(color) >= 128) { + color |= rgba_a_mask; // Set alpha=255 + i = framePalette->findExactMatch( rgba_getr(color), rgba_getg(color), @@ -1235,10 +1237,7 @@ private: 255, m_transparentIndex); if (i < 0) - i = rgbmap->mapColor(rgba_getr(color), - rgba_getg(color), - rgba_getb(color), - 255); + i = rgbmap->mapColor(color); } else { ASSERT(m_transparentIndex >= 0); diff --git a/src/app/tools/ink_processing.h b/src/app/tools/ink_processing.h index 2e73d84f0..5bd5c6c26 100644 --- a/src/app/tools/ink_processing.h +++ b/src/app/tools/ink_processing.h @@ -272,10 +272,7 @@ public: c = m_palette->getEntry(c); c = rgba_blender_normal(c, m_color, m_opacity); - *m_dstAddress = m_rgbmap->mapColor(rgba_getr(c), - rgba_getg(c), - rgba_getb(c), - rgba_geta(c)); + *m_dstAddress = m_rgbmap->mapColor(c); } private: @@ -338,10 +335,7 @@ public: c = m_palette->getEntry(c); c = rgba_blender_merge(c, m_color, m_opacity); - *m_dstAddress = m_rgbmap->mapColor(rgba_getr(c), - rgba_getg(c), - rgba_getb(c), - rgba_geta(c)); + *m_dstAddress = m_rgbmap->mapColor(c); } private: @@ -493,8 +487,7 @@ public: doc::rgba(m_area.r, m_area.g, m_area.b, m_area.a), m_opacity); - *m_dstAddress = m_rgbmap->mapColor( - rgba_getr(c), rgba_getg(c), rgba_getb(c), rgba_geta(c)); + *m_dstAddress = m_rgbmap->mapColor(c); } else { *m_dstAddress = *m_srcAddress; @@ -606,8 +599,7 @@ public: color_t c = rgba_blender_normal( m_palette->getEntry(*m_srcAddress), m_color2, m_opacity); - *m_dstAddress = m_rgbmap->mapColor( - rgba_getr(c), rgba_getg(c), rgba_getb(c), rgba_geta(c)); + *m_dstAddress = m_rgbmap->mapColor(c); } } } @@ -694,10 +686,7 @@ void JumbleInkProcessing::processPixel(int x, int y) tc, m_opacity); if (rgba_geta(c) >= 128) - *m_dstAddress = m_rgbmap->mapColor(rgba_getr(c), - rgba_getg(c), - rgba_getb(c), - rgba_geta(c)); + *m_dstAddress = m_rgbmap->mapColor(c); else *m_dstAddress = 0; } @@ -1043,10 +1032,7 @@ void GradientInkProcessing::processPixel(int x, int y) c0 = m_palette->getEntry(c0); c = rgba_blender_normal(c0, c, m_opacity); - *m_dstAddress = m_rgbmap->mapColor(rgba_getr(c), - rgba_getg(c), - rgba_getb(c), - rgba_geta(c)); + *m_dstAddress = m_rgbmap->mapColor(c); ++m_tmpAddress; } @@ -1091,10 +1077,7 @@ public: void processPixel(int x, int y) { color_t c = rgba_blender_neg_bw(m_palette->getEntry(*m_srcAddress), m_color, 255); - *m_dstAddress = m_rgbmap->mapColor(rgba_getr(c), - rgba_getg(c), - rgba_getb(c), - rgba_geta(c)); + *m_dstAddress = m_rgbmap->mapColor(c); } private: diff --git a/src/doc/CMakeLists.txt b/src/doc/CMakeLists.txt index d1c5973d1..d78b5922d 100644 --- a/src/doc/CMakeLists.txt +++ b/src/doc/CMakeLists.txt @@ -1,4 +1,5 @@ # Aseprite Document Library +# Copyright (C) 2020 Igara Studio S.A. # Copyright (C) 2001-2018 David Capello if(WIN32) @@ -52,7 +53,7 @@ add_library(doc-lib palette_io.cpp primitives.cpp remap.cpp - rgbmap.cpp + rgbmap_rgb5a3.cpp selected_frames.cpp selected_layers.cpp slice.cpp diff --git a/src/doc/LICENSE.txt b/src/doc/LICENSE.txt index 8ddfb5031..da9a44fa3 100644 --- a/src/doc/LICENSE.txt +++ b/src/doc/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (c) 2018-2019 Igara Studio S.A. +Copyright (c) 2018-2020 Igara Studio S.A. Copyright (c) 2001-2018 David Capello Permission is hereby granted, free of charge, to any person obtaining diff --git a/src/doc/doc.h b/src/doc/doc.h index 17203c193..a58c20674 100644 --- a/src/doc/doc.h +++ b/src/doc/doc.h @@ -1,5 +1,5 @@ // Aseprite Document Library -// Copyright (C) 2019 Igara Studio S.A. +// Copyright (C) 2019-2020 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This file is released under the terms of the MIT license. @@ -33,6 +33,7 @@ #include "doc/primitives_fast.h" #include "doc/remap.h" #include "doc/rgbmap.h" +#include "doc/rgbmap_rgb5a3.h" #include "doc/slice.h" #include "doc/slices.h" #include "doc/sprite.h" diff --git a/src/doc/rgbmap.h b/src/doc/rgbmap.h index 30ab666a3..54c40a644 100644 --- a/src/doc/rgbmap.h +++ b/src/doc/rgbmap.h @@ -1,6 +1,5 @@ // Aseprite Document Library // Copyright (c) 2020 Igara Studio S.A. -// Copyright (c) 2001-2016 David Capello // // This file is released under the terms of the MIT license. // Read LICENSE.txt for more information. @@ -10,48 +9,29 @@ #pragma once #include "base/debug.h" -#include "base/disable_copying.h" -#include "doc/object.h" - -#include +#include "doc/color.h" namespace doc { - class Palette; - - // It acts like a cache for Palette:findBestfit() calls. + // Matches a RGBA value with an index in a color palette (doc::Palette). class RgbMap { - // Bit activated on m_map entries that aren't yet calculated. - const int INVALID = 256; - public: - RgbMap(); + virtual ~RgbMap() { } - bool match(const Palette* palette) const; - void regenerate(const Palette* palette, int mask_index); + // Should return the best index in a palette that matches the given RGBA values. + virtual int mapColor(const color_t rgba) const = 0; - int mapColor(int r, int g, int b, int a) const { + int mapColor(const int r, + const int g, + const int b, + const int a) const { ASSERT(r >= 0 && r < 256); ASSERT(g >= 0 && g < 256); ASSERT(b >= 0 && b < 256); ASSERT(a >= 0 && a < 256); - // bits -> bbbbbgggggrrrrraaa - int i = (a>>5) | ((b>>3) << 3) | ((g>>3) << 8) | ((r>>3) << 13); - int v = m_map[i]; - return (v & INVALID) ? generateEntry(i, r, g, b, a): v; + return mapColor(rgba(r, g, b, a)); } - int maskIndex() const { return m_maskIndex; } - - private: - int generateEntry(int i, int r, int g, int b, int a) const; - - mutable std::vector m_map; - const Palette* m_palette; - int m_modifications; - int m_maskIndex; - - DISABLE_COPYING(RgbMap); }; } // namespace doc diff --git a/src/doc/rgbmap.cpp b/src/doc/rgbmap_rgb5a3.cpp similarity index 80% rename from src/doc/rgbmap.cpp rename to src/doc/rgbmap_rgb5a3.cpp index 1d56fba18..677779c4a 100644 --- a/src/doc/rgbmap.cpp +++ b/src/doc/rgbmap_rgb5a3.cpp @@ -9,7 +9,7 @@ #include "config.h" #endif -#include "doc/rgbmap.h" +#include "doc/rgbmap_rgb5a3.h" #include "doc/color_scales.h" #include "doc/palette.h" @@ -22,7 +22,7 @@ namespace doc { #define ASIZE 8 #define MAPSIZE (RSIZE*GSIZE*BSIZE*ASIZE) -RgbMap::RgbMap() +RgbMapRGB5A3::RgbMapRGB5A3() : m_map(MAPSIZE) , m_palette(NULL) , m_modifications(0) @@ -30,13 +30,13 @@ RgbMap::RgbMap() { } -bool RgbMap::match(const Palette* palette) const +bool RgbMapRGB5A3::match(const Palette* palette) const { return (m_palette == palette && m_modifications == palette->getModifications()); } -void RgbMap::regenerate(const Palette* palette, int mask_index) +void RgbMapRGB5A3::regenerate(const Palette* palette, int mask_index) { m_palette = palette; m_modifications = palette->getModifications(); @@ -47,7 +47,7 @@ void RgbMap::regenerate(const Palette* palette, int mask_index) entry |= INVALID; } -int RgbMap::generateEntry(int i, int r, int g, int b, int a) const +int RgbMapRGB5A3::generateEntry(int i, int r, int g, int b, int a) const { return m_map[i] = m_palette->findBestfit( diff --git a/src/doc/rgbmap_rgb5a3.h b/src/doc/rgbmap_rgb5a3.h new file mode 100644 index 000000000..e4a108361 --- /dev/null +++ b/src/doc/rgbmap_rgb5a3.h @@ -0,0 +1,61 @@ +// Aseprite Document Library +// Copyright (c) 2020 Igara Studio S.A. +// Copyright (c) 2001-2016 David Capello +// +// This file is released under the terms of the MIT license. +// Read LICENSE.txt for more information. + +#ifndef DOC_RGBMAP_RGB5A3_H_INCLUDED +#define DOC_RGBMAP_RGB5A3_H_INCLUDED +#pragma once + +#include "base/debug.h" +#include "base/disable_copying.h" +#include "doc/object.h" +#include "doc/rgbmap.h" + +#include + +namespace doc { + + class Palette; + + // It acts like a cache for Palette:findBestfit() calls. + class RgbMapRGB5A3 : public RgbMap { + // Bit activated on m_map entries that aren't yet calculated. + const int INVALID = 256; + + public: + RgbMapRGB5A3(); + + bool match(const Palette* palette) const; + void regenerate(const Palette* palette, int mask_index); + + // RgbMap impl + int mapColor(const color_t rgba) const override { + const int r = rgba_getr(rgba); + const int g = rgba_getg(rgba); + const int b = rgba_getb(rgba); + const int a = rgba_geta(rgba); + // bits -> bbbbbgggggrrrrraaa + const int i = (a>>5) | ((b>>3) << 3) | ((g>>3) << 8) | ((r>>3) << 13); + const int v = m_map[i]; + return (v & INVALID) ? generateEntry(i, r, g, b, a): v; + } + + int maskIndex() const { return m_maskIndex; } + + private: + int generateEntry(int i, int r, int g, int b, int a) const; + + mutable std::vector m_map; + const Palette* m_palette; + int m_modifications; + int m_maskIndex; + + DISABLE_COPYING(RgbMapRGB5A3); + }; + +} // namespace doc + +#endif diff --git a/src/doc/sprite.cpp b/src/doc/sprite.cpp index 05c5936e2..f066284e6 100644 --- a/src/doc/sprite.cpp +++ b/src/doc/sprite.cpp @@ -21,7 +21,7 @@ #include "doc/palette.h" #include "doc/primitives.h" #include "doc/remap.h" -#include "doc/rgbmap.h" +#include "doc/rgbmap_rgb5a3.h" #include "doc/tag.h" #include @@ -357,7 +357,7 @@ RgbMap* Sprite::rgbMap(frame_t frame, RgbMapFor forLayer) const -1: transparentColor()); if (m_rgbMap == NULL) { - m_rgbMap = new RgbMap(); + m_rgbMap = new RgbMapRGB5A3; m_rgbMap->regenerate(palette(frame), maskIndex); } else if (!m_rgbMap->match(palette(frame)) || diff --git a/src/doc/sprite.h b/src/doc/sprite.h index 1e6915676..79b1b0125 100644 --- a/src/doc/sprite.h +++ b/src/doc/sprite.h @@ -1,5 +1,5 @@ // Aseprite Document Library -// Copyright (C) 2018-2019 Igara Studio S.A. +// Copyright (C) 2018-2020 Igara Studio S.A. // Copyright (C) 2001-2018 David Capello // // This file is released under the terms of the MIT license. @@ -42,6 +42,7 @@ namespace doc { class Palette; class Remap; class RgbMap; + class RgbMapRGB5A3; class SelectedFrames; typedef std::vector PalettesList; @@ -199,7 +200,7 @@ namespace doc { gfx::Rect m_gridBounds; // grid settings // Current rgb map - mutable RgbMap* m_rgbMap; + mutable RgbMapRGB5A3* m_rgbMap; Tags m_tags; Slices m_slices; diff --git a/src/filters/brightness_contrast_filter.cpp b/src/filters/brightness_contrast_filter.cpp index 30b2b5a2f..3d67f3d09 100644 --- a/src/filters/brightness_contrast_filter.cpp +++ b/src/filters/brightness_contrast_filter.cpp @@ -138,10 +138,7 @@ void BrightnessContrastFilter::applyToIndexed(FilterManager* filterMgr) color_t c = pal->getEntry(*(src_address++)); applyFilterToRgb(target, c); - *(dst_address++) = rgbmap->mapColor(rgba_getr(c), - rgba_getg(c), - rgba_getb(c), - rgba_geta(c)); + *(dst_address++) = rgbmap->mapColor(c); } } diff --git a/src/filters/hue_saturation_filter.cpp b/src/filters/hue_saturation_filter.cpp index 1ede7b0cc..8f4a40551 100644 --- a/src/filters/hue_saturation_filter.cpp +++ b/src/filters/hue_saturation_filter.cpp @@ -168,10 +168,7 @@ void HueSaturationFilter::applyToIndexed(FilterManager* filterMgr) color_t c = pal->getEntry(*(src_address++)); applyFilterToRgb(target, c); - *(dst_address++) = rgbmap->mapColor(rgba_getr(c), - rgba_getg(c), - rgba_getb(c), - rgba_geta(c)); + *(dst_address++) = rgbmap->mapColor(c); } } diff --git a/src/render/quantization.cpp b/src/render/quantization.cpp index ab6d39f4d..657ced0b1 100644 --- a/src/render/quantization.cpp +++ b/src/render/quantization.cpp @@ -177,7 +177,7 @@ Image* convert_pixel_format( if (a == 0) *dst_it = new_mask_color; else if (rgbmap) - *dst_it = rgbmap->mapColor(r, g, b, a); + *dst_it = rgbmap->mapColor(c); else *dst_it = palette->findBestfit(r, g, b, a, new_mask_color); } From 886fdf8b3f11d0840b5780422a7f0d7c7137498d Mon Sep 17 00:00:00 2001 From: Gaspar Capello Date: Fri, 10 Apr 2020 15:35:11 -0300 Subject: [PATCH 3/9] Add OctreeMap as an alternative RgbMap implementation to RgbMapRGB53A There is a new experimental option to switch between both RgbMap implementations. --- data/pref.xml | 1 + data/strings/en.ini | 5 + data/widgets/options.xml | 4 + src/app/CMakeLists.txt | 1 + src/app/commands/cmd_options.cpp | 7 + src/app/commands/new_params.cpp | 23 +- src/app/file/gif_format.cpp | 2 +- src/app/pref/preferences.cpp | 8 + src/app/pref/preferences.h | 1 + src/app/script/values.cpp | 3 +- src/app/ui/rgbmap_algorithm_selector.cpp | 40 +++ src/app/ui/rgbmap_algorithm_selector.h | 26 ++ src/doc/CMakeLists.txt | 3 +- src/doc/octree_map.cpp | 297 +++++++++++++++++++++++ src/doc/octree_map.h | 169 +++++++++++++ src/doc/palette.cpp | 25 ++ src/doc/palette.h | 2 + src/doc/rgbmap.h | 4 + src/doc/rgbmap_algorithm.h | 21 ++ src/doc/rgbmap_rgb5a3.cpp | 16 +- src/doc/rgbmap_rgb5a3.h | 4 +- src/doc/sprite.cpp | 44 ++-- src/doc/sprite.h | 8 +- 23 files changed, 683 insertions(+), 31 deletions(-) create mode 100644 src/app/ui/rgbmap_algorithm_selector.cpp create mode 100644 src/app/ui/rgbmap_algorithm_selector.h create mode 100644 src/doc/octree_map.cpp create mode 100644 src/doc/octree_map.h create mode 100644 src/doc/rgbmap_algorithm.h diff --git a/data/pref.xml b/data/pref.xml index 4e220b006..07be3977f 100644 --- a/data/pref.xml +++ b/data/pref.xml @@ -190,6 +190,7 @@