Move gradient rendering code to render library

This commit is contained in:
David Capello 2017-06-09 17:18:28 -03:00
parent 0bab4e7ae7
commit 317b493fb7
6 changed files with 148 additions and 80 deletions

View File

@ -6,7 +6,6 @@
#include "app/modules/palettes.h"
#include "base/unique_ptr.h"
#include "base/vector2d.h"
#include "doc/blend_funcs.h"
#include "doc/image_impl.h"
#include "doc/layer.h"
@ -18,6 +17,7 @@
#include "gfx/hsv.h"
#include "gfx/rgb.h"
#include "render/dithering.h"
#include "render/gradient.h"
namespace app {
namespace tools {
@ -897,83 +897,12 @@ public:
return;
}
// If there is no vector defining the gradient (just one point),
// the "gradient" will be just "c0"
if (strokes[0].firstPoint().x == strokes[0].lastPoint().x &&
strokes[0].firstPoint().y == strokes[0].lastPoint().y) {
m_tmpImage->clear(c0);
return;
}
const render::DitheringMatrix& m_matrix =
loop->getDitheringMatrix();
base::Vector2d<double>
u(strokes[0].firstPoint().x,
strokes[0].firstPoint().y),
v(strokes[0].lastPoint().x,
strokes[0].lastPoint().y), w;
w = v - u;
// As we use non-premultiplied RGB values, we need correct RGB
// values on each stop. So in case that one color has alpha=0
// (complete transparent), use the RGB values of the
// non-transparent color in the other stop point.
if (doc::rgba_geta(c0) == 0 &&
doc::rgba_geta(c1) != 0) {
c0 = (c1 & rgba_rgb_mask);
}
else if (doc::rgba_geta(c0) != 0 &&
doc::rgba_geta(c1) == 0) {
c1 = (c0 & rgba_rgb_mask);
}
const double r0 = double(doc::rgba_getr(c0)) / 255.0;
const double g0 = double(doc::rgba_getg(c0)) / 255.0;
const double b0 = double(doc::rgba_getb(c0)) / 255.0;
const double a0 = double(doc::rgba_geta(c0)) / 255.0;
const double r1 = double(doc::rgba_getr(c1)) / 255.0;
const double g1 = double(doc::rgba_getg(c1)) / 255.0;
const double b1 = double(doc::rgba_getb(c1)) / 255.0;
const double a1 = double(doc::rgba_geta(c1)) / 255.0;
doc::LockImageBits<doc::RgbTraits> bits(m_tmpImage.get());
auto it = bits.begin();
const int width = m_tmpImage->width();
const int height = m_tmpImage->height();
if (m_matrix.rows() == 1 && m_matrix.cols() == 1) {
for (int y=0; y<height; ++y) {
for (int x=0; x<width; ++x, ++it) {
base::Vector2d<double> q(x, y);
q -= u;
double f = (q * w.normalize()) / (w.magnitude());
doc::color_t c;
if (f < 0.0) c = c0;
else if (f > 1.0) c = c1;
else {
c = doc::rgba(int(255.0 * (r0 + f*(r1-r0))),
int(255.0 * (g0 + f*(g1-g0))),
int(255.0 * (b0 + f*(b1-b0))),
int(255.0 * (a0 + f*(a1-a0))));
}
*it = c;
}
}
}
else {
for (int y=0; y<height; ++y) {
for (int x=0; x<width; ++x, ++it) {
base::Vector2d<double> q(x, y);
q -= u;
double f = (q * w.normalize()) / (w.magnitude());
*it = (f*m_matrix.maxValue() < m_matrix(y, x) ? c0: c1);
}
}
}
render::render_rgba_linear_gradient(
m_tmpImage.get(),
strokes[0].firstPoint(),
strokes[0].lastPoint(),
c0, c1,
loop->getDitheringMatrix());
}
protected:

View File

