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
}