|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/toonzimageutils.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tstroke.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tpalette.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tofflinegl.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tvectorrenderdata.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tvectorgl.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "trop.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/ttileset.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tcenterlinevectorizer.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tregion.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "trasterimage.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "ttoonzimage.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "ttzpimagefx.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tlevel_io.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tsystem.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tstream.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tsimplecolorstyles.h"
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
namespace {
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const int BackgroundStyle = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRect rasterizeStroke(TOfflineGL *&gl, const TRect &rasBounds, TStroke *stroke,
|
|
Shinya Kitaoka |
120a6e |
TPalette *palette, const TRectD &clip, bool doAntialias) {
|
|
Shinya Kitaoka |
120a6e |
TRectD bbox = clip * stroke->getBBox();
|
|
Shinya Kitaoka |
120a6e |
TRect rect = convert(bbox).enlarge(1) * rasBounds;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (rect.getLx() <= 0 || rect.getLy() <= 0) return TRect();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
gl = new TOfflineGL(rect.getSize());
|
|
Shinya Kitaoka |
120a6e |
gl->makeCurrent();
|
|
Shinya Kitaoka |
120a6e |
gl->clear(TPixel32::White);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TPaletteP plt = palette->clone();
|
|
Shinya Kitaoka |
120a6e |
int styleId = stroke->getStyle();
|
|
Shinya Kitaoka |
120a6e |
TColorStyleP style = plt->getStyle(styleId);
|
|
Shinya Kitaoka |
120a6e |
assert(style);
|
|
Shinya Kitaoka |
120a6e |
style->setMainColor(TPixel32::Black);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TTranslation affine(-convert(rect.getP00()));
|
|
Shinya Kitaoka |
120a6e |
TVectorRenderData rd(affine, gl->getBounds(), plt.getPointer(), 0, false,
|
|
Shinya Kitaoka |
120a6e |
doAntialias);
|
|
Shinya Kitaoka |
120a6e |
tglDraw(rd, stroke);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
glFinish();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return rect;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRect rasterizeStroke(TOfflineGL *&gl, TRect rasBounds, TStroke *stroke,
|
|
Shinya Kitaoka |
120a6e |
TRectD clip, bool filled = false) {
|
|
Shinya Kitaoka |
120a6e |
TDimension d = rasBounds.getSize();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPointD offset(d.lx * 0.5, d.ly * 0.5);
|
|
Shinya Kitaoka |
120a6e |
TTranslation offsetMatrix(offset);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRectD strokeBBox = stroke->getBBox().enlarge(2);
|
|
Shinya Kitaoka |
120a6e |
if (!clip.isEmpty())
|
|
Shinya Kitaoka |
120a6e |
strokeBBox = offsetMatrix * (strokeBBox * clip);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
strokeBBox = offsetMatrix * strokeBBox;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRect rect = ToonzImageUtils::convertWorldToRaster(strokeBBox, 0) * rasBounds;
|
|
Shinya Kitaoka |
120a6e |
if (!rect.isEmpty()) {
|
|
Shinya Kitaoka |
120a6e |
gl = new TOfflineGL(rect.getSize());
|
|
Shinya Kitaoka |
120a6e |
gl->makeCurrent();
|
|
Shinya Kitaoka |
120a6e |
glClearColor(1, 1, 1, 1);
|
|
Shinya Kitaoka |
120a6e |
glClear(GL_COLOR_BUFFER_BIT);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPalette *palette = new TPalette();
|
|
Shinya Kitaoka |
120a6e |
TTranslation affine(-strokeBBox.getP00() + offset);
|
|
Shinya Kitaoka |
120a6e |
TVectorRenderData rd(affine, gl->getBounds(), palette, 0, false, true);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int oldStyle = stroke->getStyle();
|
|
Shinya Kitaoka |
120a6e |
stroke->setStyle(1);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (filled) {
|
|
Shinya Kitaoka |
120a6e |
TVectorImage vi;
|
|
Shinya Kitaoka |
120a6e |
vi.addStroke(new TStroke(*stroke));
|
|
Shinya Kitaoka |
120a6e |
vi.findRegions();
|
|
Shinya Kitaoka |
120a6e |
vi.selectFill(vi.getBBox().enlarge(2), 0, 1, false, true, false);
|
|
Shinya Kitaoka |
120a6e |
tglDraw(rd, &vi);
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
tglDraw(rd, stroke);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
delete palette;
|
|
Shinya Kitaoka |
120a6e |
stroke->setStyle(oldStyle);
|
|
Shinya Kitaoka |
120a6e |
glFinish();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return rect;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRect rasterizeRegion(TOfflineGL *&gl, TRect rasBounds, TRegion *region,
|
|
Shinya Kitaoka |
120a6e |
TRectD clip) {
|
|
Shinya Kitaoka |
120a6e |
TRectD regionBBox = region->getBBox();
|
|
Shinya Kitaoka |
120a6e |
if (!clip.isEmpty()) regionBBox = regionBBox * clip;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRect rect = convert(regionBBox) * rasBounds;
|
|
Shinya Kitaoka |
120a6e |
if (!rect.isEmpty()) {
|
|
Shinya Kitaoka |
120a6e |
gl = new TOfflineGL(rect.getSize());
|
|
Shinya Kitaoka |
120a6e |
gl->makeCurrent();
|
|
Shinya Kitaoka |
120a6e |
gl->clear(TPixel32::White);
|
|
Shinya Kitaoka |
120a6e |
glPushAttrib(GL_ALL_ATTRIB_BITS);
|
|
Shinya Kitaoka |
120a6e |
glEnable(GL_ALPHA_TEST);
|
|
Shinya Kitaoka |
120a6e |
glAlphaFunc(GL_GREATER, 0);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPalette *palette = new TPalette();
|
|
Shinya Kitaoka |
120a6e |
TTranslation affine(-convert(rect.getP00()));
|
|
Shinya Kitaoka |
120a6e |
TVectorRenderData rd(affine, gl->getBounds(), palette, 0, true, true);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int oldStyle = region->getStyle();
|
|
Shinya Kitaoka |
120a6e |
region->setStyle(1);
|
|
Shinya Kitaoka |
120a6e |
tglDraw(rd, region);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
glDisable(GL_ALPHA_TEST);
|
|
Shinya Kitaoka |
120a6e |
glPopAttrib();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
region->setStyle(oldStyle);
|
|
Shinya Kitaoka |
120a6e |
glFinish();
|
|
Shinya Kitaoka |
120a6e |
delete palette;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return rect;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void fastAddPaintRegion(const TToonzImageP &ti, TRegion *region, int newPaintId,
|
|
Shinya Kitaoka |
120a6e |
int maxStyleId, TRectD clip = TRectD()) {
|
|
Shinya Kitaoka |
120a6e |
TRasterCM32P ras = ti->getRaster();
|
|
Shinya Kitaoka |
120a6e |
TOfflineGL *gl;
|
|
Shinya Kitaoka |
120a6e |
TRect rect = rasterizeRegion(gl, ras->getBounds(), region, clip);
|
|
Shinya Kitaoka |
120a6e |
if (rect.isEmpty()) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRaster32P glRas = gl->getRaster();
|
|
Shinya Kitaoka |
120a6e |
assert(TPixelCM32::getMaxTone() == 255);
|
|
Shinya Kitaoka |
120a6e |
ras->lock();
|
|
Shinya Kitaoka |
120a6e |
glRas->lock();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (int y = rect.y0; y <= rect.y1; y++) {
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *inPix = glRas->pixels(y - rect.y0);
|
|
Shinya Kitaoka |
120a6e |
TPixelCM32 *outPix = ras->pixels(y) + rect.x0;
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *inEndPix = inPix + rect.x1 - rect.x0 + 1;
|
|
Shinya Kitaoka |
120a6e |
for (; inPix < inEndPix; ++outPix, ++inPix)
|
|
Shinya Kitaoka |
120a6e |
if (inPix->r < 128) {
|
|
Shinya Kitaoka |
120a6e |
outPix->setPaint(newPaintId);
|
|
Shinya Kitaoka |
120a6e |
outPix->setTone(255);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
ras->unlock();
|
|
Shinya Kitaoka |
120a6e |
glRas->unlock();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
delete gl;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRegion *subregion;
|
|
Shinya Kitaoka |
120a6e |
UINT i = 0;
|
|
Shinya Kitaoka |
120a6e |
for (; i < region->getSubregionCount(); ++i) {
|
|
Shinya Kitaoka |
120a6e |
subregion = region->getSubregion(i);
|
|
Shinya Kitaoka |
120a6e |
fastAddPaintRegion(ti, subregion,
|
|
Shinya Kitaoka |
120a6e |
std::min(maxStyleId, subregion->getStyle()), maxStyleId);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRect ToonzImageUtils::convertWorldToRaster(const TRectD area,
|
|
Shinya Kitaoka |
120a6e |
const TToonzImageP ti) {
|
|
Shinya Kitaoka |
120a6e |
if (area.isEmpty()) return TRect();
|
|
Shinya Kitaoka |
120a6e |
if (!ti || !ti->getRaster())
|
|
Shinya Kitaoka |
120a6e |
return TRect(tfloor(area.x0), tfloor(area.y0), tfloor(area.x1) - 1,
|
|
Shinya Kitaoka |
120a6e |
tfloor(area.y1) - 1);
|
|
Shinya Kitaoka |
120a6e |
TRasterCM32P ras = ti->getRaster();
|
|
Shinya Kitaoka |
120a6e |
TRectD rect(area + ras->getCenterD());
|
|
Shinya Kitaoka |
120a6e |
return TRect(tfloor(rect.x0), tfloor(rect.y0), tceil(rect.x1) - 1,
|
|
Shinya Kitaoka |
120a6e |
tceil(rect.y1) - 1);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRectD ToonzImageUtils::convertRasterToWorld(const TRect area,
|
|
Shinya Kitaoka |
120a6e |
const TToonzImageP ti) {
|
|
Shinya Kitaoka |
120a6e |
if (area.isEmpty()) return TRectD();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRectD rect(area.x0, area.y0, area.x1 + 1, area.y1 + 1);
|
|
Shinya Kitaoka |
120a6e |
if (ti && ti->getRaster()) rect = rect - ti->getRaster()->getCenterD();
|
|
Shinya Kitaoka |
120a6e |
return rect;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// clip in coordinate world (cioe' della stroke)
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// overlaying inks, blend inks always "lose" on normal inks
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRect fastAddInkStroke(const TToonzImageP &ti, TStroke *stroke, int inkId,
|
|
Shinya Kitaoka |
120a6e |
bool selective, bool filled, TRectD clip,
|
|
Shinya Kitaoka |
120a6e |
bool doAntialiasing = true,
|
|
Shinya Kitaoka |
120a6e |
const set<int> &blendInks = set<int>()) {</int></int>
|
|
Shinya Kitaoka |
120a6e |
TRasterCM32P ras = ti->getRaster();
|
|
Shinya Kitaoka |
120a6e |
TOfflineGL *gl = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRect rectRender = rasterizeStroke(gl, ras->getBounds(), stroke,
|
|
Shinya Kitaoka |
120a6e |
ti->getPalette(), clip, doAntialiasing);
|
|
Shinya Kitaoka |
120a6e |
if (!gl) return TRect();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRaster32P glRas = gl->getRaster();
|
|
Shinya Kitaoka |
120a6e |
TRasterCM32P outRas = ras->extract(rectRender);
|
|
Shinya Kitaoka |
120a6e |
assert(glRas->getSize() == outRas->getSize());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
assert(TPixelCM32::getMaxTone() == 255);
|
|
Shinya Kitaoka |
120a6e |
outRas->lock();
|
|
Shinya Kitaoka |
120a6e |
glRas->lock();
|
|
Shinya Kitaoka |
120a6e |
bool isBlendInkUp = (blendInks.find(inkId) != blendInks.end());
|
|
Shinya Kitaoka |
120a6e |
for (int y = 0; y < outRas->getLy(); ++y) {
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *inPix = glRas->pixels(y);
|
|
Shinya Kitaoka |
120a6e |
TPixelCM32 *outPix = outRas->pixels(y);
|
|
Shinya Kitaoka |
120a6e |
for (int x = 0; x < outRas->getLx(); ++outPix, ++inPix, ++x) {
|
|
Shinya Kitaoka |
120a6e |
int upTone = inPix->r;
|
|
Shinya Kitaoka |
120a6e |
int dnTone = outPix->getTone();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (doAntialiasing) {
|
|
Shinya Kitaoka |
120a6e |
// overlaying inks, blend inks always "lose" on normal inks
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool isBlendInkDn =
|
|
Shinya Kitaoka |
120a6e |
(blendInks.find(outPix->getInk()) != blendInks.end());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (isBlendInkUp && !isBlendInkDn && dnTone < 255) continue;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (isBlendInkDn && !isBlendInkUp && upTone < 255) {
|
|
Shinya Kitaoka |
120a6e |
*outPix = TPixelCM32(inkId, outPix->getPaint(), upTone);
|
|
Shinya Kitaoka |
120a6e |
continue;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// The upper pixel replaces the lower one, *if*
|
|
Shinya Kitaoka |
120a6e |
// a) It's more opaque
|
|
Shinya Kitaoka |
120a6e |
// b) If the ink id id not the same, ink is not completely transparent
|
|
Shinya Kitaoka |
120a6e |
// c) ...
|
|
Shinya Kitaoka |
120a6e |
if ((upTone <= dnTone) &&
|
|
Shinya Kitaoka |
120a6e |
((outPix->getInk() == inkId) || (upTone != 255)) &&
|
|
Shinya Kitaoka |
120a6e |
(!selective || !outPix->isPureInk()))
|
|
Shinya Kitaoka |
120a6e |
*outPix = TPixelCM32(inkId, outPix->getPaint(), upTone);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (!selective || !outPix->isPureInk()) {
|
|
Shinya Kitaoka |
120a6e |
// if(upTone<=192 && upTone<=dnTone)
|
|
Shinya Kitaoka |
120a6e |
if (upTone == 0) *outPix = TPixelCM32(inkId, outPix->getPaint(), 0);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
outRas->unlock();
|
|
Shinya Kitaoka |
120a6e |
glRas->unlock();
|
|
Shinya Kitaoka |
120a6e |
delete gl;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return rectRender;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// clip in coordinate world (cioe' della stroke)
|
|
Shinya Kitaoka |
120a6e |
TRect ToonzImageUtils::addInkStroke(const TToonzImageP &ti, TStroke *stroke,
|
|
Shinya Kitaoka |
120a6e |
int inkId, bool selective, bool filled,
|
|
Shinya Kitaoka |
120a6e |
TRectD clip, bool doAntialiasing) {
|
|
Shinya Kitaoka |
120a6e |
TStroke *s = new TStroke(*stroke);
|
|
Shinya Kitaoka |
120a6e |
TPoint tiCenter = ti->getRaster()->getCenter();
|
|
Shinya Kitaoka |
120a6e |
s->transform(TTranslation(tiCenter.x, tiCenter.y));
|
|
Shinya Kitaoka |
120a6e |
TRect rect =
|
|
Shinya Kitaoka |
120a6e |
fastAddInkStroke(ti, s, inkId, selective, filled, clip, doAntialiasing);
|
|
Shinya Kitaoka |
120a6e |
rect -= tiCenter;
|
|
Shinya Kitaoka |
120a6e |
return rect;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRect ToonzImageUtils::changeColorStroke(
|
|
Shinya Kitaoka |
120a6e |
const TToonzImageP &ti, const ChangeColorStrokeSettings &settings) {
|
|
Shinya Kitaoka |
120a6e |
if (!settings.changeInk && !settings.changePaint) return TRect();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRasterCM32P ras = ti->getRaster();
|
|
Shinya Kitaoka |
120a6e |
TOfflineGL *gl;
|
|
Shinya Kitaoka |
120a6e |
TRect rect =
|
|
Shinya Kitaoka |
120a6e |
rasterizeStroke(gl, ras->getBounds(), settings.stroke, settings.clip);
|
|
Shinya Kitaoka |
120a6e |
if (rect.isEmpty()) {
|
|
Shinya Kitaoka |
120a6e |
return rect;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
TRaster32P glRas = gl->getRaster();
|
|
Shinya Kitaoka |
120a6e |
ras->lock();
|
|
Shinya Kitaoka |
120a6e |
glRas->lock();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (int y = rect.y0; y <= rect.y1; ++y) {
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *inPix = glRas->pixels(y - rect.y0);
|
|
Shinya Kitaoka |
120a6e |
TPixelCM32 *outPix = ras->pixels(y) + rect.x0;
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *inEndPix = inPix + rect.x1 - rect.x0 + 1;
|
|
Shinya Kitaoka |
120a6e |
for (; inPix < inEndPix; ++outPix, ++inPix) {
|
|
Shinya Kitaoka |
120a6e |
if (inPix->r < 128 && settings.changeInk && !outPix->isPurePaint())
|
|
Shinya Kitaoka |
120a6e |
outPix->setInk(settings.colorId);
|
|
Shinya Kitaoka |
120a6e |
if (inPix->r < 128 && settings.changePaint &&
|
|
Shinya Kitaoka |
120a6e |
(settings.maskPaintId == -1 ||
|
|
Shinya Kitaoka |
120a6e |
outPix->getPaint() == settings.maskPaintId))
|
|
Shinya Kitaoka |
120a6e |
outPix->setPaint(settings.colorId);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
delete gl;
|
|
Shinya Kitaoka |
120a6e |
ras->unlock();
|
|
Shinya Kitaoka |
120a6e |
glRas->unlock();
|
|
Shinya Kitaoka |
120a6e |
return rect;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRect ToonzImageUtils::eraseRect(const TToonzImageP &ti, const TRectD &area,
|
|
Shinya Kitaoka |
120a6e |
int maskId, bool onInk, bool onPaint) {
|
|
Shinya Kitaoka |
120a6e |
assert(onInk || onPaint);
|
|
Shinya Kitaoka |
120a6e |
TRasterCM32P ras = ti->getRaster();
|
|
Shinya Kitaoka |
120a6e |
TRect rect = convertWorldToRaster(area, ti) * ras->getBounds();
|
|
Shinya Kitaoka |
120a6e |
if (rect.isEmpty()) return rect;
|
|
Shinya Kitaoka |
120a6e |
ras->lock();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (int y = rect.y0; y <= rect.y1; y++) {
|
|
Shinya Kitaoka |
120a6e |
TPixelCM32 *pix = ras->pixels(y) + rect.x0;
|
|
Shinya Kitaoka |
120a6e |
TPixelCM32 *endPix = ras->pixels(y) + rect.x1 + 1;
|
|
Shinya Kitaoka |
120a6e |
for (; pix < endPix; ++pix) {
|
|
Shinya Kitaoka |
120a6e |
if (onPaint && (maskId == -1 || maskId == pix->getPaint()))
|
|
Shinya Kitaoka |
120a6e |
pix->setPaint(BackgroundStyle);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (onInk && (maskId == -1 || maskId == pix->getInk()))
|
|
Shinya Kitaoka |
120a6e |
*pix = TPixelCM32(BackgroundStyle, pix->getPaint(),
|
|
Shinya Kitaoka |
120a6e |
TPixelCM32::getMaxTone());
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
ras->unlock();
|
|
Shinya Kitaoka |
120a6e |
return rect;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
std::vector<trect> ToonzImageUtils::paste(const TToonzImageP &ti,</trect>
|
|
Shinya Kitaoka |
120a6e |
const TTileSetCM32 *tileSet) {
|
|
Shinya Kitaoka |
120a6e |
std::vector<trect> rects;</trect>
|
|
Shinya Kitaoka |
120a6e |
TRasterCM32P raster = ti->getRaster();
|
|
Shinya Kitaoka |
120a6e |
// for(int i=0;i<tileset->getTileCount();i++)</tileset->
|
|
Shinya Kitaoka |
120a6e |
for (int i = tileSet->getTileCount() - 1; i >= 0; i--) {
|
|
Shinya Kitaoka |
120a6e |
const TTileSetCM32::Tile *tile = tileSet->getTile(i);
|
|
Shinya Kitaoka |
120a6e |
TRasterCM32P rasCM32;
|
|
Shinya Kitaoka |
120a6e |
tile->getRaster(rasCM32);
|
|
Shinya Kitaoka |
120a6e |
assert(!!rasCM32);
|
|
Shinya Kitaoka |
120a6e |
raster->copy(rasCM32, tile->m_rasterBounds.getP00());
|
|
Shinya Kitaoka |
120a6e |
rects.push_back(tile->m_rasterBounds);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return rects;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// DA RIFARE
|
|
Toshihiro Shimizu |
890ddd |
// e' lenta da far schifo
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
//! Converts a TVectorImage into a TToonzImage. The input vector image
|
|
Shinya Kitaoka |
120a6e |
//! is transformed through the passed affine \b aff, and put into a
|
|
Shinya Kitaoka |
120a6e |
//! TToonzImage strictly covering the bounding box of the transformed
|
|
Shinya Kitaoka |
120a6e |
//! vector image. The output image has its lower-left position in the
|
|
Shinya Kitaoka |
120a6e |
//! world reference specified by the \b pos parameter, which is granted to
|
|
Shinya Kitaoka |
120a6e |
//! be an integer displacement of the passed value. Additional parameters
|
|
Shinya Kitaoka |
120a6e |
//! include an integer \b enlarge by which the output image is enlarged with
|
|
Shinya Kitaoka |
120a6e |
//! respect to the transformed image's bbox, and the bool \b transformThickness
|
|
Shinya Kitaoka |
120a6e |
//! to specify whether the transformation should involve strokes' thickensses
|
|
Shinya Kitaoka |
120a6e |
//! or not.
|
|
Toshihiro Shimizu |
890ddd |
TToonzImageP ToonzImageUtils::vectorToToonzImage(
|
|
Shinya Kitaoka |
120a6e |
const TVectorImageP &vimage, const TAffine &aff, TPalette *palette,
|
|
Shinya Kitaoka |
120a6e |
const TPointD &outputPos, const TDimension &outputSize,
|
|
Shinya Kitaoka |
120a6e |
const std::vector<trasterfxrenderdatap> *fxs, bool transformThickness) {</trasterfxrenderdatap>
|
|
Shinya Kitaoka |
120a6e |
if (!vimage || !palette) return 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Transform the vector image through aff
|
|
Shinya Kitaoka |
120a6e |
TVectorImageP vi = vimage->clone();
|
|
Shinya Kitaoka |
120a6e |
vi->transform(aff, transformThickness);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Allocate the output ToonzImage
|
|
Shinya Kitaoka |
120a6e |
TRasterCM32P raster(outputSize.lx, outputSize.ly);
|
|
Shinya Kitaoka |
120a6e |
raster->clear();
|
|
Shinya Kitaoka |
120a6e |
TToonzImageP ti(raster, raster->getBounds());
|
|
Shinya Kitaoka |
120a6e |
ti->setPalette(palette->clone());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Shift outputPos to the origin
|
|
Shinya Kitaoka |
120a6e |
vi->transform(TTranslation(-outputPos));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int strokeCount = vi->getStrokeCount();
|
|
Shinya Kitaoka |
120a6e |
std::vector<int> strokeIndex(strokeCount);</int>
|
|
Shinya Kitaoka |
120a6e |
std::vector<tstroke *=""> strokes(strokeCount);</tstroke>
|
|
Shinya Kitaoka |
120a6e |
int maxStyleId = palette->getStyleCount() - 1;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int i;
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < strokeCount; ++i) {
|
|
Shinya Kitaoka |
120a6e |
strokeIndex[i] = i;
|
|
Shinya Kitaoka |
120a6e |
strokes[i] = vi->getStroke(i);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
vi->notifyChangedStrokes(strokeIndex, strokes);
|
|
Shinya Kitaoka |
120a6e |
int regionCount = vi->getRegionCount();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// In such reference, the clip for rendering strokes is the output size
|
|
Shinya Kitaoka |
120a6e |
TRectD clip(TDimensionD(outputSize.lx, outputSize.ly));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
set<int> colors;</int>
|
|
Shinya Kitaoka |
120a6e |
if (fxs) {
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < (int)fxs->size(); i++) {
|
|
Shinya Kitaoka |
120a6e |
SandorFxRenderData *sandorData =
|
|
Shinya Kitaoka |
120a6e |
dynamic_cast<sandorfxrenderdata *="">((*fxs)[i].getPointer());</sandorfxrenderdata>
|
|
Shinya Kitaoka |
120a6e |
if (sandorData && sandorData->m_type == BlendTz) {
|
|
Shinya Kitaoka |
120a6e |
std::string indexes =
|
|
Shinya Kitaoka |
120a6e |
::to_string(sandorData->m_blendParams.m_colorIndex);
|
|
Shinya Kitaoka |
120a6e |
std::vector<std::string> items;</std::string>
|
|
Shinya Kitaoka |
120a6e |
parseIndexes(indexes, items);
|
|
Shinya Kitaoka |
120a6e |
PaletteFilterFxRenderData paletteFilterData;
|
|
Shinya Kitaoka |
120a6e |
insertIndexes(items, &paletteFilterData);
|
|
Shinya Kitaoka |
120a6e |
colors.insert(paletteFilterData.m_colors.begin(),
|
|
Shinya Kitaoka |
120a6e |
paletteFilterData.m_colors.end());
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int k, l;
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < strokeCount;) {
|
|
Shinya Kitaoka |
120a6e |
// Draw all regions which have the same group.
|
|
Shinya Kitaoka |
120a6e |
for (k = 0; k < regionCount; ++k)
|
|
Shinya Kitaoka |
120a6e |
if (vi->areDifferentGroup(i, false, k, true) == -1) {
|
|
Shinya Kitaoka |
120a6e |
TRegion *region = vi->getRegion(k);
|
|
Shinya Kitaoka |
120a6e |
fastAddPaintRegion(ti, region, std::min(maxStyleId, region->getStyle()),
|
|
Shinya Kitaoka |
120a6e |
maxStyleId);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Find the first stroke which does not belong to the group
|
|
Shinya Kitaoka |
120a6e |
for (k = i;
|
|
Shinya Kitaoka |
120a6e |
k < strokeCount && vi->areDifferentGroup(i, false, k, false) == -1;
|
|
Shinya Kitaoka |
120a6e |
++k)
|
|
Shinya Kitaoka |
120a6e |
;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Draw all found strokes
|
|
Shinya Kitaoka |
120a6e |
for (l = i; l < k; ++l) {
|
|
Shinya Kitaoka |
120a6e |
TStroke *stroke = vi->getStroke(l);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool visible = false;
|
|
Shinya Kitaoka |
120a6e |
int styleId = stroke->getStyle();
|
|
Shinya Kitaoka |
120a6e |
TColorStyleP style = palette->getStyle(styleId);
|
|
Shinya Kitaoka |
120a6e |
assert(style);
|
|
Shinya Kitaoka |
120a6e |
int colorCount = style->getColorParamCount();
|
|
Shinya Kitaoka |
120a6e |
if (colorCount == 0)
|
|
Shinya Kitaoka |
120a6e |
visible = true;
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
visible = false;
|
|
Shinya Kitaoka |
120a6e |
for (int j = 0; j < style->getColorParamCount() && !visible; j++) {
|
|
Shinya Kitaoka |
120a6e |
TPixel32 color = style->getColorParamValue(j);
|
|
Shinya Kitaoka |
120a6e |
if (color.m != 0) visible = true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (visible)
|
|
Shinya Kitaoka |
120a6e |
fastAddInkStroke(ti, stroke, std::min(maxStyleId, stroke->getStyle()),
|
|
Shinya Kitaoka |
120a6e |
false, false, clip, true, colors);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
i = k;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return ti;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TPalette *ToonzImageUtils::loadTzPalette(const TFilePath &pltFile) {
|
|
Shinya Kitaoka |
120a6e |
TImageP pltImg;
|
|
Shinya Kitaoka |
120a6e |
TImageReader loader(pltFile);
|
|
Shinya Kitaoka |
120a6e |
pltImg = loader.load();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRasterImageP pltRasImg(pltImg);
|
|
Shinya Kitaoka |
120a6e |
if (!pltRasImg) return 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRaster32P rasPlt = pltRasImg->getRaster();
|
|
Shinya Kitaoka |
120a6e |
if (!rasPlt) return 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
std::map<int, std::pair<std::string,="" std::string="">> pltColorNames;</int,>
|
|
Shinya Kitaoka |
120a6e |
std::map<int, std::pair<std::string,="" std::string="">>::iterator it;</int,>
|
|
Shinya Kitaoka |
120a6e |
loader.getTzpPaletteColorNames(pltColorNames);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPalette *palette = new TPalette();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
const int offset = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
assert(rasPlt->getLy() == 2);
|
|
Shinya Kitaoka |
120a6e |
rasPlt->lock();
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *pixelRow = rasPlt->pixels(0);
|
|
Shinya Kitaoka |
120a6e |
int x = 0;
|
|
Shinya Kitaoka |
120a6e |
int count = palette->getStyleCount();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (; x < rasPlt->getLx(); ++x) {
|
|
Shinya Kitaoka |
120a6e |
TSolidColorStyle *style = new TSolidColorStyle(pixelRow[x]);
|
|
Shinya Kitaoka |
120a6e |
if ((it = pltColorNames.find(x)) != pltColorNames.end()) {
|
|
Shinya Kitaoka |
120a6e |
std::string styleName = it->second.second;
|
|
Shinya Kitaoka |
120a6e |
style->setName(::to_wstring(styleName));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (x < count) palette->setStyle(x, style);
|
|
Shinya Kitaoka |
120a6e |
// palette->setStyle(x, pixelRow[x]);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
palette->addStyle(style);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// aggiungo solo i colori usati (salvo il BG)
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPalette::Page *page = palette->getPage(0);
|
|
Shinya Kitaoka |
120a6e |
// nella pagina c'e' gia' lo sfondo e il colore 1:
|
|
Shinya Kitaoka |
120a6e |
// tolgo quest'ultimo
|
|
Shinya Kitaoka |
120a6e |
page->removeStyle(1);
|
|
Shinya Kitaoka |
120a6e |
// aggiungo gli altri
|
|
Shinya Kitaoka |
120a6e |
std::map<std::wstring, int=""> pages;</std::wstring,>
|
|
Shinya Kitaoka |
120a6e |
std::map<std::wstring, int="">::iterator itpage;</std::wstring,>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
pixelRow = rasPlt->pixels(1);
|
|
Shinya Kitaoka |
120a6e |
for (x = 0; x < rasPlt->getLx(); ++x) {
|
|
Shinya Kitaoka |
120a6e |
if ((it = pltColorNames.find(x)) != pltColorNames.end()) {
|
|
Shinya Kitaoka |
120a6e |
std::wstring pageName;
|
|
Shinya Kitaoka |
120a6e |
pageName = ::to_wstring(it->second.first);
|
|
Shinya Kitaoka |
120a6e |
if (x == 0) {
|
|
Shinya Kitaoka |
120a6e |
page = palette->getPage(0);
|
|
Shinya Kitaoka |
120a6e |
page->setName(pageName);
|
|
Shinya Kitaoka |
120a6e |
pages[pageName] = 0;
|
|
Shinya Kitaoka |
120a6e |
} else if ((itpage = pages.find(pageName)) != pages.end())
|
|
Shinya Kitaoka |
120a6e |
page = palette->getPage(itpage->second);
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
page = palette->addPage(pageName);
|
|
Shinya Kitaoka |
120a6e |
pages[pageName] = page->getIndex();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
page = palette->getPage(0);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (pixelRow[x].r == 255) page->addStyle(offset + x);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
rasPlt->unlock();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return palette;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void ToonzImageUtils::getUsedStyles(std::set<int> &styles,</int>
|
|
Shinya Kitaoka |
120a6e |
const TToonzImageP &ti) {
|
|
Shinya Kitaoka |
120a6e |
TRasterCM32P ras = ti->getRaster();
|
|
Shinya Kitaoka |
120a6e |
if (!ras) return;
|
|
Shinya Kitaoka |
120a6e |
int lx = ras->getLx();
|
|
Shinya Kitaoka |
120a6e |
int ly = ras->getLy();
|
|
Shinya Kitaoka |
120a6e |
ras->lock();
|
|
Shinya Kitaoka |
120a6e |
for (int y = 0; y < ly; y++) {
|
|
Shinya Kitaoka |
120a6e |
TPixelCM32 *pix = ras->pixels(y);
|
|
Shinya Kitaoka |
120a6e |
TPixelCM32 *endPix = pix + lx;
|
|
Shinya Kitaoka |
120a6e |
while (pix < endPix) {
|
|
Shinya Kitaoka |
120a6e |
styles.insert(pix->getInk());
|
|
Shinya Kitaoka |
120a6e |
styles.insert(pix->getPaint());
|
|
Shinya Kitaoka |
120a6e |
++pix;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
ras->unlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void ToonzImageUtils::scrambleStyles(const TToonzImageP &ti,
|
|
Shinya Kitaoka |
120a6e |
std::map<int, int=""> styleTable) {</int,>
|
|
Shinya Kitaoka |
120a6e |
TRasterCM32P ras = ti->getRaster();
|
|
Shinya Kitaoka |
120a6e |
if (!ras) return;
|
|
Shinya Kitaoka |
120a6e |
if (styleTable.empty()) return;
|
|
Shinya Kitaoka |
120a6e |
std::map<int, int="">::iterator it;</int,>
|
|
Shinya Kitaoka |
120a6e |
std::vector<int> lut(4096, -1);</int>
|
|
Shinya Kitaoka |
120a6e |
bool isIdentity = true;
|
|
Shinya Kitaoka |
120a6e |
for (it = styleTable.begin(); it != styleTable.end(); ++it) {
|
|
Shinya Kitaoka |
120a6e |
int j = it->first, k = it->second;
|
|
Shinya Kitaoka |
120a6e |
assert(j >= 0);
|
|
Shinya Kitaoka |
120a6e |
assert(j < 1000000);
|
|
Shinya Kitaoka |
120a6e |
if (j >= (int)lut.size()) lut.resize(j + 1, -1);
|
|
Shinya Kitaoka |
120a6e |
lut[j] = k;
|
|
Shinya Kitaoka |
120a6e |
if (j != k) isIdentity = false;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (isIdentity) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int m = lut.size();
|
|
Shinya Kitaoka |
120a6e |
int lx = ras->getLx();
|
|
Shinya Kitaoka |
120a6e |
int ly = ras->getLy();
|
|
Shinya Kitaoka |
120a6e |
ras->lock();
|
|
Shinya Kitaoka |
120a6e |
for (int y = 0; y < ly; y++) {
|
|
Shinya Kitaoka |
120a6e |
TPixelCM32 *pix = ras->pixels(y);
|
|
Shinya Kitaoka |
120a6e |
TPixelCM32 *endPix = pix + lx;
|
|
Shinya Kitaoka |
120a6e |
while (pix < endPix) {
|
|
Shinya Kitaoka |
120a6e |
int ink = pix->getInk();
|
|
Shinya Kitaoka |
120a6e |
if (0 <= ink && ink < m && lut[ink] >= 0) ink = lut[ink];
|
|
Shinya Kitaoka |
120a6e |
int paint = pix->getPaint();
|
|
Shinya Kitaoka |
120a6e |
if (0 <= paint && paint < m && lut[paint] >= 0) paint = lut[paint];
|
|
Shinya Kitaoka |
120a6e |
if (ink != pix->getInk() || paint != pix->getPaint()) {
|
|
Shinya Kitaoka |
120a6e |
*pix = TPixelCM32(ink, paint, pix->getTone());
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
++pix;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
ras->unlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef LEVO
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool ToonzImageUtils::convertToTlv(const TFilePath &levelPathIn) {
|
|
Shinya Kitaoka |
120a6e |
try {
|
|
Shinya Kitaoka |
120a6e |
TFilePath levelPathOut = levelPathIn.getParentDir() +
|
|
Shinya Kitaoka |
120a6e |
TFilePath(levelPathIn.getWideName() + L".tlv");
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TLevelReaderP lr(levelPathIn);
|
|
Shinya Kitaoka |
120a6e |
TLevelP level = lr->loadInfo();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TLevelWriterP lw(levelPathOut, 0);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPalette *plt = new TPalette();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TLevel::Iterator it = level->begin();
|
|
Shinya Kitaoka |
120a6e |
TLevel::Iterator end = level->end();
|
|
Shinya Kitaoka |
120a6e |
for (; it != level->end(); ++it) {
|
|
Shinya Kitaoka |
120a6e |
try {
|
|
Shinya Kitaoka |
120a6e |
TImageReaderP ir = lr->getFrameReader(it->first);
|
|
Shinya Kitaoka |
120a6e |
TRasterImageP img = ir->load();
|
|
Shinya Kitaoka |
120a6e |
double dpix, dpiy;
|
|
Shinya Kitaoka |
120a6e |
img->getDpi(dpix, dpiy);
|
|
Shinya Kitaoka |
120a6e |
TRasterCM32P raster(convert(img->getBBox()).getSize());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRop::convert(raster, img->getRaster());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TImageWriterP iw = lw->getFrameWriter(it->first);
|
|
Shinya Kitaoka |
120a6e |
TToonzImageP outimg(raster, raster->getBounds());
|
|
Shinya Kitaoka |
120a6e |
outimg->setDpi(dpix, dpiy);
|
|
Shinya Kitaoka |
120a6e |
outimg->setPalette(plt);
|
|
Shinya Kitaoka |
120a6e |
iw->save(outimg);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
} catch (...) {
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Shinya Kitaoka |
120a6e |
// string msg="Frame "+toString(it->first.getNumber())+": conversion
|
|
Shinya Kitaoka |
120a6e |
// failed!";
|
|
Shinya Kitaoka |
120a6e |
// cout << msg << endl;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TFilePath pltPath = lw->getFilePath().withNoFrame().withType("tpl");
|
|
Shinya Kitaoka |
120a6e |
if (TSystem::touchParentDir(pltPath)) {
|
|
Shinya Kitaoka |
120a6e |
if (TSystem::doesExistFileOrLevel(pltPath))
|
|
Shinya Kitaoka |
120a6e |
TSystem::removeFileOrLevel(pltPath);
|
|
Shinya Kitaoka |
120a6e |
TOStream os(pltPath);
|
|
Shinya Kitaoka |
120a6e |
os << plt;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
lr = TLevelReaderP();
|
|
Shinya Kitaoka |
120a6e |
lw = TLevelWriterP();
|
|
Shinya Kitaoka |
120a6e |
// delete plt;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Shinya Kitaoka |
120a6e |
} catch (...) {
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void ToonzImageUtils::eraseImage(const TToonzImageP &ti,
|
|
Shinya Kitaoka |
120a6e |
const TRaster32P &image, const TPoint &pos,
|
|
Shinya Kitaoka |
120a6e |
bool invert, bool eraseInk, bool erasePaint,
|
|
Shinya Kitaoka |
120a6e |
bool selective, int styleId) {
|
|
Shinya Kitaoka |
120a6e |
TRect rasBounds = ti->getRaster()->getBounds();
|
|
Shinya Kitaoka |
120a6e |
TRect imageBounds = image->getBounds() + pos;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (invert) {
|
|
Shinya Kitaoka |
120a6e |
/*----------------------------------------
|
|
Shinya Kitaoka |
120a6e |
┌───┬─┐
|
|
Shinya Kitaoka |
120a6e |
│③ │②│
|
|
Shinya Kitaoka |
120a6e |
├─┬─┤ │
|
|
Shinya Kitaoka |
120a6e |
│④│★│ │
|
|
Shinya Kitaoka |
120a6e |
│ ├─┴─┤
|
|
Shinya Kitaoka |
120a6e |
│ │① │
|
|
Shinya Kitaoka |
120a6e |
└─┴───┘
|
|
Shinya Kitaoka |
120a6e |
★はFreeHandで囲んだ領域のバウンディングボックス
|
|
Shinya Kitaoka |
120a6e |
外側のワクはラスタ画像のフチ
|
|
Shinya Kitaoka |
120a6e |
-----------------------------------------*/
|
|
Shinya Kitaoka |
120a6e |
TRect rect;
|
|
Shinya Kitaoka |
120a6e |
/*- ①の部分を消す -*/
|
|
Shinya Kitaoka |
120a6e |
if (rasBounds.y0 != imageBounds.y0) {
|
|
Shinya Kitaoka |
120a6e |
rect = TRect(imageBounds.x0, rasBounds.y0, rasBounds.x1, imageBounds.y0);
|
|
Shinya Kitaoka |
120a6e |
ToonzImageUtils::eraseRect(
|
|
Shinya Kitaoka |
120a6e |
ti, ToonzImageUtils::convertRasterToWorld(rect, ti),
|
|
Shinya Kitaoka |
120a6e |
selective ? styleId : -1, eraseInk, erasePaint);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
/*- ②の部分を消す -*/
|
|
Shinya Kitaoka |
120a6e |
if (imageBounds.x1 != rasBounds.x1) {
|
|
Shinya Kitaoka |
120a6e |
rect = TRect(imageBounds.x1, imageBounds.y0, rasBounds.x1, rasBounds.y1);
|
|
Shinya Kitaoka |
120a6e |
ToonzImageUtils::eraseRect(
|
|
Shinya Kitaoka |
120a6e |
ti, ToonzImageUtils::convertRasterToWorld(rect, ti),
|
|
Shinya Kitaoka |
120a6e |
selective ? styleId : -1, eraseInk, erasePaint);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
/*- ③の部分を消す -*/
|
|
Shinya Kitaoka |
120a6e |
if (imageBounds.y1 != rasBounds.y1) {
|
|
Shinya Kitaoka |
120a6e |
rect = TRect(rasBounds.x0, imageBounds.y1, imageBounds.x1, rasBounds.y1);
|
|
Shinya Kitaoka |
120a6e |
ToonzImageUtils::eraseRect(
|
|
Shinya Kitaoka |
120a6e |
ti, ToonzImageUtils::convertRasterToWorld(rect, ti),
|
|
Shinya Kitaoka |
120a6e |
selective ? styleId : -1, eraseInk, erasePaint);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
/*- ④の部分を消す -*/
|
|
Shinya Kitaoka |
120a6e |
if (rasBounds.x0 != imageBounds.x0) {
|
|
Shinya Kitaoka |
120a6e |
rect = TRect(rasBounds.x0, rasBounds.y0, imageBounds.x0, imageBounds.y1);
|
|
Shinya Kitaoka |
120a6e |
ToonzImageUtils::eraseRect(
|
|
Shinya Kitaoka |
120a6e |
ti, ToonzImageUtils::convertRasterToWorld(rect, ti),
|
|
Shinya Kitaoka |
120a6e |
selective ? styleId : -1, eraseInk, erasePaint);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRasterCM32P workRas = ti->getRaster()->extract(imageBounds);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int y;
|
|
Shinya Kitaoka |
120a6e |
for (y = 0; y < workRas->getLy(); y++) {
|
|
Shinya Kitaoka |
120a6e |
TPixelCM32 *outPix = workRas->pixels(y);
|
|
Shinya Kitaoka |
120a6e |
TPixelCM32 *outEndPix = outPix + workRas->getLx();
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *inPix = image->pixels(y);
|
|
Shinya Kitaoka |
120a6e |
for (outPix; outPix != outEndPix; outPix++, inPix++) {
|
|
Shinya Kitaoka |
120a6e |
bool canEraseInk =
|
|
Shinya Kitaoka |
120a6e |
!selective || (selective && styleId == outPix->getInk());
|
|
Shinya Kitaoka |
120a6e |
bool canErasePaint =
|
|
Shinya Kitaoka |
120a6e |
!selective || (selective && styleId == outPix->getPaint());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int paint, tone;
|
|
Shinya Kitaoka |
120a6e |
if (!invert) {
|
|
Shinya Kitaoka |
120a6e |
paint = inPix->m > 0 && erasePaint && canErasePaint
|
|
Shinya Kitaoka |
120a6e |
? 0
|
|
Shinya Kitaoka |
120a6e |
: outPix->getPaint();
|
|
Shinya Kitaoka |
120a6e |
tone = inPix->m > 0 && eraseInk && canEraseInk
|
|
Shinya Kitaoka |
120a6e |
? std::max(outPix->getTone(), (int)inPix->m)
|
|
Shinya Kitaoka |
120a6e |
: outPix->getTone();
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
paint = inPix->m < 255 && erasePaint && canErasePaint
|
|
Shinya Kitaoka |
120a6e |
? 0
|
|
Shinya Kitaoka |
120a6e |
: outPix->getPaint();
|
|
Shinya Kitaoka |
120a6e |
tone = inPix->m < 255 && eraseInk && canEraseInk
|
|
Shinya Kitaoka |
120a6e |
? std::max(outPix->getTone(), 255 - (int)inPix->m)
|
|
Shinya Kitaoka |
120a6e |
: outPix->getTone();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
*outPix = TPixelCM32(outPix->getInk(), paint, tone);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
std::string ToonzImageUtils::premultiply(const TFilePath &levelPath) {
|
|
Shinya Kitaoka |
120a6e |
assert(0);
|
|
Shinya Kitaoka |
120a6e |
/*
|
|
Toshihiro Shimizu |
890ddd |
if (levelPath==TFilePath())
|
|
Shinya Kitaoka |
120a6e |
return "";
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if(!TSystem::doesExistFileOrLevel(levelPath))
|
|
Shinya Kitaoka |
120a6e |
return string("Can't find level")+toString(levelPath.getWideString());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TFileType::Type type = TFileType::getInfo(levelPath);
|
|
Toshihiro Shimizu |
890ddd |
if(type == TFileType::CMAPPED_LEVEL)
|
|
Shinya Kitaoka |
120a6e |
return "Cannot premultiply the selected file.";
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (type == TFileType::VECTOR_LEVEL || type == TFileType::VECTOR_IMAGE)
|
|
Shinya Kitaoka |
120a6e |
return "Cannot premultiply a vector-based level.";
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (type != TFileType::RASTER_LEVEL && type != TFileType::RASTER_IMAGE)
|
|
Shinya Kitaoka |
120a6e |
return "Cannot premultiply the selected file.";
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
try
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
TLevelReaderP lr = TLevelReaderP(levelPath);
|
|
Shinya Kitaoka |
120a6e |
if (!lr) return "";
|
|
Shinya Kitaoka |
120a6e |
TLevelP level = lr->loadInfo();
|
|
Shinya Kitaoka |
120a6e |
if(!level || level->getFrameCount()==0) return "";
|
|
Shinya Kitaoka |
120a6e |
string format = levelPath.getType();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPropertyGroup* prop =
|
|
Shinya Kitaoka |
120a6e |
TApplication::instance()
|
|
Shinya Kitaoka |
120a6e |
->getCurrentScene()
|
|
Shinya Kitaoka |
120a6e |
->getProperties()
|
|
Shinya Kitaoka |
120a6e |
->getOutputProperties()
|
|
Shinya Kitaoka |
120a6e |
->getFileFormatProperties(format)
|
|
Shinya Kitaoka |
120a6e |
->clone();
|
|
Shinya Kitaoka |
120a6e |
assert(prop);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TEnumProperty *p = (TEnumProperty*)prop->getProperty("Bits Per Pixel");
|
|
Shinya Kitaoka |
120a6e |
int bpp = p?atoi((toString(p->getValue()).c_str())):32;
|
|
Shinya Kitaoka |
120a6e |
if (bpp!=32 && bpp!=64) //non ha senso premoltiplicare senza il canale alpha...
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
if (bpp<32)
|
|
Shinya Kitaoka |
120a6e |
p->setValue(L"32(RGBM)");
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
p->setValue(L"64(RGBM)");
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool isMovie = (format=="mov" || format=="avi" || format=="3gp");
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TLevelWriterP lw;
|
|
Shinya Kitaoka |
120a6e |
if (!isMovie)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
lw = TLevelWriterP(levelPath, prop);
|
|
Shinya Kitaoka |
120a6e |
if (!lw) return "";
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int count = 0;
|
|
Shinya Kitaoka |
120a6e |
TLevel::Iterator it = level->begin();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (;it!=level->end(); ++it)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
TImageReaderP ir = lr->getFrameReader(it->first);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRasterImageP rimg = (TRasterImageP)ir->load();
|
|
Shinya Kitaoka |
120a6e |
if (!rimg)
|
|
Shinya Kitaoka |
120a6e |
continue;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRop::premultiply(rimg->getRaster());
|
|
Shinya Kitaoka |
120a6e |
ir = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (isMovie)
|
|
Shinya Kitaoka |
120a6e |
level->setFrame(it->first, rimg);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
TImageWriterP iw = lw->getFrameWriter(it->first);
|
|
Shinya Kitaoka |
120a6e |
iw->save(rimg);
|
|
Shinya Kitaoka |
120a6e |
iw = 0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
lr = TLevelReaderP();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (isMovie)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
TSystem::deleteFile(levelPath);
|
|
Shinya Kitaoka |
120a6e |
lw = TLevelWriterP(levelPath, prop);
|
|
Shinya Kitaoka |
120a6e |
if (!lw) return "";
|
|
Shinya Kitaoka |
120a6e |
lw->save(level);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (prop)
|
|
Shinya Kitaoka |
120a6e |
delete prop;
|
|
Shinya Kitaoka |
120a6e |
}catch(...)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
return "Cannot premultiply the selected file.";
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
*/
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return "";
|
|
Toshihiro Shimizu |
890ddd |
}
|