/*-- (StylePickerTool内で)LineとAreaを切り替えてPickできる。mode: 0=Area, 1=Line, 2=Line&Areas(default) --*/ int StylePicker::pickStyleId(const TPointD &pos, double radius2, int mode) const { int styleId = 0; if (TToonzImageP ti = m_image) { TRasterCM32P ras = ti->getRaster(); TPoint point = getRasterPoint(pos); if (!ras->getBounds().contains(point)) return -1; TPixelCM32 col = ras->pixels(point.y)[point.x]; switch (mode) { case 0: //AREAS styleId = col.getPaint(); break; case 1: //LINES styleId = col.getInk(); break; case 2: //ALL (Line & Area) default: styleId = col.isPurePaint() ? col.getPaint() : col.getInk(); break; } } else if (TRasterImageP ri = m_image) { const TPalette *palette = m_palette.getPointer(); if (!palette) return -1; TRaster32P ras = ri->getRaster(); if (!ras) return -1; TPoint point = getRasterPoint(pos); if (!ras->getBounds().contains(point)) return -1; TPixel32 col = ras->pixels(point.y)[point.x]; styleId = palette->getClosestStyle(col); } else if (TVectorImageP vi = m_image) { // prima cerca lo stile della regione piu' vicina TRegion *r = vi->getRegion(pos); if (r) styleId = r->getStyle(); // poi cerca quello della stroke, ma se prima aveva trovato una regione, richiede che // il click sia proprio sopra la stroke, altrimenti cerca la stroke piu' vicina (max circa 10 pixel) const double maxDist2 = (styleId == 0) ? 100.0 * radius2 : 0; bool strokeFound; double dist2, w, thick; UINT index; //!funzionerebbe ancora meglio con un getNearestStroke che considera //la thickness, cioe' la min distance dalla outline e non dalla centerLine strokeFound = vi->getNearestStroke(pos, w, index, dist2); if (strokeFound) { TStroke *stroke = vi->getStroke(index); thick = stroke->getThickPoint(w).thick; if (dist2 - thick * thick < maxDist2) { assert(stroke); styleId = stroke->getStyle(); } } } return styleId; }
FullColorAreaFiller::FullColorAreaFiller(const TRaster32P &ras) : m_ras(ras) , m_bounds(ras->getBounds()) , m_pixels(ras->pixels()) , m_wrap(ras->getWrap()) , m_color(0) { m_ras->lock(); }
TImageP ImageFiller::build(int imFlags, void *extData) { assert(imFlags == ImageManager::none); // Fetch image assert(extData); ImageLoader::BuildExtData *data = (ImageLoader::BuildExtData *)extData; assert(data->m_subs == 0); const std::string &srcImgId = data->m_sl->getImageId(data->m_fid); TImageP img = ImageManager::instance()->getImage(srcImgId, imFlags, extData); if (img) { TRasterImageP ri = img; if (ri) { TRaster32P ras = ri->getRaster(); if (ras) { TRaster32P newRas = ras->clone(); FullColorAreaFiller filler(newRas); TPaletteP palette = new TPalette(); int styleId = palette->getPage(0)->addStyle(TPixel32::White); FillParameters params; params.m_palette = palette.getPointer(); params.m_styleId = styleId; params.m_minFillDepth = 0; params.m_maxFillDepth = 15; filler.rectFill(newRas->getBounds(), params, false); TRasterImageP ri = TRasterImageP(newRas); return ri; } } } // Error case: return a dummy image (is it really required?) TRaster32P ras(10, 10); ras->fill(TPixel32(127, 0, 127, 127)); return TRasterImageP(ras); }
void fill(const TRaster32P &ras, const TRaster32P &ref, const FillParameters ¶ms, TTileSaverFullColor *saver) { TPixel32 *pix, *limit, *pix0, *oldpix; int oldy, xa, xb, xc, xd, dy; int oldxc, oldxd; int matte, oldMatte; int x = params.m_p.x, y = params.m_p.y; TRaster32P workRas = ref ? ref : ras; TRect bbbox = workRas->getBounds(); if (!bbbox.contains(params.m_p)) return; TPaletteP plt = params.m_palette; TPixel32 color = plt->getStyle(params.m_styleId)->getMainColor(); int fillDepth = params.m_shiftFill ? params.m_maxFillDepth : params.m_minFillDepth; assert(fillDepth >= 0 && fillDepth < 16); fillDepth = ((15 - fillDepth) << 4) | (15 - fillDepth); // looking for any pure transparent pixel along the border; if after filling // that pixel will be changed, // it means that I filled the bg and the savebox needs to be recomputed! TPixel32 borderIndex; TPixel32 *borderPix = 0; pix = workRas->pixels(0); int i; for (i = 0; i < workRas->getLx(); i++, pix++) // border down if (pix->m == 0) { borderIndex = *pix; borderPix = pix; break; } if (borderPix == 0) // not found in border down...try border up (avoid left // and right borders...so unlikely) { pix = workRas->pixels(workRas->getLy() - 1); for (i = 0; i < workRas->getLx(); i++, pix++) // border up if (pix->m == 0) { borderIndex = *pix; borderPix = pix; break; } } std::stack<FillSeed> seeds; std::map<int, std::vector<std::pair<int, int>>> segments; // fillRow(r, params.m_p, xa, xb, color ,saver); findSegment(workRas, params.m_p, xa, xb, color); segments[y].push_back(std::pair<int, int>(xa, xb)); seeds.push(FillSeed(xa, xb, y, 1)); seeds.push(FillSeed(xa, xb, y, -1)); while (!seeds.empty()) { FillSeed fs = seeds.top(); seeds.pop(); xa = fs.m_xa; xb = fs.m_xb; oldy = fs.m_y; dy = fs.m_dy; y = oldy + dy; if (y > bbbox.y1 || y < bbbox.y0) continue; pix = pix0 = workRas->pixels(y) + xa; limit = workRas->pixels(y) + xb; oldpix = workRas->pixels(oldy) + xa; x = xa; oldxd = (std::numeric_limits<int>::min)(); oldxc = (std::numeric_limits<int>::max)(); while (pix <= limit) { oldMatte = threshMatte(oldpix->m, fillDepth); matte = threshMatte(pix->m, fillDepth); bool test = false; if (segments.find(y) != segments.end()) test = isPixelInSegment(segments[y], x); if (*pix != color && !test && matte >= oldMatte && matte != 255) { findSegment(workRas, TPoint(x, y), xc, xd, color); // segments[y].push_back(std::pair<int,int>(xc, xd)); insertSegment(segments[y], std::pair<int, int>(xc, xd)); if (xc < xa) seeds.push(FillSeed(xc, xa - 1, y, -dy)); if (xd > xb) seeds.push(FillSeed(xb + 1, xd, y, -dy)); if (oldxd >= xc - 1) oldxd = xd; else { if (oldxd >= 0) seeds.push(FillSeed(oldxc, oldxd, y, dy)); oldxc = xc; oldxd = xd; } pix += xd - x + 1; oldpix += xd - x + 1; x += xd - x + 1; } else { pix++; oldpix++, x++; } } if (oldxd > 0) seeds.push(FillSeed(oldxc, oldxd, y, dy)); } std::map<int, std::vector<std::pair<int, int>>>::iterator it; for (it = segments.begin(); it != segments.end(); it++) { TPixel32 *line = ras->pixels(it->first); TPixel32 *refLine = 0; TPixel32 *refPix; if (ref) refLine = ref->pixels(it->first); std::vector<std::pair<int, int>> segmentVector = it->second; for (int i = 0; i < (int)segmentVector.size(); i++) { std::pair<int, int> segment = segmentVector[i]; if (segment.second >= segment.first) { pix = line + segment.first; if (ref) refPix = refLine + segment.first; int n; for (n = 0; n < segment.second - segment.first + 1; n++, pix++) { if (ref) { *pix = *refPix; refPix++; } else *pix = pix->m == 0 ? color : overPix(color, *pix); } } } } }
GLuint MeshTexturizer::Imp::textureAlloc(const TRaster32P &ras, const TRaster32P &aux, int x, int y, int textureLx, int textureLy, bool premultiplied) { struct locals { static void clearMatte(const TRaster32P &ras, int xBegin, int yBegin, int xEnd, int yEnd) { for (int y = yBegin; y != yEnd; ++y) { TPixel32 *line = ras->pixels(y), *pixEnd = line + xEnd; for (TPixel32 *pix = line + xBegin; pix != pixEnd; ++pix) pix->m = 0; } } static void clearMatte_border(const TRaster32P &ras, int border0, int border1) { assert(border0 < border1); // Horizontal clearMatte(ras, border0, border0, ras->getLx() - border0, border1); clearMatte(ras, border0, ras->getLy() - border1, ras->getLx() - border0, ras->getLy() - border0); // Vertical clearMatte(ras, border0, border1, border1, ras->getLy() - border1); clearMatte(ras, ras->getLx() - border1, border1, ras->getLx() - border0, ras->getLy() - border1); } }; // locals // Prepare the texture tile assert(aux->getLx() >= textureLx + TOTAL_BORDER_2 && aux->getLy() >= textureLy + TOTAL_BORDER_2); TRect rasRect(x, y, x + textureLx - 1, y + textureLy - 1); rasRect = rasRect.enlarge(premultiplied ? COPIED_BORDER : COPIED_BORDER + NONPREM_BORDER); rasRect = rasRect * ras->getBounds(); TRect auxRect(rasRect - TPoint(x - TOTAL_BORDER, y - TOTAL_BORDER)); // An auxiliary raster must be used to supply the transparent border TRaster32P tex(aux->extract(0, 0, textureLx + TOTAL_BORDER_2 - 1, textureLy + TOTAL_BORDER_2 - 1)); tex->clear(); aux->extract(auxRect)->copy(ras->extract(rasRect)); if (!premultiplied && NONPREM_BORDER > 0) locals::clearMatte_border(aux, TRANSP_BORDER - NONPREM_BORDER, TRANSP_BORDER); // Pass the raster into VRAM GLuint texId; glGenTextures(1, &texId); glBindTexture(GL_TEXTURE_2D, texId); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); // These must be used on a bound texture, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); // and are remembered in the OpenGL context. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // They can be set here, no need for glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // the user to do it. glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->getWrap()); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexImage2D(GL_TEXTURE_2D, 0, // one level only GL_RGBA, // pixel channels count tex->getLx(), // width tex->getLy(), // height 0, // border size TGL_FMT, // pixel format GL_UNSIGNED_BYTE, // pixel data type (GLvoid *)tex->getRawData()); return texId; }