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