|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tbinarizer.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tpixelutils.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
namespace {
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Shinya Kitaoka |
120a6e |
// computeColor: RGB => colore(0=Black, 1=Red,2=Green,3=Blue), valore
|
|
Shinya Kitaoka |
120a6e |
// (=max(r,g,b)), croma (= max(r,g,b)-min(r,g,b))
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Shinya Kitaoka |
120a6e |
inline void computeColor(int &color, int &value, int &chroma,
|
|
Shinya Kitaoka |
120a6e |
const TPixel32 &pix) {
|
|
Shinya Kitaoka |
120a6e |
int c[3] = {pix.r, pix.g, pix.b};
|
|
Shinya Kitaoka |
120a6e |
// unrolled bubble-sort
|
|
Shinya Kitaoka |
120a6e |
if (c[0] < c[1]) qSwap(c[0], c[1]);
|
|
Shinya Kitaoka |
120a6e |
if (c[1] < c[2]) qSwap(c[1], c[2]);
|
|
Shinya Kitaoka |
120a6e |
if (c[0] < c[1]) qSwap(c[0], c[1]);
|
|
Shinya Kitaoka |
120a6e |
assert(c[0] >= c[1] && c[1] >= c[2]);
|
|
Shinya Kitaoka |
120a6e |
int cMax = c[0];
|
|
Shinya Kitaoka |
120a6e |
int cMin = c[2];
|
|
Shinya Kitaoka |
120a6e |
value = cMax;
|
|
Shinya Kitaoka |
120a6e |
chroma = cMax - cMin;
|
|
Shinya Kitaoka |
120a6e |
if (chroma == 0) {
|
|
Shinya Kitaoka |
120a6e |
color = 0;
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (pix.r == cMax)
|
|
Shinya Kitaoka |
120a6e |
color = 1;
|
|
Shinya Kitaoka |
120a6e |
else if (pix.g == cMax)
|
|
Shinya Kitaoka |
120a6e |
color = 2;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
color = 3;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/*
|
|
Shinya Kitaoka |
120a6e |
// quando gestiremo anche ciano, magenta e giallo
|
|
Shinya Kitaoka |
120a6e |
int cD0 = c[0]-c[1], cD1 = c[1]-c[2];
|
|
Shinya Kitaoka |
120a6e |
if(cD0>cD1)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Shinya Kitaoka |
120a6e |
if(pix.r==cMax) color=1;
|
|
Shinya Kitaoka |
120a6e |
else if(pix.g==cMax) color=2;
|
|
Shinya Kitaoka |
120a6e |
else color=3;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
if(pix.r==cMin) color=4;
|
|
Shinya Kitaoka |
120a6e |
else if(pix.g==cMin) color=5;
|
|
Shinya Kitaoka |
120a6e |
else color=6;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
*/
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// ritorna true se i primi pixel del buffer non sono tutti opachi
|
|
Shinya Kitaoka |
120a6e |
bool hasAlpha(const TPixel32 *buffer, int w, int h) {
|
|
Shinya Kitaoka |
120a6e |
int n = qMin(500, w * h);
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < n; i++)
|
|
Shinya Kitaoka |
120a6e |
if (buffer[i].m < 255) return true;
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// aggiunge un bianco opaco all'immagine (dovremmo gia' avere una funzione del
|
|
Shinya Kitaoka |
120a6e |
// genere, ma non l'ho trovata)
|
|
Shinya Kitaoka |
120a6e |
void removeAlpha(TPixel32 *buffer, int w, int h) {
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *pix = buffer;
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *endPix = pix + w * h;
|
|
Shinya Kitaoka |
120a6e |
while (pix < endPix) {
|
|
Shinya Kitaoka |
120a6e |
*pix = overPixOnWhite(*pix);
|
|
Shinya Kitaoka |
120a6e |
++pix;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
} // namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=========================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TBinarizer::TBinarizer() : m_alphaEnabled(true) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TBinarizer::process(const TRaster32P &ras) {
|
|
Shinya Kitaoka |
120a6e |
// palette di colori puri che verranno usati per l'output: nero, rosso, verde,
|
|
Shinya Kitaoka |
120a6e |
// blu
|
|
Shinya Kitaoka |
120a6e |
static const TPixel32 colors[] = {
|
|
Shinya Kitaoka |
120a6e |
TPixel32(0, 0, 0), TPixel32(255, 0, 0), TPixel32(0, 255, 0),
|
|
Shinya Kitaoka |
120a6e |
TPixel32(0, 0, 255), TPixel32(0, 255, 255), TPixel32(255, 0, 255),
|
|
Shinya Kitaoka |
120a6e |
TPixel32(255, 255, 0)};
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int w = ras->getLx(), h = ras->getLy();
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *buffer = ras->pixels(); // WARNING! non funziona sui sotto-raster
|
|
Shinya Kitaoka |
120a6e |
assert(ras->getWrap() == ras->getLx());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// mi cautelo contro immagini trasparenti
|
|
Shinya Kitaoka |
120a6e |
if (hasAlpha(buffer, w, h)) removeAlpha(buffer, w, h);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// divido l'immagine in quadrati grandi 2^b pixel
|
|
Shinya Kitaoka |
120a6e |
int b = 5;
|
|
Shinya Kitaoka |
120a6e |
int bsize = 1 << b;
|
|
Shinya Kitaoka |
120a6e |
int w1 = ((w - 1) >> b) + 1, h1 = ((h - 1) >> b) + 1;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// buffer di appoggio
|
|
Shinya Kitaoka |
120a6e |
std::vector<unsigned char=""> vBuffer(</unsigned>
|
|
Shinya Kitaoka |
120a6e |
w * h, 0); // per ogni pixel: v = min(r,g,b) (inchiostro scuro su sfondo
|
|
Shinya Kitaoka |
120a6e |
// chiaro: mi sembra che min funzioni meglio di max)
|
|
Shinya Kitaoka |
120a6e |
std::vector<unsigned char=""> thrBuffer(w1 * h1, 0); // per ogni quadrato: se</unsigned>
|
|
Shinya Kitaoka |
120a6e |
// v>thrBuffer[k1] allora
|
|
Shinya Kitaoka |
120a6e |
// siamo sicuro che e'
|
|
Shinya Kitaoka |
120a6e |
// sfondo
|
|
Shinya Kitaoka |
120a6e |
std::vector<unsigned char=""> qBuffer(w1 * h1, 0); // per ogni quadrato: quel v</unsigned>
|
|
Shinya Kitaoka |
120a6e |
// tale che solo 20 pixel in
|
|
Shinya Kitaoka |
120a6e |
// tutto il quadrato sono
|
|
Shinya Kitaoka |
120a6e |
// piu' scuri
|
|
Shinya Kitaoka |
120a6e |
std::vector<unsigned char=""> tBuffer(w * h, 255); // per ogni pixel: 'tipo' del</unsigned>
|
|
Shinya Kitaoka |
120a6e |
// pixel (0..6=>colore,
|
|
Shinya Kitaoka |
120a6e |
// 20=cornice esterna, )
|
|
Shinya Kitaoka |
120a6e |
std::vector<unsigned char=""> sBuffer(w * h, 255); // per ogni pixel: quando</unsigned>
|
|
Shinya Kitaoka |
120a6e |
// faccio il fill il colore
|
|
Shinya Kitaoka |
120a6e |
// si puo' estendere solo sui
|
|
Shinya Kitaoka |
120a6e |
// vicini con v
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
std::vector<int> boundary1, boundary2; // usati per il fill</int>
|
|
Shinya Kitaoka |
120a6e |
boundary1.reserve(w * h / 2);
|
|
Shinya Kitaoka |
120a6e |
boundary2.reserve(w * h / 2);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int goodBgQuadCount = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// per ogni quadrato costruisco l'istrogramma e determino il threshold per il
|
|
Shinya Kitaoka |
120a6e |
// bg
|
|
Shinya Kitaoka |
120a6e |
// conto i quadrati che hanno un "buon" background
|
|
Shinya Kitaoka |
120a6e |
for (int y1 = 0; y1 < h1; y1++) {
|
|
Shinya Kitaoka |
120a6e |
int ya = y1 * bsize;
|
|
Shinya Kitaoka |
120a6e |
int yb = qMin(h, ya + bsize) - 1;
|
|
Shinya Kitaoka |
120a6e |
for (int x1 = 0; x1 < w1; x1++) {
|
|
Shinya Kitaoka |
120a6e |
int xa = x1 * bsize;
|
|
Shinya Kitaoka |
120a6e |
int xb = qMin(w, xa + bsize) - 1;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int tot = 0;
|
|
Shinya Kitaoka |
120a6e |
std::vector<int> histo(32, 0);</int>
|
|
Shinya Kitaoka |
120a6e |
for (int y = ya; y <= yb; y++) {
|
|
Shinya Kitaoka |
120a6e |
for (int x = xa; x <= xb; x++) {
|
|
Shinya Kitaoka |
120a6e |
int k = y * w + x;
|
|
Shinya Kitaoka |
120a6e |
TPixel32 pix = buffer[k];
|
|
Shinya Kitaoka |
120a6e |
int v = qMin(qMin(pix.r, pix.g), pix.b);
|
|
Shinya Kitaoka |
120a6e |
vBuffer[k] = v;
|
|
Shinya Kitaoka |
120a6e |
histo[v >> 3] += 1;
|
|
Shinya Kitaoka |
120a6e |
tot += 1;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int bgThreshold = 31;
|
|
Shinya Kitaoka |
120a6e |
if (histo[31] > tot / 2 && histo[30] < 4) {
|
|
Shinya Kitaoka |
120a6e |
// "buon" background. Picco su histo[31] che finisce in histo[30]
|
|
Shinya Kitaoka |
120a6e |
goodBgQuadCount++;
|
|
Shinya Kitaoka |
120a6e |
bgThreshold = 29;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
// background normale. salto eventuali zeri (lo sfondo puo' essere
|
|
Shinya Kitaoka |
120a6e |
// grigio, anche scuro)
|
|
Shinya Kitaoka |
120a6e |
int i = 31;
|
|
Shinya Kitaoka |
120a6e |
while (i >= 0 && histo[i] == 0) i--;
|
|
Shinya Kitaoka |
120a6e |
int i0 = i;
|
|
Shinya Kitaoka |
120a6e |
// cerco il massimo
|
|
Shinya Kitaoka |
120a6e |
while (i > 0 && histo[i - 1] > histo[i]) i--;
|
|
Shinya Kitaoka |
120a6e |
int i1 = i;
|
|
MCCCS |
a0ce32 |
// presuppongo che il picco del BG sia symmetrico: i0-i1 == i1-i2
|
|
Shinya Kitaoka |
120a6e |
int i2 = 2 * i1 - i0;
|
|
Shinya Kitaoka |
120a6e |
bgThreshold = i2 - 1;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
// calcolo qBuffer[k1] : e' un valore di v tale che pochi pixel (<20)
|
|
Shinya Kitaoka |
120a6e |
// hanno un valore inferiore.
|
|
Shinya Kitaoka |
120a6e |
// Se qBuffer[k1] e' molto grande vuol dire che il quadrato e' vuoto
|
|
Shinya Kitaoka |
120a6e |
int i = 0;
|
|
Shinya Kitaoka |
120a6e |
int c = histo[i];
|
|
Shinya Kitaoka |
120a6e |
while (i < bgThreshold && c < 20) c += histo[++i];
|
|
Shinya Kitaoka |
120a6e |
int k1 = y1 * w1 + x1;
|
|
Shinya Kitaoka |
120a6e |
qBuffer[k1] = i * 255 / 31;
|
|
Shinya Kitaoka |
120a6e |
bgThreshold = bgThreshold * 255 / 31;
|
|
Shinya Kitaoka |
120a6e |
thrBuffer[k1] = bgThreshold;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// L'immagine ha un buon background se la maggior parte dei quadrati ha un
|
|
Shinya Kitaoka |
120a6e |
// buon background
|
|
Shinya Kitaoka |
120a6e |
bool goodBackground = goodBgQuadCount > w1 * h1 / 2;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// thrDelta e' una correzione sul threshold per immagini con cattivo
|
|
Shinya Kitaoka |
120a6e |
// background
|
|
Shinya Kitaoka |
120a6e |
// un quadrato che abbia meno di 20 (v.s sopra c<20) sotto
|
|
Shinya Kitaoka |
120a6e |
// thrBuffer[k1]-thrDelta e' considerato sfondo
|
|
Shinya Kitaoka |
120a6e |
int thrDelta = 0;
|
|
Shinya Kitaoka |
120a6e |
if (!goodBackground) thrDelta = 20;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// inizializzo la cornice dell'immagine (mi serve per non sconfinare quando
|
|
Shinya Kitaoka |
120a6e |
// faccio fill)
|
|
Shinya Kitaoka |
120a6e |
for (int y = 0; y < h; y++) tBuffer[y * w] = tBuffer[y * w + w - 1] = 20;
|
|
Shinya Kitaoka |
120a6e |
for (int x = 0; x < w; x++) tBuffer[x] = tBuffer[(h - 1) * w + x] = 20;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// cerco i pixel sicuramente colorati e i sicuramente neri
|
|
Shinya Kitaoka |
120a6e |
for (int y1 = 0; y1 < h1; y1++) {
|
|
Shinya Kitaoka |
120a6e |
int ya = qMax(1, y1 * bsize);
|
|
Shinya Kitaoka |
120a6e |
int yb = qMin(h - 1, ya + bsize) - 1;
|
|
Shinya Kitaoka |
120a6e |
for (int x1 = 0; x1 < w1; x1++) {
|
|
Shinya Kitaoka |
120a6e |
int k1 = y1 * w1 + x1;
|
|
Shinya Kitaoka |
120a6e |
// salto i quadrati completamente bianchi
|
|
Shinya Kitaoka |
120a6e |
if (qBuffer[k1] >= thrBuffer[k1] - thrDelta) continue;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (int y = ya + 1; y <= yb; y++) {
|
|
Shinya Kitaoka |
120a6e |
int xa = qMax(1, x1 * bsize);
|
|
Shinya Kitaoka |
120a6e |
int xb = qMin(w - 1, xa + bsize) - 1;
|
|
Shinya Kitaoka |
120a6e |
for (int x = xa + 1; x <= xb; x++) {
|
|
Shinya Kitaoka |
120a6e |
int k = y * w + x;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int vk = vBuffer[k];
|
|
Shinya Kitaoka |
120a6e |
int vk2 = vk;
|
|
Shinya Kitaoka |
120a6e |
if (vk < thrBuffer[k1]) {
|
|
Shinya Kitaoka |
120a6e |
// vk
|
|
Shinya Kitaoka |
120a6e |
bool isSeed = false;
|
|
Shinya Kitaoka |
120a6e |
if (vk2 <= vBuffer[k + 1] && vk2 <= vBuffer[k - 1] &&
|
|
Shinya Kitaoka |
120a6e |
vk2 <= vBuffer[k + w] && vk2 <= vBuffer[k - w]) {
|
|
Shinya Kitaoka |
120a6e |
// il pixel e' un minimo locale. calcolo il colore
|
|
Shinya Kitaoka |
120a6e |
int color, value, chroma;
|
|
Shinya Kitaoka |
120a6e |
computeColor(color, value, chroma, buffer[k]);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
const int chromaThreshold = 40;
|
|
Shinya Kitaoka |
120a6e |
if (chroma > chromaThreshold) {
|
|
Shinya Kitaoka |
120a6e |
// il pixel e' un buon candidato ad essere "sicuramente
|
|
Shinya Kitaoka |
120a6e |
// colorato": controllo i vicini
|
|
Shinya Kitaoka |
120a6e |
// per evitare i pixel colorati sparsi (sulle linee nere).
|
|
Shinya Kitaoka |
120a6e |
int m = 0;
|
|
Shinya Kitaoka |
120a6e |
int dd[] = {1, -1, w, -w, 1 + w, 1 - w, -1 + w, -1 - w};
|
|
Shinya Kitaoka |
120a6e |
for (int j = 0; j < 8; j++) {
|
|
Shinya Kitaoka |
120a6e |
int c1, v1, ch1;
|
|
Shinya Kitaoka |
120a6e |
computeColor(c1, v1, ch1, buffer[k + dd[j]]);
|
|
Shinya Kitaoka |
120a6e |
if (ch1 > 20 && c1 == color) m++;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
// scarto se intorno non ci sono almeno due pixel dello stesso
|
|
Shinya Kitaoka |
120a6e |
// colore
|
|
Shinya Kitaoka |
120a6e |
// n.b. lascio un valore alto per chroma per evitare che il
|
|
Shinya Kitaoka |
120a6e |
// pixel possa diventare "sicuramente nero". vedi sotto
|
|
Shinya Kitaoka |
120a6e |
if (m < 2) chroma = chromaThreshold - 1;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (chroma > chromaThreshold) {
|
|
Shinya Kitaoka |
120a6e |
// "sicuramente" colorato
|
|
Shinya Kitaoka |
120a6e |
tBuffer[k] = color;
|
|
Shinya Kitaoka |
120a6e |
isSeed = true;
|
|
Shinya Kitaoka |
120a6e |
} else if (chroma < 15 &&
|
|
Shinya Kitaoka |
120a6e |
vBuffer[k] * 100 <
|
|
Shinya Kitaoka |
120a6e |
qBuffer[k1] * 25 +
|
|
Shinya Kitaoka |
120a6e |
(thrBuffer[k1] - thrDelta) * 75) {
|
|
Shinya Kitaoka |
120a6e |
// molto poco colorato e scuro (al 25% della distanza fra
|
|
Shinya Kitaoka |
120a6e |
// qBuffer[] e bg) => "sicuramente" nero
|
|
Shinya Kitaoka |
120a6e |
tBuffer[k] = 0;
|
|
Shinya Kitaoka |
120a6e |
isSeed = true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (isSeed) {
|
|
Shinya Kitaoka |
120a6e |
// se il pixel e' sicuramente colorato o sicuramente nero diventa
|
|
Shinya Kitaoka |
120a6e |
// un seme per il fill
|
|
Shinya Kitaoka |
120a6e |
// il fill si deve fermare quando sono al 50% della distanza verso
|
|
Shinya Kitaoka |
120a6e |
// il bg
|
|
Shinya Kitaoka |
120a6e |
sBuffer[k] = (vBuffer[k] + thrBuffer[k1]) / 2;
|
|
Shinya Kitaoka |
120a6e |
boundary1.push_back(k);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// vado avanti finche' ci sono semi, ma non oltre 10 iterazioni
|
|
Shinya Kitaoka |
120a6e |
for (int it = 0; it < 10 && !boundary1.empty(); it++) {
|
|
Shinya Kitaoka |
120a6e |
// per tutti i semi
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)boundary1.size(); i++) {
|
|
Shinya Kitaoka |
120a6e |
int k = boundary1[i];
|
|
Shinya Kitaoka |
120a6e |
// per ogni direzione
|
|
Shinya Kitaoka |
120a6e |
const int dd[] = {1, -1, w, -w};
|
|
Shinya Kitaoka |
120a6e |
for (int j = 0; j < 4; j++) {
|
|
Shinya Kitaoka |
120a6e |
int ka = dd[j] + k;
|
|
Shinya Kitaoka |
120a6e |
// se il pixel adiacente non e' gia' colorato (e non e' la cornice
|
|
Shinya Kitaoka |
120a6e |
// esterna) e ha un v ancora abbastanza scuro...
|
|
Shinya Kitaoka |
120a6e |
if (tBuffer[ka] > 20 && vBuffer[ka] < sBuffer[k]) {
|
|
Shinya Kitaoka |
120a6e |
// lo coloro e lo faccio diventare un nuovo seme
|
|
Shinya Kitaoka |
120a6e |
tBuffer[ka] = tBuffer[k];
|
|
Shinya Kitaoka |
120a6e |
sBuffer[ka] = sBuffer[k];
|
|
Shinya Kitaoka |
120a6e |
boundary2.push_back(ka);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
// scambio i buffer
|
|
Shinya Kitaoka |
120a6e |
boundary1.clear();
|
|
Shinya Kitaoka |
120a6e |
boundary1.swap(boundary2);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// output
|
|
Shinya Kitaoka |
120a6e |
TPixel32 bgColor =
|
|
Shinya Kitaoka |
120a6e |
m_alphaEnabled ? TPixel32(0, 0, 0, 0) : TPixel32(255, 255, 255);
|
|
Shinya Kitaoka |
120a6e |
for (int y = 0; y < h; y++) {
|
|
Shinya Kitaoka |
120a6e |
for (int x = 0; x < w; x++) {
|
|
Shinya Kitaoka |
120a6e |
int k = y * w + x;
|
|
Shinya Kitaoka |
120a6e |
if (tBuffer[k] <= 6)
|
|
Shinya Kitaoka |
120a6e |
buffer[k] = colors[tBuffer[k]];
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
buffer[k] = bgColor;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|