Add palette gradient based on Hue (fix #2171)

This commit is contained in:
Gaspar Capello 2020-08-12 17:04:25 -03:00
parent 432e8d9943
commit e62efb4124
5 changed files with 99 additions and 6 deletions

View File

@ -57,6 +57,7 @@
#include "doc/image.h"
#include "doc/image_impl.h"
#include "doc/palette.h"
#include "doc/palette_gradient_type.h"
#include "doc/primitives.h"
#include "doc/remap.h"
#include "doc/rgbmap.h"
@ -924,16 +925,21 @@ void ColorBar::onSortBy(SortPaletteBy channel)
setPalette(&newPalette, "Sort Colors");
}
void ColorBar::onGradient()
void ColorBar::onGradient(GradientType gradientType)
{
int index1, index2;
if (!m_paletteView.getSelectedRange(index1, index2))
return;
Palette newPalette(*get_current_palette());
newPalette.makeGradient(index1, index2);
setPalette(&newPalette, "Gradient");
if (gradientType == GradientType::LINEAR) {
newPalette.makeGradient(index1, index2);
setPalette(&newPalette, "Gradient");
}
else {
newPalette.makeHueGradient(index1, index2);
setPalette(&newPalette, "Gradient by Hue");
}
}
void ColorBar::setAscending(bool ascending)
@ -1249,6 +1255,7 @@ void ColorBar::showPaletteSortOptions()
MenuItem
rev("Reverse Colors"),
grd("Gradient"),
grh("Gradient by Hue"),
hue("Sort by Hue"),
sat("Sort by Saturation"),
bri("Sort by Brightness"),
@ -1261,6 +1268,7 @@ void ColorBar::showPaletteSortOptions()
des("Descending");
menu.addChild(&rev);
menu.addChild(&grd);
menu.addChild(&grh);
menu.addChild(new ui::MenuSeparator);
menu.addChild(&hue);
menu.addChild(&sat);
@ -1279,7 +1287,8 @@ void ColorBar::showPaletteSortOptions()
else des.setSelected(true);
rev.Click.connect([this]{ onReverseColors(); });
grd.Click.connect([this]{ onGradient(); });
grd.Click.connect([this]{ onGradient(GradientType::LINEAR); });
grh.Click.connect([this]{ onGradient(GradientType::HUE); });
hue.Click.connect([this]{ onSortBy(SortPaletteBy::HUE); });
sat.Click.connect([this]{ onSortBy(SortPaletteBy::SATURATION); });
bri.Click.connect([this]{ onSortBy(SortPaletteBy::VALUE); });

View File

@ -17,6 +17,7 @@
#include "app/ui/color_button.h"
#include "app/ui/input_chain_element.h"
#include "app/ui/palette_view.h"
#include "doc/palette_gradient_type.h"
#include "doc/pixel_format.h"
#include "doc/sort_palette.h"
#include "obs/connection.h"
@ -119,7 +120,7 @@ namespace app {
void onPickSpectrum(const app::Color& color, ui::MouseButton button);
void onReverseColors();
void onSortBy(doc::SortPaletteBy channel);
void onGradient();
void onGradient(GradientType gradientType);
void onFixWarningClick(ColorButton* colorButton, ui::Button* warningIcon);
void onTimerTick();
void setAscending(bool ascending);

View File

@ -13,7 +13,10 @@
#include "base/base.h"
#include "doc/image.h"
#include "doc/palette_gradient_type.h"
#include "doc/remap.h"
#include "gfx/hsv.h"
#include "gfx/rgb.h"
#include <algorithm>
#include <limits>
@ -206,6 +209,64 @@ void Palette::makeGradient(int from, int to)
}
}
void Palette::makeHueGradient(int from, int to)
{
int r1, g1, b1, a1;
int r2, g2, b2, a2;
int i, n;
ASSERT(from >= 0 && from < size());
ASSERT(to >= 0 && to < size());
if (from > to)
std::swap(from, to);
n = to - from;
if (n < 2)
return;
r1 = rgba_getr(getEntry(from));
g1 = rgba_getg(getEntry(from));
b1 = rgba_getb(getEntry(from));
a1 = rgba_geta(getEntry(from));
r2 = rgba_getr(getEntry(to));
g2 = rgba_getg(getEntry(to));
b2 = rgba_getb(getEntry(to));
a2 = rgba_geta(getEntry(to));
gfx::Hsv hsv1(gfx::Rgb(r1, g1, b1));
gfx::Hsv hsv2(gfx::Rgb(r2, g2, b2));
double h1 = hsv1.hue();
double s1 = hsv1.saturation();
double v1 = hsv1.value();
double h2 = hsv2.hue();
double s2 = hsv2.saturation();
double v2 = hsv2.value();
if (h2 >= h1) {
if (h2-h1 > 180.0)
h2 = h2 - 360.0;
}
else {
if (h1-h2 > 180.0)
h2 = h2 + 360.0;
}
gfx::Hsv hsv;
for (i=from+1; i<to; ++i) {
double t = double(i - from) / double(n);
hsv.hue(h1 + (h2 - h1) * t);
hsv.saturation(s1 + (s2 - s1) * t);
hsv.value(v1 + (v2 - v1) * t);
int alpha = int(a1 + double(a2 - a1) * t);
gfx::Rgb rgb(hsv);
setEntry(i, rgba(rgb.red(), rgb.green(), rgb.blue(), alpha));
}
}
int Palette::findExactMatch(int r, int g, int b, int a, int mask_index) const
{
for (int i=0; i<(int)m_colors.size(); ++i)

View File

@ -13,6 +13,7 @@
#include "doc/color.h"
#include "doc/frame.h"
#include "doc/object.h"
#include "doc/palette_gradient_type.h"
#include <vector>
#include <string>
@ -90,6 +91,7 @@ namespace doc {
void makeBlack();
void makeGradient(int from, int to);
void makeHueGradient(int from, int to);
int findExactMatch(int r, int g, int b, int a, int mask_index) const;
int findBestfit(int r, int g, int b, int a, int mask_index) const;

View File

@ -0,0 +1,20 @@
// Aseprite Document Library
// Copyright (c) 2020 Igara Studio S.A.
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef DOC_PALETTE_GRADIENT_TYPE_H_INCLUDED
#define DOC_PALETTE_GRADIENT_TYPE_H_INCLUDED
#pragma once
namespace doc {
enum class GradientType {
LINEAR,
HUE,
};
} // namespace doc
#endif