|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Toonz includes
|
|
Toshihiro Shimizu |
890ddd |
#include "tpixelutils.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tpalette.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tcolorstyles.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "timage_io.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tropcm.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "ttile.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/toonzscene.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tcamera.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "autoadjust.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "autopos.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "cleanuppalette.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "cleanupcommon.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tmsgcore.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/cleanupparameters.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tcleanupper.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
using namespace CleanupTypes;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/* The Cleanup Process Reworked - EXPLANATION (by Daniele)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
INTRODUCTION:
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
The purpose of a Cleanup Process is hereby intended as the task of transforming
|
|
Toshihiro Shimizu |
890ddd |
a fullcolor image (any bpp, matte supported*) into a TRasterCM32 -
|
|
Toshihiro Shimizu |
890ddd |
that is, a colormap image - given an externally specified palette of ink colors to
|
|
Toshihiro Shimizu |
890ddd |
be recognized. No paint color is assumed at this stage.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Typically, artists draw outlines using a black or dark color, whereas different hues are
|
|
Toshihiro Shimizu |
890ddd |
used to mark lines that denote shadows or lights on characters.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Additional processing steps include the ability to recognize and counter any linear
|
|
Toshihiro Shimizu |
890ddd |
transformation in the image which is 'signaled' by the presence of (black) pegbar holes,
|
|
Toshihiro Shimizu |
890ddd |
so that the countering linear transformation maps those peg holes in the usual centered
|
|
Toshihiro Shimizu |
890ddd |
horizontal fashion.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Post-processing include despeckling (ie removal or recoloration of little blots with
|
|
Toshihiro Shimizu |
890ddd |
uniform color), and tones' brigthness/contrast manipulation.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
(*) The image is first overed on top of a white background
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
CONSTRAINTS:
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
We assume the following constraints throughout the process:
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
- Palette colors:
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
* Color 0 represents the PAPER color, and will just substitute it in the colormap.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
* Colors with index >= 2 are MATCH-LINE colors, and their HUE ONLY (the H in HSV coordinates)
|
|
Toshihiro Shimizu |
890ddd |
is essential to line recognition. The hue of image pixels is compared to that of each
|
|
Toshihiro Shimizu |
890ddd |
matchline color - and the nearest matchline color is associated to that pixel.
|
|
Toshihiro Shimizu |
890ddd |
If that associated matchline color is still too 'hue-distant' from the pixel color
|
|
Toshihiro Shimizu |
890ddd |
(beyond a user-specified parameter), the pixel is ignored (ie associated to paper).
|
|
Toshihiro Shimizu |
890ddd |
Furthermore, each matchline color also has a parameter corresponding to a saturation
|
|
Toshihiro Shimizu |
890ddd |
threshold; pixels whose color's saturation is below the threshold specified by the
|
|
Toshihiro Shimizu |
890ddd |
associated color are reassociated to the PAPER color.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
* Color 1 represents the OUTLINE color, and its VALUE (the V in HSV coordinates) is
|
|
Toshihiro Shimizu |
890ddd |
assumed to be the image's lowest. Its H and S components are unused.
|
|
Toshihiro Shimizu |
890ddd |
Pixels whose value is below this value + a user-defined threshold parameter are
|
|
Toshihiro Shimizu |
890ddd |
'outline-PRONE' pixels (even matchline-associated pixels can be).
|
|
Toshihiro Shimizu |
890ddd |
They are assumed to be full outline pixels if their CHROMA (S*V) is above a
|
|
Toshihiro Shimizu |
890ddd |
'Color threshold'. This condition lets the user settle how outline/matchline
|
|
Toshihiro Shimizu |
890ddd |
disputed pixels should be considered.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
- The Colormap tone for a pixel is extracted according to these rules:
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
* Paper pixels are completely transparent (tone = 255).
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
* Undisputed matchline colors build the tone upon the pixel's Saturation, scaled
|
|
Toshihiro Shimizu |
890ddd |
so that 1.0 maps to 0, and the saturation threshold for that matchline
|
|
Toshihiro Shimizu |
890ddd |
color maps to 255.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
* Undisputed Outline colors do similarly, with the Value.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
* Disputed outline/matchline colors result in the blend PRODUCT of the above tones.
|
|
Toshihiro Shimizu |
890ddd |
This makes the tone smoother on outline/matchline intersections.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//**************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Local namespace stuff
|
|
Toshihiro Shimizu |
890ddd |
//**************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
namespace
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//some useful functions for doing math
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline double affMV1(const TAffine &aff, double v1, double v2)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return aff.a11 * v1 + aff.a12 * v2 + aff.a13;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline double affMV2(const TAffine &aff, double v1, double v2)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return aff.a21 * v1 + aff.a22 * v2 + aff.a23;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=========================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! Auxiliary class for HSV (toonz 4.x style)
|
|
Toshihiro Shimizu |
890ddd |
struct HSVColor {
|
|
Toshihiro Shimizu |
890ddd |
double m_h;
|
|
Toshihiro Shimizu |
890ddd |
double m_s;
|
|
Toshihiro Shimizu |
890ddd |
double m_v;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
HSVColor(double h = 0, double s = 0, double v = 0)
|
|
Toshihiro Shimizu |
890ddd |
: m_h(h), m_s(s), m_v(v) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
static HSVColor fromRGB(double r, double g, double b);
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
HSVColor HSVColor::fromRGB(double r, double g, double b)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
double h, s, v;
|
|
Toshihiro Shimizu |
890ddd |
double max, min, delta;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
max = tmax(r, g, b);
|
|
Toshihiro Shimizu |
890ddd |
min = tmin(r, g, b);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
v = max;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (max != 0)
|
|
Toshihiro Shimizu |
890ddd |
s = (max - min) / max;
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
s = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (s == 0)
|
|
Toshihiro Shimizu |
890ddd |
h = 0;
|
|
Toshihiro Shimizu |
890ddd |
else {
|
|
Toshihiro Shimizu |
890ddd |
delta = max - min;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (r == max)
|
|
Toshihiro Shimizu |
890ddd |
h = (g - b) / delta;
|
|
Toshihiro Shimizu |
890ddd |
else if (g == max)
|
|
Toshihiro Shimizu |
890ddd |
h = 2.0 + (b - r) / delta;
|
|
Toshihiro Shimizu |
890ddd |
else if (b == max)
|
|
Toshihiro Shimizu |
890ddd |
h = 4.0 + (r - g) / delta;
|
|
Toshihiro Shimizu |
890ddd |
h = h * 60.0;
|
|
Toshihiro Shimizu |
890ddd |
if (h < 0)
|
|
Toshihiro Shimizu |
890ddd |
h += 360.0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return HSVColor(h, s, v);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=========================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! Precomputation data about target colors
|
|
Toshihiro Shimizu |
890ddd |
struct TargetColorData {
|
|
Toshihiro Shimizu |
890ddd |
int m_idx; //!< Palette color index
|
|
Toshihiro Shimizu |
890ddd |
HSVColor m_hsv; //!< HSV coordinates of the color
|
|
Toshihiro Shimizu |
890ddd |
double m_saturationLower; //!< Pixel colors associated with this color must be above this
|
|
Toshihiro Shimizu |
890ddd |
double m_hueLower, m_hueUpper; //!< Pixel colors associated with this color must in this range
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
TargetColorData(const TargetColor &color)
|
|
Toshihiro Shimizu |
890ddd |
: m_idx(-1), m_hsv(HSVColor::fromRGB(color.m_color.r / 255.0, color.m_color.g / 255.0, color.m_color.b / 255.0)), m_saturationLower(1.0 - color.m_threshold / 100.0), m_hueLower(m_hsv.m_h - color.m_hRange * 0.5), m_hueUpper(m_hsv.m_h + color.m_hRange * 0.5)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_hueLower < 0.0)
|
|
Toshihiro Shimizu |
890ddd |
m_hueLower += 360.0;
|
|
Toshihiro Shimizu |
890ddd |
if (m_hueUpper > 360.0)
|
|
Toshihiro Shimizu |
890ddd |
m_hueUpper -= 360.0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=========================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! Birghtness/Contrast color transform data
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define MAX_N_PENCILS 8
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/* the following must be updated at every change in palette content */
|
|
Toshihiro Shimizu |
890ddd |
int N_pencils = 4; /* not counting autoclose */
|
|
Toshihiro Shimizu |
890ddd |
TPixelRGBM32 Pencil[MAX_N_PENCILS + 1]; /* last is autoclose pencil */
|
|
Toshihiro Shimizu |
890ddd |
int Pencil_index[MAX_N_PENCILS + 1]; /* "" */
|
|
Toshihiro Shimizu |
890ddd |
int Pencil_id[MAX_N_PENCILS + 1]; /* "" */
|
|
Toshihiro Shimizu |
890ddd |
TPixelRGBM32 Paper = TPixel32::White;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=========================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! Birghtness/Contrast color transform structure
|
|
Toshihiro Shimizu |
890ddd |
class TransfFunction
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
USHORT TransfFun[(MAX_N_PENCILS + 1) << 8];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void setTransfFun(int pencil, int b1, int c1)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int i, p1, p2, brig, cont, max;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
cont = 255 - c1;
|
|
Toshihiro Shimizu |
890ddd |
brig = 255 - b1;
|
|
Toshihiro Shimizu |
890ddd |
max = 255;
|
|
Toshihiro Shimizu |
890ddd |
notLessThan(1, cont);
|
|
Toshihiro Shimizu |
890ddd |
p2 = brig;
|
|
Toshihiro Shimizu |
890ddd |
p1 = p2 - cont;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i <= p1; i++)
|
|
Toshihiro Shimizu |
890ddd |
TransfFun[pencil << 8 | i] = 0;
|
|
Toshihiro Shimizu |
890ddd |
for (; i < p2; i++)
|
|
Toshihiro Shimizu |
890ddd |
TransfFun[pencil << 8 | i] = tmin(max, max * (i - p1) / cont);
|
|
Toshihiro Shimizu |
890ddd |
for (; i < 256; i++)
|
|
Toshihiro Shimizu |
890ddd |
TransfFun[pencil << 8 | i] = max;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
TransfFunction(const TargetColors &colors)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
memset(TransfFun, 0, sizeof TransfFun);
|
|
Toshihiro Shimizu |
890ddd |
int count = tmin(colors.getColorCount(), MAX_N_PENCILS);
|
|
Toshihiro Shimizu |
890ddd |
for (int p = 0; p < count; p++) {
|
|
Toshihiro Shimizu |
890ddd |
int brightness = troundp(2.55 * colors.getColor(p).m_brightness);
|
|
Toshihiro Shimizu |
890ddd |
int contrast = troundp(2.55 * colors.getColor(p).m_contrast);
|
|
Toshihiro Shimizu |
890ddd |
setTransfFun(p, brightness, contrast);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
USHORT *getTransfFun() { return TransfFun; }
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=========================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! Brightness/Contrast functions
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void brightnessContrast(const TRasterCM32P &cm, const TargetColors &colors)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TransfFunction transform(colors);
|
|
Toshihiro Shimizu |
890ddd |
USHORT *transf_fun = transform.getTransfFun();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int ink, tone;
|
|
Toshihiro Shimizu |
890ddd |
int newTone, newInk;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (int y = 0; y < cm->getLy(); ++y) {
|
|
Toshihiro Shimizu |
890ddd |
TPixelCM32 *pix = cm->pixels(y);
|
|
Toshihiro Shimizu |
890ddd |
TPixelCM32 *endPix = pix + cm->getLx();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (; pix < endPix; ++pix) {
|
|
Toshihiro Shimizu |
890ddd |
tone = pix->getTone();
|
|
Toshihiro Shimizu |
890ddd |
if (tone < 255) {
|
|
Toshihiro Shimizu |
890ddd |
ink = pix->getInk();
|
|
Toshihiro Shimizu |
890ddd |
newTone = transf_fun[ink << 8 | tone];
|
|
Toshihiro Shimizu |
890ddd |
newInk = (newTone == 255) ? 0 : colors.getColor(ink).m_index;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
*pix = TPixelCM32(newInk, 0, newTone);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void brightnessContrastGR8(const TRasterCM32P &cm, const TargetColors &colors)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TransfFunction transform(colors);
|
|
Toshihiro Shimizu |
890ddd |
USHORT *transf_fun = transform.getTransfFun();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int val, black = colors.getColor(1).m_index;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (int y = 0; y < cm->getLy(); ++y) {
|
|
Toshihiro Shimizu |
890ddd |
TPixelCM32 *pix = cm->pixels(y);
|
|
Toshihiro Shimizu |
890ddd |
TPixelCM32 *endPix = pix + cm->getLx();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (; pix < endPix; ++pix) {
|
|
Toshihiro Shimizu |
890ddd |
val = transf_fun[pix->getValue() + 256];
|
|
Toshihiro Shimizu |
890ddd |
*pix = (val < 255) ? TPixelCM32(black, 0, val) : TPixelCM32();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=========================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! Transparency check
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void transparencyCheck(const TRasterCM32P &cmin, const TRaster32P &rasout)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
for (int y = 0; y < cmin->getLy(); ++y) {
|
|
Toshihiro Shimizu |
890ddd |
TPixelCM32 *pix = cmin->pixels(y);
|
|
Toshihiro Shimizu |
890ddd |
TPixelCM32 *endPix = pix + cmin->getLx();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPixel32 *outPix = rasout->pixels(y);
|
|
Toshihiro Shimizu |
890ddd |
for (; pix < endPix; ++pix, ++outPix) {
|
|
Toshihiro Shimizu |
890ddd |
int ink = pix->getInk();
|
|
Toshihiro Shimizu |
890ddd |
int tone = pix->getTone();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (ink == 4095)
|
|
Toshihiro Shimizu |
890ddd |
*outPix = TPixel32::Green;
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
*outPix = (tone == 0) ? TPixel32::Black : (tone == 255) ? TPixel32::White : TPixel32::Red;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} //namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//**************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// TCleanupper implementation - elementary functions
|
|
Toshihiro Shimizu |
890ddd |
//**************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TCleanupper *TCleanupper::instance()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
static TCleanupper theCleanupper;
|
|
Toshihiro Shimizu |
890ddd |
return &theCleanupper;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TCleanupper::setParameters(CleanupParameters *parameters)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_parameters = parameters;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPalette *TCleanupper::createToonzPaletteFromCleanupPalette()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TPalette *cleanupPalette = m_parameters->m_cleanupPalette.getPointer();
|
|
Toshihiro Shimizu |
890ddd |
return createToonzPalette(cleanupPalette, 1);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//**************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// CleanupProcessedImage implementation
|
|
Toshihiro Shimizu |
890ddd |
//**************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TToonzImageP CleanupPreprocessedImage::getImg() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return (TToonzImageP)(TImageCache::instance()->get(m_imgId, true));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
CleanupPreprocessedImage::CleanupPreprocessedImage(
|
|
Toshihiro Shimizu |
890ddd |
CleanupParameters *parameters,
|
|
Toshihiro Shimizu |
890ddd |
TToonzImageP processed,
|
|
Toshihiro Shimizu |
890ddd |
bool fromGr8)
|
|
Toshihiro Shimizu |
890ddd |
: m_wasFromGR8(fromGr8), m_autocentered(false), m_size(processed->getSize())
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!processed)
|
|
Toshihiro Shimizu |
890ddd |
m_imgId = "";
|
|
Toshihiro Shimizu |
890ddd |
else {
|
|
Toshihiro Shimizu |
890ddd |
m_imgId = TImageCache::instance()->getUniqueId();
|
|
Toshihiro Shimizu |
890ddd |
assert(!processed->getRaster()->getParent());
|
|
Toshihiro Shimizu |
890ddd |
TImageCache::instance()->add(m_imgId, (TImageP)processed);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!m_wasFromGR8) {
|
|
Toshihiro Shimizu |
890ddd |
const TPixel32 white(255, 255, 255, 0);
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 0; i < parameters->m_colors.getColorCount(); ++i) {
|
|
Toshihiro Shimizu |
890ddd |
TPixel32 cc = parameters->m_colors.getColor(i).m_color;
|
|
Toshihiro Shimizu |
890ddd |
for (int tone = 0; tone < 256; tone++) {
|
|
Toshihiro Shimizu |
890ddd |
m_pixelsLut.push_back(
|
|
Toshihiro Shimizu |
890ddd |
blend(parameters->m_colors.getColor(i).m_color,
|
|
Toshihiro Shimizu |
890ddd |
white,
|
|
Toshihiro Shimizu |
890ddd |
tone,
|
|
Toshihiro Shimizu |
890ddd |
TPixelCM32::getMaxTone()));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
CleanupPreprocessedImage::~CleanupPreprocessedImage()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TImageCache::instance()->remove(m_imgId);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRasterImageP CleanupPreprocessedImage::getPreviewImage() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TRaster32P ras(getSize());
|
|
Toshihiro Shimizu |
890ddd |
TRasterImageP ri(ras);
|
|
Toshihiro Shimizu |
890ddd |
double xdpi = 0, ydpi = 0;
|
|
Toshihiro Shimizu |
890ddd |
getImg()->getDpi(xdpi, ydpi);
|
|
Toshihiro Shimizu |
890ddd |
ri->setDpi(xdpi, ydpi);
|
|
Toshihiro Shimizu |
890ddd |
return ri;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//**************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// TCleanupper implementation - Process functions
|
|
Toshihiro Shimizu |
890ddd |
//**************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool TCleanupper::getResampleValues(const TRasterImageP &image, TAffine &aff, double &blur,
|
|
Toshihiro Shimizu |
890ddd |
TDimension &outDim, TPointD &outDpi, bool isCameraTest, bool &isSameDpi)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
double outlp, outlq;
|
|
Toshihiro Shimizu |
890ddd |
double scalex, scaley;
|
|
Toshihiro Shimizu |
890ddd |
double cxin, cyin, cpout, cqout;
|
|
Toshihiro Shimizu |
890ddd |
double max_blur;
|
|
Toshihiro Shimizu |
890ddd |
TPointD dpi;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Locking the input image to be cleanupped
|
|
Toshihiro Shimizu |
890ddd |
image->getRaster()->lock();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Retrieve image infos
|
|
Toshihiro Shimizu |
890ddd |
int rasterLx = image->getRaster()->getLx();
|
|
Toshihiro Shimizu |
890ddd |
int rasterLy = image->getRaster()->getLy();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*---入力画像サイズとSaveBoxのサイズが一致しているか?の判定---*/
|
|
Toshihiro Shimizu |
890ddd |
TRect saveBox = image->getSavebox();
|
|
Toshihiro Shimizu |
890ddd |
bool raster_is_savebox = true;
|
|
Toshihiro Shimizu |
890ddd |
if (saveBox == TRect() && (saveBox.getLx() > 0 && saveBox.getLx() < rasterLx ||
|
|
Toshihiro Shimizu |
890ddd |
saveBox.getLy() > 0 && saveBox.getLy() < rasterLy))
|
|
Toshihiro Shimizu |
890ddd |
raster_is_savebox = false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
image->getDpi(dpi.x, dpi.y);
|
|
Toshihiro Shimizu |
890ddd |
if (dpi == TPointD()) {
|
|
Toshihiro Shimizu |
890ddd |
dpi = getCustomDpi();
|
|
Toshihiro Shimizu |
890ddd |
if (dpi == TPointD())
|
|
Toshihiro Shimizu |
890ddd |
dpi.x = dpi.y = 65.0; //using 65.0 as default DPI
|
|
Toshihiro Shimizu |
890ddd |
} else if (!dpi.x)
|
|
Toshihiro Shimizu |
890ddd |
dpi.x = dpi.y;
|
|
Toshihiro Shimizu |
890ddd |
else if (!dpi.y)
|
|
Toshihiro Shimizu |
890ddd |
dpi.y = dpi.x;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Retrieve some cleanup parameters
|
|
Toshihiro Shimizu |
890ddd |
int rotate = m_parameters->m_rotate;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Build scaling/dpi data
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_parameters->getOutputImageInfo(outDim, outDpi.x, outDpi.y);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// input -> output scale factor
|
|
Toshihiro Shimizu |
890ddd |
scalex = outDpi.x / dpi.x;
|
|
Toshihiro Shimizu |
890ddd |
scaley = outDpi.y / dpi.y;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
outlp = outDim.lx;
|
|
Toshihiro Shimizu |
890ddd |
outlq = outDim.ly;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*--- 拡大/縮小をしていない場合(DPIが変わらない場合)、NearestNeighborでリサンプリングする。---*/
|
|
Toshihiro Shimizu |
890ddd |
isSameDpi = areAlmostEqual(outDpi.x, dpi.x, 0.1) && areAlmostEqual(outDpi.y, dpi.y, 0.1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Retrieve input center
|
|
Toshihiro Shimizu |
890ddd |
if (raster_is_savebox) {
|
|
Toshihiro Shimizu |
890ddd |
cxin = -saveBox.getP00().x + (saveBox.getLx() - 1) / 2.0;
|
|
Toshihiro Shimizu |
890ddd |
cyin = -saveBox.getP00().y + (saveBox.getLy() - 1) / 2.0;
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
cxin = (rasterLx - 1) / 2.0;
|
|
Toshihiro Shimizu |
890ddd |
cyin = (rasterLy - 1) / 2.0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Retrieve output center
|
|
Toshihiro Shimizu |
890ddd |
cpout = (outlp - 1) / 2.0;
|
|
Toshihiro Shimizu |
890ddd |
cqout = (outlq - 1) / 2.0;
|
|
Toshihiro Shimizu |
890ddd |
// Perform autocenter if any is found
|
|
Toshihiro Shimizu |
890ddd |
double angle = 0.0;
|
|
Toshihiro Shimizu |
890ddd |
double skew = 0.0;
|
|
Toshihiro Shimizu |
890ddd |
TAffine pre_aff;
|
|
Toshihiro Shimizu |
890ddd |
image->getRaster()->lock();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool autocentered =
|
|
Toshihiro Shimizu |
890ddd |
doAutocenter(
|
|
Toshihiro Shimizu |
890ddd |
angle, skew,
|
|
Toshihiro Shimizu |
890ddd |
cxin, cyin, cqout, cpout,
|
|
Toshihiro Shimizu |
890ddd |
dpi.x, dpi.y,
|
|
Toshihiro Shimizu |
890ddd |
raster_is_savebox, saveBox,
|
|
Toshihiro Shimizu |
890ddd |
image, scalex);
|
|
Toshihiro Shimizu |
890ddd |
image->getRaster()->unlock();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Build the image transform as deduced by the autocenter
|
|
Toshihiro Shimizu |
890ddd |
if (m_parameters->m_autocenterType == AUTOCENTER_CTR && skew) {
|
|
Toshihiro Shimizu |
890ddd |
pre_aff.a11 = cos(skew * TConsts::pi_180);
|
|
Toshihiro Shimizu |
890ddd |
pre_aff.a21 = sin(skew * TConsts::pi_180);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
aff = (TScale(scalex, scaley) * pre_aff) * TRotation(angle);
|
|
Toshihiro Shimizu |
890ddd |
aff = aff.place(cxin, cyin, cpout, cqout);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Apply eventual additional user-defined transforms
|
|
Toshihiro Shimizu |
890ddd |
TPointD pout = TPointD((outlp - 1) / 2.0, (outlq - 1) / 2.0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_parameters->m_rotate != 0)
|
|
Toshihiro Shimizu |
890ddd |
aff = TRotation(-(double)m_parameters->m_rotate).place(pout, pout) * aff;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_parameters->m_flipx || m_parameters->m_flipy)
|
|
Toshihiro Shimizu |
890ddd |
aff = TScale(m_parameters->m_flipx ? -1 : 1, m_parameters->m_flipy ? -1 : 1).place(pout, pout) * aff;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!isCameraTest)
|
|
Toshihiro Shimizu |
890ddd |
aff = TTranslation(m_parameters->m_offx * outDpi.x / 2, m_parameters->m_offy * outDpi.y / 2) * aff;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
max_blur = 20.0 * sqrt(fabs(scalex /*** * oversample_factor ***/));
|
|
Toshihiro Shimizu |
890ddd |
blur = pow(max_blur, (100 - m_parameters->m_sharpness) / (100 - 1));
|
|
Toshihiro Shimizu |
890ddd |
return autocentered;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//this one incorporate the preprocessColors and the finalize function; used for swatch.(tipically on very small rasters)
|
|
Toshihiro Shimizu |
890ddd |
TRasterP TCleanupper::processColors(const TRasterP &rin)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_parameters->m_lineProcessingMode == lpNone)
|
|
Toshihiro Shimizu |
890ddd |
return rin;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRasterCM32P rcm = TRasterCM32P(rin->getSize());
|
|
Toshihiro Shimizu |
890ddd |
if (!rcm) {
|
|
Toshihiro Shimizu |
890ddd |
assert(!"failed finalRas allocation!");
|
|
Toshihiro Shimizu |
890ddd |
return TRasterCM32P();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Copy current cleanup palette to parameters' colors
|
|
Toshihiro Shimizu |
890ddd |
m_parameters->m_colors.update(m_parameters->m_cleanupPalette.getPointer(), m_parameters->m_noAntialias);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool toGr8 = (m_parameters->m_lineProcessingMode == lpGrey);
|
|
Toshihiro Shimizu |
890ddd |
if (toGr8) {
|
|
Toshihiro Shimizu |
890ddd |
//No (color) processing. Not even thresholding. This just means that all the important
|
|
Toshihiro Shimizu |
890ddd |
//stuff here is made in the brightness/contrast stage...
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//NOTE: Most of the color processing should be DISABLED in this case!!
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//finalRas->clear();
|
|
Toshihiro Shimizu |
890ddd |
rin->lock();
|
|
Toshihiro Shimizu |
890ddd |
rcm->lock();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (TRasterGR8P(rin)) {
|
|
Toshihiro Shimizu |
890ddd |
UCHAR *rowin = rin->getRawData();
|
|
Toshihiro Shimizu |
890ddd |
TUINT32 *rowout = reinterpret_cast<tuint32 *="">(rcm->getRawData());</tuint32>
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 0; i < rin->getLy(); i++) {
|
|
Toshihiro Shimizu |
890ddd |
for (int j = 0; j < rin->getLx(); j++)
|
|
Toshihiro Shimizu |
890ddd |
*rowout++ = *rowin++; //Direct copy for now... :(
|
|
Toshihiro Shimizu |
890ddd |
rowin += rin->getWrap() - rin->getLx();
|
|
Toshihiro Shimizu |
890ddd |
rowout += rcm->getWrap() - rcm->getLx();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
TPixel32 *rowin = reinterpret_cast<tpixel32 *="">(rin->getRawData());</tpixel32>
|
|
Toshihiro Shimizu |
890ddd |
TUINT32 *rowout = reinterpret_cast<tuint32 *="">(rcm->getRawData());</tuint32>
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 0; i < rin->getLy(); i++) {
|
|
Toshihiro Shimizu |
890ddd |
for (int j = 0; j < rin->getLx(); j++)
|
|
Toshihiro Shimizu |
890ddd |
*rowout++ = TPixelGR8::from(*rowin++).value;
|
|
Toshihiro Shimizu |
890ddd |
rowin += rin->getWrap() - rin->getLx();
|
|
Toshihiro Shimizu |
890ddd |
rowout += rcm->getWrap() - rcm->getLx();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
rin->unlock();
|
|
Toshihiro Shimizu |
890ddd |
rcm->unlock();
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
assert(TRaster32P(rin));
|
|
Toshihiro Shimizu |
890ddd |
preprocessColors(rcm, rin, m_parameters->m_colors);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//outImg->setDpi(outDpi.x, outDpi.y);
|
|
Toshihiro Shimizu |
890ddd |
CleanupPreprocessedImage cpi(m_parameters, TToonzImageP(rcm, rcm->getBounds()), toGr8);
|
|
Toshihiro Shimizu |
890ddd |
cpi.m_autocentered = true;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRaster32P rout = TRaster32P(rin->getSize());
|
|
Toshihiro Shimizu |
890ddd |
finalize(rout, &cpi);
|
|
Toshihiro Shimizu |
890ddd |
return rout;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
CleanupPreprocessedImage *TCleanupper::process(
|
|
Toshihiro Shimizu |
890ddd |
TRasterImageP &image, bool first_image, TRasterImageP &onlyResampledImage,
|
|
Toshihiro Shimizu |
890ddd |
bool isCameraTest, bool returnResampled, bool onlyForSwatch, TAffine *resampleAff)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TAffine aff;
|
|
Toshihiro Shimizu |
890ddd |
double blur;
|
|
Toshihiro Shimizu |
890ddd |
TDimension outDim(0, 0);
|
|
Toshihiro Shimizu |
890ddd |
TPointD outDpi;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool isSameDpi = false;
|
|
Toshihiro Shimizu |
890ddd |
bool autocentered = getResampleValues(image, aff, blur, outDim, outDpi, isCameraTest, isSameDpi);
|
|
Toshihiro Shimizu |
890ddd |
if (m_parameters->m_autocenterType != AUTOCENTER_NONE && !autocentered)
|
|
Toshihiro Shimizu |
890ddd |
DVGui::MsgBox(DVGui::WARNING, QObject::tr("The autocentering failed on the current drawing."));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool fromGr8 = (bool)TRasterGR8P(image->getRaster());
|
|
Toshihiro Shimizu |
890ddd |
bool toGr8 = (m_parameters->m_lineProcessingMode == lpGrey);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// If necessary, perform auto-adjust
|
|
Toshihiro Shimizu |
890ddd |
if (!isCameraTest && m_parameters->m_lineProcessingMode != lpNone && toGr8 && m_parameters->m_autoAdjustMode != AUTO_ADJ_NONE &&
|
|
Toshihiro Shimizu |
890ddd |
!onlyForSwatch) {
|
|
Toshihiro Shimizu |
890ddd |
static int ref_cum[256];
|
|
Toshihiro Shimizu |
890ddd |
UCHAR lut[256];
|
|
Toshihiro Shimizu |
890ddd |
int cum[256];
|
|
Toshihiro Shimizu |
890ddd |
double x0_src_f, y0_src_f, x1_src_f, y1_src_f;
|
|
Toshihiro Shimizu |
890ddd |
int x0_src, y0_src, x1_src, y1_src;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//cleanup_message("Autoadjusting... \n");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TAffine inv = aff.inv();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
x0_src_f = affMV1(inv, 0, 0);
|
|
Toshihiro Shimizu |
890ddd |
y0_src_f = affMV2(inv, 0, 0);
|
|
Toshihiro Shimizu |
890ddd |
x1_src_f = affMV1(inv, outDim.lx - 1, outDim.ly - 1);
|
|
Toshihiro Shimizu |
890ddd |
y1_src_f = affMV2(inv, outDim.lx - 1, outDim.ly - 1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
x0_src = tround(x0_src_f);
|
|
Toshihiro Shimizu |
890ddd |
y0_src = tround(y0_src_f);
|
|
Toshihiro Shimizu |
890ddd |
x1_src = tround(x1_src_f);
|
|
Toshihiro Shimizu |
890ddd |
y1_src = tround(y1_src_f);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
set_autoadjust_window(x0_src, y0_src, x1_src, y1_src);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!TRasterGR8P(image->getRaster())) {
|
|
Toshihiro Shimizu |
890ddd |
//Auto-adjusting a 32-bit image. This means that a white background must be introduced first.
|
|
Toshihiro Shimizu |
890ddd |
TRaster32P ras32(image->getRaster()->clone());
|
|
Toshihiro Shimizu |
890ddd |
TRop::addBackground(ras32, TPixel32::White);
|
|
Toshihiro Shimizu |
890ddd |
image = TRasterImageP(ras32); //old image is released here
|
|
Toshihiro Shimizu |
890ddd |
ras32 = TRaster32P();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRasterGR8P rgr(image->getRaster()->getSize());
|
|
Toshihiro Shimizu |
890ddd |
TRop::copy(rgr, image->getRaster());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//This is now legit. It was NOT before the clone, since the original could be cached.
|
|
Toshihiro Shimizu |
890ddd |
image->setRaster(rgr);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
switch (m_parameters->m_autoAdjustMode) {
|
|
Toshihiro Shimizu |
890ddd |
case AUTO_ADJ_HISTOGRAM: {
|
|
Toshihiro Shimizu |
890ddd |
if (first_image) {
|
|
Toshihiro Shimizu |
890ddd |
build_gr_cum(image, ref_cum);
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
build_gr_cum(image, cum);
|
|
Toshihiro Shimizu |
890ddd |
build_gr_lut(ref_cum, cum, lut);
|
|
Toshihiro Shimizu |
890ddd |
apply_lut(image, lut);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
CASE AUTO_ADJ_HISTO_L : histo_l_algo(image, first_image);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
CASE AUTO_ADJ_BLACK_EQ : black_eq_algo(image);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
CASE AUTO_ADJ_NONE : DEFAULT : assert(false);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
fromGr8 = (bool)TRasterGR8P(image->getRaster()); //may have changed type due to auto-adjust
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(returnResampled || !onlyForSwatch); //if onlyForSwatch, then returnResampled
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Allocate output colormap raster
|
|
Toshihiro Shimizu |
890ddd |
TRasterCM32P finalRas;
|
|
Toshihiro Shimizu |
890ddd |
if (!onlyForSwatch) {
|
|
Toshihiro Shimizu |
890ddd |
finalRas = TRasterCM32P(outDim);
|
|
Toshihiro Shimizu |
890ddd |
if (!finalRas) {
|
|
Toshihiro Shimizu |
890ddd |
TImageCache::instance()->outputMap(outDim.lx * outDim.ly * 4, "C:\\cachelog");
|
|
Toshihiro Shimizu |
890ddd |
assert(!"failed finalRas allocation!");
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// In case the input raster was a greymap, we cannot reutilize finalRas's buffer to transform the final
|
|
Toshihiro Shimizu |
890ddd |
// fullcolor pixels to colormap pixels directly (1 32-bit pixel would hold 4 8-bit pixels) - therefore,
|
|
Toshihiro Shimizu |
890ddd |
// a secondary greymap is allocated.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//NOTE: This should be considered obsolete? By using TRop::resample( <traster32p& instance=""> , ...) we</traster32p&>
|
|
Toshihiro Shimizu |
890ddd |
//should get the same effect!!
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRasterP tmp_ras;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (returnResampled || (fromGr8 && toGr8)) {
|
|
Toshihiro Shimizu |
890ddd |
if (fromGr8 && toGr8)
|
|
Toshihiro Shimizu |
890ddd |
tmp_ras = TRasterGR8P(outDim);
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
tmp_ras = TRaster32P(outDim);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!tmp_ras) {
|
|
Toshihiro Shimizu |
890ddd |
TImageCache::instance()->outputMap(outDim.lx * outDim.ly * 4, "C:\\cachelog");
|
|
Toshihiro Shimizu |
890ddd |
assert(!"failed tmp_ras allocation!");
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
} else
|
|
Toshihiro Shimizu |
890ddd |
//if finalRas is allocated, and the intermediate raster has to be 32-bit, we can perform pixel
|
|
Toshihiro Shimizu |
890ddd |
//conversion directly on the same output buffer
|
|
Toshihiro Shimizu |
890ddd |
tmp_ras = TRaster32P(outDim.lx, outDim.ly, outDim.lx, (TPixel32 *)finalRas->getRawData());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRop::ResampleFilterType flt_type;
|
|
Toshihiro Shimizu |
890ddd |
if (isSameDpi)
|
|
Toshihiro Shimizu |
890ddd |
flt_type = TRop::ClosestPixel; //NearestNeighbor
|
|
Toshihiro Shimizu |
890ddd |
else if (isCameraTest)
|
|
Toshihiro Shimizu |
890ddd |
flt_type = TRop::Triangle;
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
flt_type = TRop::Hann2;
|
|
Toshihiro Shimizu |
890ddd |
TRop::resample(tmp_ras, image->getRaster(), aff, flt_type, blur);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if ((TRaster32P)tmp_ras)
|
|
Toshihiro Shimizu |
890ddd |
//Add white background to deal with semitransparent pixels
|
|
Toshihiro Shimizu |
890ddd |
TRop::addBackground(tmp_ras, TPixel32::White);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (resampleAff)
|
|
Toshihiro Shimizu |
890ddd |
*resampleAff = aff;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
image->getRaster()->unlock();
|
|
Toshihiro Shimizu |
890ddd |
image = TRasterImageP();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (returnResampled) {
|
|
Toshihiro Shimizu |
890ddd |
onlyResampledImage = TRasterImageP(tmp_ras);
|
|
Toshihiro Shimizu |
890ddd |
onlyResampledImage->setDpi(outDpi.x, outDpi.y);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (onlyForSwatch)
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(finalRas);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Copy current cleanup palette to parameters' colors
|
|
Toshihiro Shimizu |
890ddd |
m_parameters->m_colors.update(m_parameters->m_cleanupPalette.getPointer(), m_parameters->m_noAntialias);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (toGr8) {
|
|
Toshihiro Shimizu |
890ddd |
//No (color) processing. Not even thresholding. This just means that all the important
|
|
Toshihiro Shimizu |
890ddd |
//stuff here is made in the brightness/contrast stage...
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//NOTE: Most of the color processing should be DISABLED in this case!!
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tmp_ras->lock();
|
|
Toshihiro Shimizu |
890ddd |
finalRas->lock();
|
|
Toshihiro Shimizu |
890ddd |
assert(tmp_ras->getSize() == finalRas->getSize());
|
|
Toshihiro Shimizu |
890ddd |
assert(tmp_ras->getLx() == tmp_ras->getWrap());
|
|
Toshihiro Shimizu |
890ddd |
assert(finalRas->getLx() == finalRas->getWrap());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int pixCount = outDim.lx * outDim.ly;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (fromGr8) {
|
|
Toshihiro Shimizu |
890ddd |
UCHAR *rowin = tmp_ras->getRawData();
|
|
Toshihiro Shimizu |
890ddd |
TUINT32 *rowout = reinterpret_cast<tuint32 *="">(finalRas->getRawData());</tuint32>
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 0; i < pixCount; i++)
|
|
Toshihiro Shimizu |
890ddd |
*rowout++ = *rowin++; //Direct copy for now... :(
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
TPixel32 *rowin = reinterpret_cast<tpixel32 *="">(tmp_ras->getRawData());</tpixel32>
|
|
Toshihiro Shimizu |
890ddd |
TUINT32 *rowout = reinterpret_cast<tuint32 *="">(finalRas->getRawData());</tuint32>
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 0; i < pixCount; i++)
|
|
Toshihiro Shimizu |
890ddd |
*rowout++ = TPixelGR8::from(*rowin++).value;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tmp_ras->unlock();
|
|
Toshihiro Shimizu |
890ddd |
finalRas->unlock();
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
//WARNING: finalRas and tmp_ras may share the SAME buffer!
|
|
Toshihiro Shimizu |
890ddd |
assert(TRaster32P(tmp_ras));
|
|
Toshihiro Shimizu |
890ddd |
preprocessColors(finalRas, tmp_ras, m_parameters->m_colors);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TToonzImageP final;
|
|
Toshihiro Shimizu |
890ddd |
final = TToonzImageP(finalRas, finalRas->getBounds());
|
|
Toshihiro Shimizu |
890ddd |
final->setDpi(outDpi.x, outDpi.y);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
CleanupPreprocessedImage *cpi = new CleanupPreprocessedImage(m_parameters, final, toGr8);
|
|
Toshihiro Shimizu |
890ddd |
cpi->m_autocentered = autocentered;
|
|
Toshihiro Shimizu |
890ddd |
cpi->m_appliedAff = aff;
|
|
Toshihiro Shimizu |
890ddd |
return cpi;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRasterImageP TCleanupper::autocenterOnly(
|
|
Toshihiro Shimizu |
890ddd |
const TRasterImageP &image, bool isCameraTest, bool &autocentered)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
double xDpi, yDpi;
|
|
Toshihiro Shimizu |
890ddd |
//double inlx, inly, zoom_factor, max_blur;
|
|
Toshihiro Shimizu |
890ddd |
double skew = 0, angle = 0, dist = 0 /*lq_nozoom, lp_nozoom,, cx, cy, scalex, scaley*/;
|
|
Toshihiro Shimizu |
890ddd |
double cxin, cyin, cpout, cqout;
|
|
Toshihiro Shimizu |
890ddd |
int rasterIsSavebox = true;
|
|
Toshihiro Shimizu |
890ddd |
TAffine aff, preAff, inv;
|
|
Toshihiro Shimizu |
890ddd |
int rasterLx, finalLx, rasterLy, finalLy;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
rasterLx = finalLx = image->getRaster()->getLx();
|
|
Toshihiro Shimizu |
890ddd |
rasterLy = finalLy = image->getRaster()->getLy();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRect saveBox = image->getSavebox();
|
|
Toshihiro Shimizu |
890ddd |
if ((saveBox == TRect()) && ((saveBox.getLx() > 0 && saveBox.getLx() < rasterLx) ||
|
|
Toshihiro Shimizu |
890ddd |
(saveBox.getLy() > 0 && saveBox.getLy() < rasterLy)))
|
|
Toshihiro Shimizu |
890ddd |
rasterIsSavebox = false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int rotate = m_parameters->m_rotate;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
image->getDpi(xDpi, yDpi);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!xDpi) //using 65.0 as default DPI
|
|
Toshihiro Shimizu |
890ddd |
xDpi = (yDpi ? yDpi : 65);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!yDpi)
|
|
Toshihiro Shimizu |
890ddd |
yDpi = (xDpi ? xDpi : 65);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (rasterIsSavebox) {
|
|
Toshihiro Shimizu |
890ddd |
cxin = -saveBox.getP00().x + (saveBox.getLx() - 1) / 2.0;
|
|
Toshihiro Shimizu |
890ddd |
cyin = -saveBox.getP00().y + (saveBox.getLy() - 1) / 2.0;
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
cxin = (rasterLx - 1) / 2.0;
|
|
Toshihiro Shimizu |
890ddd |
cyin = (rasterLy - 1) / 2.0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
cpout = (rasterLx - 1) / 2.0;
|
|
Toshihiro Shimizu |
890ddd |
cqout = (rasterLy - 1) / 2.0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_parameters->m_autocenterType != AUTOCENTER_NONE)
|
|
Toshihiro Shimizu |
890ddd |
autocentered = doAutocenter(angle, skew, cxin, cyin, cqout, cpout,
|
|
Toshihiro Shimizu |
890ddd |
xDpi, yDpi, rasterIsSavebox, saveBox, image, 1.0);
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
autocentered = true;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_parameters->m_autocenterType == AUTOCENTER_CTR && skew) {
|
|
Toshihiro Shimizu |
890ddd |
aff.a11 = cos(skew * TConsts::pi_180);
|
|
Toshihiro Shimizu |
890ddd |
aff.a21 = sin(skew * TConsts::pi_180);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
aff = aff * TRotation(angle);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
aff = aff.place(cxin, cyin, cpout, cqout);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (rotate != 0 && rotate != 180)
|
|
Toshihiro Shimizu |
890ddd |
tswap(finalLx, finalLy);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPointD pin = TPointD((rasterLx - 1) / 2.0, (rasterLy - 1) / 2.0);
|
|
Toshihiro Shimizu |
890ddd |
TPointD pout = TPointD((finalLx - 1) / 2.0, (finalLy - 1) / 2.0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (rotate != 0)
|
|
Toshihiro Shimizu |
890ddd |
aff = TRotation(-(double)rotate).place(pin, pout) * aff;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_parameters->m_flipx || m_parameters->m_flipy)
|
|
Toshihiro Shimizu |
890ddd |
aff = TScale(m_parameters->m_flipx ? -1 : 1, m_parameters->m_flipy ? -1 : 1).place(pout, pout) * aff;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!isCameraTest)
|
|
Toshihiro Shimizu |
890ddd |
aff = TTranslation(m_parameters->m_offx * xDpi / 2,
|
|
Toshihiro Shimizu |
890ddd |
m_parameters->m_offy * yDpi / 2) *
|
|
Toshihiro Shimizu |
890ddd |
aff;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRasterP tmpRas;
|
|
Toshihiro Shimizu |
890ddd |
TPoint dp;
|
|
Toshihiro Shimizu |
890ddd |
if (isCameraTest) //in cameratest, I don't want to crop the image to be shown.
|
|
Toshihiro Shimizu |
890ddd |
// so, I resample without cropping, and I compute the offset needed to have it autocentered.
|
|
Toshihiro Shimizu |
890ddd |
// That offset is stored in the RasterImage(setOffset below) and then used when displaying the image in camerastand (in method RasterPainter::onRasterImage)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
//TPointD srcActualCenter = aff.inv()*TPointD(finalLx/2.0, finalLy/2.0);// the autocenter position in the source image
|
|
Toshihiro Shimizu |
890ddd |
//TPointD srcCenter = imageToResample->getRaster()->getCenterD();*/
|
|
Toshihiro Shimizu |
890ddd |
TPointD dstActualCenter = TPointD(finalLx / 2.0, finalLy / 2.0);
|
|
Toshihiro Shimizu |
890ddd |
TPointD dstCenter = aff * image->getRaster()->getCenterD();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
dp = convert(dstCenter - dstActualCenter); //the amount to be offset in the destination image.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRect r = convert(aff * convert(image->getRaster()->getBounds()));
|
|
Toshihiro Shimizu |
890ddd |
aff = (TTranslation(convert(-r.getP00())) * aff);
|
|
Toshihiro Shimizu |
890ddd |
//aff = aff.place(srcActualCenter, dstActualCenter);
|
|
Toshihiro Shimizu |
890ddd |
tmpRas = image->getRaster()->create(r.getLx(), r.getLy());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} else
|
|
Toshihiro Shimizu |
890ddd |
tmpRas = image->getRaster()->create(finalLx, finalLy);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRop::resample(tmpRas, image->getRaster(), aff);
|
|
Toshihiro Shimizu |
890ddd |
//TImageWriter::save(TFilePath("C:\\temp\\incleanup.tif"), imageToResample);
|
|
Toshihiro Shimizu |
890ddd |
//TImageWriter::save(TFilePath("C:\\temp\\outcleanup.tif"), tmp_ras);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRasterImageP final(tmpRas);
|
|
Toshihiro Shimizu |
890ddd |
final->setOffset(dp);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
final->setDpi(xDpi, yDpi);
|
|
Toshihiro Shimizu |
890ddd |
//final->sethPos(finalHPos);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return final;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//**************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// AutoCenter
|
|
Toshihiro Shimizu |
890ddd |
//**************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool TCleanupper::doAutocenter(
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double &angle, double &skew,
|
|
Toshihiro Shimizu |
890ddd |
double &cxin, double &cyin,
|
|
Toshihiro Shimizu |
890ddd |
double &cqout, double &cpout,
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const double xdpi, const double ydpi,
|
|
Toshihiro Shimizu |
890ddd |
const int raster_is_savebox,
|
|
Toshihiro Shimizu |
890ddd |
const TRect saveBox,
|
|
Toshihiro Shimizu |
890ddd |
const TRasterImageP &image,
|
|
Toshihiro Shimizu |
890ddd |
const double scalex)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
double sigma = 0, theta = 0;
|
|
Toshihiro Shimizu |
890ddd |
FDG_INFO fdg_info = m_parameters->getFdgInfo();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
switch (m_parameters->m_autocenterType) {
|
|
Toshihiro Shimizu |
890ddd |
case AUTOCENTER_CTR:
|
|
Toshihiro Shimizu |
890ddd |
angle = fdg_info.ctr_angle;
|
|
Toshihiro Shimizu |
890ddd |
skew = fdg_info.ctr_skew;
|
|
Toshihiro Shimizu |
890ddd |
cxin = mmToPixel(fdg_info.ctr_x, xdpi);
|
|
Toshihiro Shimizu |
890ddd |
cyin = mmToPixel(fdg_info.ctr_y, ydpi);
|
|
Toshihiro Shimizu |
890ddd |
if (raster_is_savebox) {
|
|
Toshihiro Shimizu |
890ddd |
cxin -= saveBox.getP00().x;
|
|
Toshihiro Shimizu |
890ddd |
cyin -= saveBox.getP00().y;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
case AUTOCENTER_FDG: {
|
|
Toshihiro Shimizu |
890ddd |
// e se image->raster_is_savebox?
|
|
Toshihiro Shimizu |
890ddd |
//cleanup_message ("Autocentering...");
|
|
Toshihiro Shimizu |
890ddd |
int strip_width = compute_strip_pixel(&fdg_info, xdpi) + 1; /* ?!? */
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
switch (m_parameters->m_pegSide) {
|
|
Toshihiro Shimizu |
890ddd |
case PEGS_BOTTOM:
|
|
Toshihiro Shimizu |
890ddd |
sigma = 0.0;
|
|
Toshihiro Shimizu |
890ddd |
CASE PEGS_RIGHT : sigma = 90.0;
|
|
Toshihiro Shimizu |
890ddd |
CASE PEGS_TOP : sigma = 180.0;
|
|
Toshihiro Shimizu |
890ddd |
CASE PEGS_LEFT : sigma = -90.0;
|
|
Toshihiro Shimizu |
890ddd |
DEFAULT:
|
|
Toshihiro Shimizu |
890ddd |
sigma = 0.0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
theta = sigma;
|
|
Toshihiro Shimizu |
890ddd |
if (theta > 180.0)
|
|
Toshihiro Shimizu |
890ddd |
theta -= 360.0;
|
|
Toshihiro Shimizu |
890ddd |
else if (theta <= -180.0)
|
|
Toshihiro Shimizu |
890ddd |
theta += 360.0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
PEGS_SIDE pegs_ras_side;
|
|
Toshihiro Shimizu |
890ddd |
if (theta == 0.0)
|
|
Toshihiro Shimizu |
890ddd |
pegs_ras_side = PEGS_BOTTOM;
|
|
Toshihiro Shimizu |
890ddd |
else if (theta == 90.0)
|
|
Toshihiro Shimizu |
890ddd |
pegs_ras_side = PEGS_RIGHT;
|
|
Toshihiro Shimizu |
890ddd |
else if (theta == 180.0)
|
|
Toshihiro Shimizu |
890ddd |
pegs_ras_side = PEGS_TOP;
|
|
Toshihiro Shimizu |
890ddd |
else if (theta == -90.0)
|
|
Toshihiro Shimizu |
890ddd |
pegs_ras_side = PEGS_LEFT;
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
pegs_ras_side = PEGS_BOTTOM;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
switch (pegs_ras_side) {
|
|
Toshihiro Shimizu |
890ddd |
case PEGS_LEFT:
|
|
Toshihiro Shimizu |
890ddd |
__OR PEGS_RIGHT : notMoreThan(image->getRaster()->getLx(), strip_width);
|
|
Toshihiro Shimizu |
890ddd |
DEFAULT:
|
|
Toshihiro Shimizu |
890ddd |
notMoreThan(image->getRaster()->getLy(), strip_width);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
convert_dots_mm_to_pixel(
|
|
Toshihiro Shimizu |
890ddd |
&fdg_info.dots[0],
|
|
Toshihiro Shimizu |
890ddd |
fdg_info.dots.size(),
|
|
Toshihiro Shimizu |
890ddd |
xdpi, ydpi);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double cx, cy;
|
|
Toshihiro Shimizu |
890ddd |
if (!get_image_rotation_and_center(
|
|
Toshihiro Shimizu |
890ddd |
image->getRaster(), strip_width, pegs_ras_side,
|
|
Toshihiro Shimizu |
890ddd |
&angle, &cx, &cy, &fdg_info.dots[0], fdg_info.dots.size())) {
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
angle *= TConsts::invOf_pi_180;
|
|
Toshihiro Shimizu |
890ddd |
cxin = cx;
|
|
Toshihiro Shimizu |
890ddd |
cyin = cy;
|
|
Toshihiro Shimizu |
890ddd |
double dist = (double)mmToPixel(fdg_info.dist_ctr_to_ctr_hole, xdpi * scalex);
|
|
Toshihiro Shimizu |
890ddd |
switch (m_parameters->m_pegSide) {
|
|
Toshihiro Shimizu |
890ddd |
case PEGS_BOTTOM:
|
|
Toshihiro Shimizu |
890ddd |
cqout -= dist;
|
|
Toshihiro Shimizu |
890ddd |
CASE PEGS_TOP : cqout += dist;
|
|
Toshihiro Shimizu |
890ddd |
CASE PEGS_LEFT : cpout -= dist;
|
|
Toshihiro Shimizu |
890ddd |
CASE PEGS_RIGHT : cpout += dist;
|
|
Toshihiro Shimizu |
890ddd |
DEFAULT : {
|
|
Toshihiro Shimizu |
890ddd |
// bad pegs side
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
fdg_info.dots.clear();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
default:
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//**************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// (Pre) Processing (ie the core Cleanup procedure)
|
|
Toshihiro Shimizu |
890ddd |
//**************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline void preprocessColor(const TPixel32 &pix, const TargetColorData &blackColor,
|
|
Toshihiro Shimizu |
890ddd |
const std::vector<targetcolordata> &featureColors, int nFeatures,</targetcolordata>
|
|
Toshihiro Shimizu |
890ddd |
TPixelCM32 &outpix)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
//Translate the pixel to HSV
|
|
Toshihiro Shimizu |
890ddd |
HSVColor pixHSV(HSVColor::fromRGB(pix.r / 255.0, pix.g / 255.0, pix.b / 255.0));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//First, check against matchline colors. This is needed as outline pixels' tone is based upon that
|
|
Toshihiro Shimizu |
890ddd |
//extracted here.
|
|
Toshihiro Shimizu |
890ddd |
int idx = -1, tone = 255;
|
|
Toshihiro Shimizu |
890ddd |
double hDist = (std::numeric_limits<double>::max)(), newHDist;</double>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 0; i < nFeatures; ++i) {
|
|
Toshihiro Shimizu |
890ddd |
const TargetColorData &fColor = featureColors[i];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Feature Color
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Retrieve the hue distance and, in case it's less than current one, this idx better
|
|
Toshihiro Shimizu |
890ddd |
//approximates the color.
|
|
Toshihiro Shimizu |
890ddd |
newHDist = (pixHSV.m_h > fColor.m_hsv.m_h) ? tmin(pixHSV.m_h - fColor.m_hsv.m_h, fColor.m_hsv.m_h - pixHSV.m_h + 360.0) : tmin(fColor.m_hsv.m_h - pixHSV.m_h, pixHSV.m_h - fColor.m_hsv.m_h + 360.0);
|
|
Toshihiro Shimizu |
890ddd |
if (newHDist < hDist) {
|
|
Toshihiro Shimizu |
890ddd |
hDist = newHDist;
|
|
Toshihiro Shimizu |
890ddd |
idx = i;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (idx >= 0) {
|
|
Toshihiro Shimizu |
890ddd |
const TargetColorData &fColor = featureColors[idx];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//First, perform saturation check
|
|
Toshihiro Shimizu |
890ddd |
bool saturationOk = (pixHSV.m_s > fColor.m_saturationLower) &&
|
|
Toshihiro Shimizu |
890ddd |
((fColor.m_hueLower <= fColor.m_hueUpper) ? (pixHSV.m_h >= fColor.m_hueLower) && (pixHSV.m_h <= fColor.m_hueUpper) : (pixHSV.m_h >= fColor.m_hueLower) || (pixHSV.m_h <= fColor.m_hueUpper));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (saturationOk) {
|
|
Toshihiro Shimizu |
890ddd |
tone = 255.0 * (1.0 - pixHSV.m_s) / (1.0 - fColor.m_saturationLower);
|
|
Toshihiro Shimizu |
890ddd |
idx = fColor.m_idx;
|
|
Toshihiro Shimizu |
890ddd |
} else
|
|
Toshihiro Shimizu |
890ddd |
idx = -1;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Check against outline color
|
|
Toshihiro Shimizu |
890ddd |
if (pixHSV.m_v < blackColor.m_hsv.m_v) {
|
|
Toshihiro Shimizu |
890ddd |
//Outline-sensitive tone is imposed when the value check passes
|
|
Toshihiro Shimizu |
890ddd |
tone = (tone * pixHSV.m_v / blackColor.m_hsv.m_v);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//A further Chroma test is applied to decide whether a would-be outline color
|
|
Toshihiro Shimizu |
890ddd |
//is to be intended as a matchline color instead (it has too much color)
|
|
Toshihiro Shimizu |
890ddd |
if ((idx < 0) || (pixHSV.m_s * pixHSV.m_v) < blackColor.m_saturationLower)
|
|
Toshihiro Shimizu |
890ddd |
//Outline Color
|
|
Toshihiro Shimizu |
890ddd |
idx = 1;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
outpix = (idx > 0 && tone < 255) ? TPixelCM32(idx, 0, tone) : TPixelCM32();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TCleanupper::preprocessColors(
|
|
Toshihiro Shimizu |
890ddd |
const TRasterCM32P &outRas,
|
|
Toshihiro Shimizu |
890ddd |
const TRaster32P &raster32,
|
|
Toshihiro Shimizu |
890ddd |
const TargetColors &colors)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(outRas && outRas->getSize() == raster32->getSize());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Convert the target palette to HSV colorspace
|
|
Toshihiro Shimizu |
890ddd |
std::vector<targetcolordata> pencilsHSV;</targetcolordata>
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 2; i < colors.getColorCount(); ++i) {
|
|
Toshihiro Shimizu |
890ddd |
TargetColorData cdata(colors.getColor(i));
|
|
Toshihiro Shimizu |
890ddd |
cdata.m_idx = i;
|
|
Toshihiro Shimizu |
890ddd |
pencilsHSV.push_back(cdata);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Extract the 'black' Value
|
|
Toshihiro Shimizu |
890ddd |
TargetColor black = colors.getColor(1);
|
|
Toshihiro Shimizu |
890ddd |
TargetColorData blackData(black);
|
|
Toshihiro Shimizu |
890ddd |
blackData.m_hsv.m_v += (1.0 - black.m_threshold / 100.0);
|
|
Toshihiro Shimizu |
890ddd |
blackData.m_saturationLower = sq(1.0 - black.m_hRange / 100.0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
raster32->lock();
|
|
Toshihiro Shimizu |
890ddd |
outRas->lock();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//For every image pixel, process it
|
|
Toshihiro Shimizu |
890ddd |
for (int j = 0; j < raster32->getLy(); j++) {
|
|
Toshihiro Shimizu |
890ddd |
TPixel32 *pix = raster32->pixels(j);
|
|
Toshihiro Shimizu |
890ddd |
TPixel32 *endPix = pix + raster32->getLx();
|
|
Toshihiro Shimizu |
890ddd |
TPixelCM32 *outPix = outRas->pixels(j);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
while (pix < endPix) {
|
|
Toshihiro Shimizu |
890ddd |
if (*pix == TPixel32::White || pix->m < 255) //sometimes the resampling produces semitransparent pixels
|
|
Toshihiro Shimizu |
890ddd |
//on the border of the raster; I discards those pixels.
|
|
Toshihiro Shimizu |
890ddd |
//(which otherwise creates a black border in the final cleanupped image) vinz
|
|
Toshihiro Shimizu |
890ddd |
*outPix = TPixelCM32();
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
preprocessColor(*pix, blackData, pencilsHSV, pencilsHSV.size(), *outPix);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
pix++;
|
|
Toshihiro Shimizu |
890ddd |
outPix++;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
raster32->unlock();
|
|
Toshihiro Shimizu |
890ddd |
outRas->unlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//**************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Post-Processing
|
|
Toshihiro Shimizu |
890ddd |
//**************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TCleanupper::finalize(
|
|
Toshihiro Shimizu |
890ddd |
const TRaster32P &outRas,
|
|
Toshihiro Shimizu |
890ddd |
CleanupPreprocessedImage *srcImg)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!outRas)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (srcImg->m_wasFromGR8)
|
|
Toshihiro Shimizu |
890ddd |
doPostProcessingGR8(outRas, srcImg);
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
doPostProcessingColor(outRas, srcImg);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TToonzImageP TCleanupper::finalize(CleanupPreprocessedImage *src, bool isCleanupper)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (src->m_wasFromGR8)
|
|
Toshihiro Shimizu |
890ddd |
return doPostProcessingGR8(src);
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
return doPostProcessingColor(src->getImg(), isCleanupper);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TCleanupper::doPostProcessingGR8(
|
|
Toshihiro Shimizu |
890ddd |
const TRaster32P &outRas,
|
|
Toshihiro Shimizu |
890ddd |
CleanupPreprocessedImage *srcImg)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TToonzImageP image = srcImg->getImg();
|
|
Toshihiro Shimizu |
890ddd |
TRasterCM32P rasCM32 = image->getRaster();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
rasCM32->lock();
|
|
Toshihiro Shimizu |
890ddd |
outRas->lock();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRasterCM32P cmout(outRas->getLx(), outRas->getLy(), outRas->getWrap(), (TPixelCM32 *)outRas->getRawData());
|
|
Toshihiro Shimizu |
890ddd |
TRop::copy(cmout, rasCM32);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
rasCM32->unlock();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Apply brightness/contrast and grayscale conversion directly
|
|
Toshihiro Shimizu |
890ddd |
brightnessContrastGR8(cmout, m_parameters->m_colors);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Apply despeckling
|
|
Toshihiro Shimizu |
890ddd |
if (m_parameters->m_despeckling)
|
|
Toshihiro Shimizu |
890ddd |
TRop::despeckle(cmout, m_parameters->m_despeckling, m_parameters->m_transparencyCheckEnabled);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Morphological antialiasing
|
|
Toshihiro Shimizu |
890ddd |
if (m_parameters->m_postAntialias) {
|
|
Toshihiro Shimizu |
890ddd |
TRasterCM32P newRas(cmout->getLx(), cmout->getLy());
|
|
Toshihiro Shimizu |
890ddd |
TRop::antialias(cmout, newRas, 10, m_parameters->m_aaValue);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
cmout->unlock();
|
|
Toshihiro Shimizu |
890ddd |
cmout = newRas;
|
|
Toshihiro Shimizu |
890ddd |
cmout->lock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Finally, do transparency check
|
|
Toshihiro Shimizu |
890ddd |
if (m_parameters->m_transparencyCheckEnabled)
|
|
Toshihiro Shimizu |
890ddd |
transparencyCheck(cmout, outRas);
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
//TRop::convert(outRas, cmout, m_parameters->m_cleanupPalette);
|
|
Toshihiro Shimizu |
890ddd |
TRop::convert(outRas, cmout, createToonzPaletteFromCleanupPalette());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
outRas->unlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TToonzImageP TCleanupper::doPostProcessingGR8(const CleanupPreprocessedImage *img)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TToonzImageP image = img->getImg();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRasterCM32P rasCM32 = image->getRaster();
|
|
Toshihiro Shimizu |
890ddd |
TRasterCM32P cmout(rasCM32->clone());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
cmout->lock();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Apply brightness/contrast and grayscale conversion directly
|
|
Toshihiro Shimizu |
890ddd |
brightnessContrastGR8(cmout, m_parameters->m_colors);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Apply despeckling
|
|
Toshihiro Shimizu |
890ddd |
if (m_parameters->m_despeckling)
|
|
Toshihiro Shimizu |
890ddd |
TRop::despeckle(cmout, m_parameters->m_despeckling, false);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Morphological antialiasing
|
|
Toshihiro Shimizu |
890ddd |
if (m_parameters->m_postAntialias) {
|
|
Toshihiro Shimizu |
890ddd |
TRasterCM32P newRas(cmout->getLx(), cmout->getLy());
|
|
Toshihiro Shimizu |
890ddd |
TRop::antialias(cmout, newRas, 10, m_parameters->m_aaValue);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
cmout->unlock();
|
|
Toshihiro Shimizu |
890ddd |
cmout = newRas;
|
|
Toshihiro Shimizu |
890ddd |
cmout->lock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
cmout->unlock();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Rebuild the cmap's bbox
|
|
Toshihiro Shimizu |
890ddd |
TRect bbox;
|
|
Toshihiro Shimizu |
890ddd |
TRop::computeBBox(cmout, bbox);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Copy the dpi
|
|
Toshihiro Shimizu |
890ddd |
TToonzImageP outImg(cmout, bbox);
|
|
Toshihiro Shimizu |
890ddd |
double dpix, dpiy;
|
|
Toshihiro Shimizu |
890ddd |
image->getDpi(dpix, dpiy);
|
|
Toshihiro Shimizu |
890ddd |
outImg->setDpi(dpix, dpiy);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return outImg;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TCleanupper::doPostProcessingColor(
|
|
Toshihiro Shimizu |
890ddd |
const TRaster32P &outRas,
|
|
Toshihiro Shimizu |
890ddd |
CleanupPreprocessedImage *srcImg)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(srcImg);
|
|
Toshihiro Shimizu |
890ddd |
assert(outRas->getSize() == srcImg->getSize());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TToonzImageP imgToProcess = srcImg->getImg();
|
|
Toshihiro Shimizu |
890ddd |
TRasterCM32P rasCM32 = imgToProcess->getRaster();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
rasCM32->lock();
|
|
Toshihiro Shimizu |
890ddd |
outRas->lock();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRasterCM32P cmout(outRas->getLx(), outRas->getLy(), outRas->getWrap(), (TPixelCM32 *)outRas->getRawData());
|
|
Toshihiro Shimizu |
890ddd |
TRop::copy(cmout, rasCM32);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
rasCM32->unlock();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//First, deal with brightness/contrast
|
|
Toshihiro Shimizu |
890ddd |
brightnessContrast(cmout, m_parameters->m_colors);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Then, apply despeckling
|
|
Toshihiro Shimizu |
890ddd |
if (m_parameters->m_despeckling)
|
|
Toshihiro Shimizu |
890ddd |
TRop::despeckle(cmout, m_parameters->m_despeckling, m_parameters->m_transparencyCheckEnabled);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Morphological antialiasing
|
|
Toshihiro Shimizu |
890ddd |
if (m_parameters->m_postAntialias) {
|
|
Toshihiro Shimizu |
890ddd |
TRasterCM32P newRas(cmout->getLx(), cmout->getLy());
|
|
Toshihiro Shimizu |
890ddd |
TRop::antialias(cmout, newRas, 10, m_parameters->m_aaValue);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
cmout->unlock();
|
|
Toshihiro Shimizu |
890ddd |
cmout = newRas;
|
|
Toshihiro Shimizu |
890ddd |
cmout->lock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Finally, do transparency check
|
|
Toshihiro Shimizu |
890ddd |
if (m_parameters->m_transparencyCheckEnabled)
|
|
Toshihiro Shimizu |
890ddd |
transparencyCheck(cmout, outRas);
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
//TRop::convert(outRas, cmout, m_parameters->m_cleanupPalette);
|
|
Toshihiro Shimizu |
890ddd |
TRop::convert(outRas, cmout, createToonzPaletteFromCleanupPalette());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
outRas->unlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TToonzImageP TCleanupper::doPostProcessingColor(const TToonzImageP &imgToProcess, bool isCleanupper)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
//(Build and) Copy imgToProcess to output image
|
|
Toshihiro Shimizu |
890ddd |
TToonzImageP outImage;
|
|
Toshihiro Shimizu |
890ddd |
if (isCleanupper)
|
|
Toshihiro Shimizu |
890ddd |
outImage = imgToProcess;
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
outImage = TToonzImageP(imgToProcess->cloneImage());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(outImage);
|
|
Toshihiro Shimizu |
890ddd |
assert(m_parameters->m_colors.getColorCount() < 9);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Perform post-processing
|
|
Toshihiro Shimizu |
890ddd |
TRasterCM32P outRasCM32 = outImage->getRaster();
|
|
Toshihiro Shimizu |
890ddd |
outRasCM32->lock();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Brightness/Contrast
|
|
Toshihiro Shimizu |
890ddd |
brightnessContrast(outRasCM32, m_parameters->m_colors);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Despeckling
|
|
Toshihiro Shimizu |
890ddd |
if (m_parameters->m_despeckling)
|
|
Toshihiro Shimizu |
890ddd |
TRop::despeckle(outRasCM32, m_parameters->m_despeckling, false);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Morphological antialiasing
|
|
Toshihiro Shimizu |
890ddd |
if (m_parameters->m_postAntialias) {
|
|
Toshihiro Shimizu |
890ddd |
TRasterCM32P newRas(outRasCM32->getLx(), outRasCM32->getLy());
|
|
Toshihiro Shimizu |
890ddd |
TRop::antialias(outRasCM32, newRas, 10, m_parameters->m_aaValue);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
outRasCM32->unlock();
|
|
Toshihiro Shimizu |
890ddd |
outRasCM32 = newRas;
|
|
Toshihiro Shimizu |
890ddd |
outImage->setCMapped(outRasCM32);
|
|
Toshihiro Shimizu |
890ddd |
outRasCM32->lock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRect bbox;
|
|
Toshihiro Shimizu |
890ddd |
TRop::computeBBox(outRasCM32, bbox);
|
|
Toshihiro Shimizu |
890ddd |
outImage->setSavebox(bbox);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
outRasCM32->unlock();
|
|
Toshihiro Shimizu |
890ddd |
return outImage;
|
|
Toshihiro Shimizu |
890ddd |
}
|