@ -3,6 +3,7 @@
add_library(render-lib
get_sprite_pixel.cpp
gradient.cpp
ordered_dither.cpp
quantization.cpp
render.cpp

View File

@ -1,4 +1,4 @@
Copyright (c) 2001-2014 David Capello
Copyright (c) 2001-2017 David Capello
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

View File

@ -1,4 +1,4 @@
# Aseprite Render Library
*Copyright (C) 2001-2014 David Capello*
*Copyright (C) 2001-2017 David Capello*
> Distributed under [MIT license](LICENSE.txt)

106
src/render/gradient.cpp Normal file
View File

@ -0,0 +1,106 @@
// Aseprite Render Library
// Copyright (c) 2017 David Capello
//
// 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 "render/gradient.h"
#include "base/vector2d.h"
#include "doc/image.h"
#include "doc/image_impl.h"
#include "render/dithering_matrix.h"
namespace render {
void render_rgba_linear_gradient(
doc::Image* img,
const gfx::Point p0,
const gfx::Point p1,
doc::color_t c0,
doc::color_t c1,
const render::DitheringMatrix& matrix)
{
ASSERT(img->pixelFormat() == doc::IMAGE_RGB);
if (img->pixelFormat() != doc::IMAGE_RGB) {
return;
}
// If there is no vector defining the gradient (just one point),
// the "gradient" will be just "c0"
if (p0 == p1) {
img->clear(c0);
return;
}
base::Vector2d<double>
u(p0.x, p0.y),
v(p1.x, p1.y), w;
w = v - u;
// As we use non-premultiplied RGB values, we need correct RGB
// values on each stop. So in case that one color has alpha=0
// (complete transparent), use the RGB values of the
// non-transparent color in the other stop point.
if (doc::rgba_geta(c0) == 0 &&
doc::rgba_geta(c1) != 0) {
c0 = (c1 & doc::rgba_rgb_mask);
}
else if (doc::rgba_geta(c0) != 0 &&
doc::rgba_geta(c1) == 0) {
c1 = (c0 & doc::rgba_rgb_mask);
}
const double r0 = double(doc::rgba_getr(c0)) / 255.0;
const double g0 = double(doc::rgba_getg(c0)) / 255.0;
const double b0 = double(doc::rgba_getb(c0)) / 255.0;
const double a0 = double(doc::rgba_geta(c0)) / 255.0;
const double r1 = double(doc::rgba_getr(c1)) / 255.0;
const double g1 = double(doc::rgba_getg(c1)) / 255.0;
const double b1 = double(doc::rgba_getb(c1)) / 255.0;
const double a1 = double(doc::rgba_geta(c1)) / 255.0;
doc::LockImageBits<doc::RgbTraits> bits(img);
auto it = bits.begin();
const int width = img->width();
const int height = img->height();
if (matrix.rows() == 1 && matrix.cols() == 1) {
for (int y=0; y<height; ++y) {
for (int x=0; x<width; ++x, ++it) {
base::Vector2d<double> q(x, y);
q -= u;
double f = (q * w.normalize()) / (w.magnitude());
doc::color_t c;
if (f < 0.0) c = c0;
else if (f > 1.0) c = c1;
else {
c = doc::rgba(int(255.0 * (r0 + f*(r1-r0))),
int(255.0 * (g0 + f*(g1-g0))),
int(255.0 * (b0 + f*(b1-b0))),
int(255.0 * (a0 + f*(a1-a0))));
}
*it = c;
}
}
}
else {
for (int y=0; y<height; ++y) {
for (int x=0; x<width; ++x, ++it) {
base::Vector2d<double> q(x, y);
q -= u;
double f = (q * w.normalize()) / (w.magnitude());
*it = (f*matrix.maxValue() < matrix(y, x) ? c0: c1);
}
}
}
}
} // namespace render

32
src/render/gradient.h Normal file
View File

@ -0,0 +1,32 @@
// Aseprite Render Library
// Copyright (c) 2017 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef RENDER_GRADIENT_H_INCLUDED
#define RENDER_GRADIENT_H_INCLUDED
#pragma once
#include "doc/color.h"
#include "gfx/point.h"
namespace doc {
class Image;
}
namespace render {
class DitheringMatrix;
void render_rgba_linear_gradient(
doc::Image* img,
const gfx::Point p0,
const gfx::Point p1,
doc::color_t c0,
doc::color_t c1,
const render::DitheringMatrix& matrix);
} // namespace render
#endif