uint8_t ADMVideoDeinterlace::getFrameNumberNoAlloc(uint32_t frame, uint32_t *len, ADMImage *data, uint32_t *flags) { //uint8_t *dst,*dstu,*dstv,*srcu,*srcv; uint32_t uvlen; if(frame>=_info.nb_frames) return 0; // read uncompressed frame if(!_in->getFrameNumberNoAlloc(frame, len,_uncompressed,flags)) return 0; uvlen= _info.width*_info.height; *len= (uvlen*3)>>1; // No interleaving detected if(!hasMotion(_uncompressed)) { data->duplicate(_uncompressed); } else { //printf("Blending\n"); doBlend(_uncompressed,data); memcpy(UPLANE(data),UPLANE(_uncompressed),uvlen>>2); memcpy(VPLANE(data),VPLANE(_uncompressed),uvlen>>2); data->copyInfo(_uncompressed); } return 1; }
void AutoBlend::init() { // Add widget auto toolsWidgetContainer = new QWidget(); widget = new Ui::AutoBlendWidget(); widget->setupUi(toolsWidgetContainer); widgetProxy = new QGraphicsProxyWidget(this); widgetProxy->setWidget(toolsWidgetContainer); // Place at bottom left corner auto delta = widgetProxy->sceneBoundingRect().bottomLeft() - scene()->views().front()->rect().bottomLeft(); widgetProxy->moveBy(-delta.x(), -delta.y()); // Fill categories box { for(auto cat : document->categories.keys()){ widget->categoriesBox->insertItem(widget->categoriesBox->count(), cat); } int idx = widget->categoriesBox->findText(document->categoryOf(document->firstModelName())); widget->categoriesBox->setCurrentIndex(idx); } // Create gallery of shapes gallery = new Gallery(this, QRectF(0,0,this->bounds.width(), 220)); // Create container that holds results results = new Gallery(this, QRectF(0,0, this->bounds.width(), bounds.height() - gallery->boundingRect().height()), QRectF(0,0,256,256), true); results->moveBy(0, gallery->boundingRect().height()); // Gallery on top of results gallery->setZValue(results->zValue() + 10); auto dropShadow = new QGraphicsDropShadowEffect(); dropShadow->setOffset(0, 5); dropShadow->setColor(QColor(0, 0, 0, 150)); dropShadow->setBlurRadius(10); gallery->setGraphicsEffect(dropShadow); // Connect UI with actions { connect(widget->categoriesBox, &QComboBox::currentTextChanged, [&](QString text){ document->currentCategory = text; }); connect(widget->analyzeButton, &QPushButton::pressed, [&](){ document->computePairwise(widget->categoriesBox->currentText()); }); // Default view angle { // Camera target and initial position auto camera = new Eigen::Camera(); auto frame = camera->frame(); frame.position = Eigen::Vector3f(-1, 0, 0.5); camera->setTarget(Eigen::Vector3f(0, 0, 0.5)); camera->setFrame(frame); int deltaZoom = document->extent().length() * 1.0; // Default view angle double theta1 = acos(-1) * 0.75; double theta2 = acos(-1) * 0.10; camera->rotateAroundTarget(Eigen::Quaternionf(Eigen::AngleAxisf(theta1, Eigen::Vector3f::UnitY()))); camera->zoom(-(4+deltaZoom)); camera->rotateAroundTarget(Eigen::Quaternionf(Eigen::AngleAxisf(theta2, Eigen::Vector3f::UnitX()))); auto cp = camera->position(); cameraPos = QVector3D(cp[0], cp[1], cp[2]); // Camera settings camera->setViewport(128, 128); Eigen::Matrix4f p = camera->projectionMatrix(); Eigen::Matrix4f v = camera->viewMatrix().matrix(); p.transposeInPlace(); v.transposeInPlace(); cameraMatrix = QMatrix4x4(p.data()) * QMatrix4x4(v.data()); } connect(document, &Document::categoryAnalysisDone, [=](){ if (gallery == nullptr) return; // Fill gallery gallery->clearThumbnails(); auto catModels = document->categories[document->currentCategory].toStringList(); for (auto targetName : catModels) { auto targetModel = document->cacheModel(targetName); auto t = gallery->addTextItem(targetName); QVariantMap data = t->data; data["targetName"].setValue(targetName); t->setData(data); t->setCamera(cameraPos, cameraMatrix); t->setFlag(QGraphicsItem::ItemIsSelectable); // Add parts of target shape for (auto n : targetModel->nodes){ t->addAuxMesh(toBasicMesh(targetModel->getMesh(n->id), n->vis_property["color"].value<QColor>())); } scene()->update(t->sceneBoundingRect()); } scene()->update(this->sceneBoundingRect()); QTimer::singleShot(500, [=]{ gallery->update(); }); }); // Do blend connect(widget->blendButton, SIGNAL(pressed()), SLOT(doBlend())); } }
uint8_t ADMVideoTelecide::getFrameNumberNoAlloc(uint32_t frame, uint32_t *len, ADMImage *data, uint32_t *flags) { uint32_t uvlen; uint32_t dummylen; uint8_t motion; uint32_t cmatch,nmatch,n2match; ADMImage *cur,*next; if(frame>=_info.nb_frames) return 0; uvlen= _info.width*_info.height; *len=uvlen+(uvlen>>1); cur=vidCache->getImage(frame); if(!cur) return 0; data->copyInfo(cur); if(!frame || frame==_info.nb_frames-1) { data->duplicate(cur); vidCache->unlockAll(); return 1; } next=vidCache->getImage(frame-1); if(!next) { vidCache->unlockAll(); return 0; } // for u & v , no action -> copy it as is memcpy(UPLANE(data),UPLANE(cur),uvlen>>2); memcpy(VPLANE(data),VPLANE(cur),uvlen>>2); data->copyInfo(cur); // No interleaving detected if(!(motion=hasMotion(data)) ) { printf("\n Not interlaced !\n"); memcpy(YPLANE(data),YPLANE(cur),uvlen); vidCache->unlockAll(); return 1; // over ! } // else cmatch is the current match cmatch=getMatch(cur); /* ------------------------------------------------------------------------------------ Try to complete with next frame fields ----------------------------------------------------------------------------------- */ // Interleav next in even field interleave(cur,_uncompressed,1); interleave(next,_uncompressed,0); nmatch=getMatch(_uncompressed); interleave(cur,_uncompressed,0); interleave(next,_uncompressed,1); n2match=getMatch(_uncompressed); printf(" Cur : %lu \n",cmatch); printf(" Next : %lu \n",nmatch); printf(" NextP: %lu \n",n2match); if((cmatch<nmatch)&&(cmatch<n2match)) { printf("\n __ pure interlaced __\n"); interleave(cur,_uncompressed,0); interleave(cur,_uncompressed,1); hasMotion(_uncompressed); doBlend(_uncompressed,data); vidCache->unlockAll(); return 1; } if( nmatch > n2match) { printf("\n -------Shifted-P is better \n"); if(hasMotion(_uncompressed)) { doBlend(_uncompressed,data); printf(" but there is still motion \n"); } else data->duplicate(_uncompressed); } else { printf("\n -------Shifted-O is better \n"); interleave(cur,_uncompressed,1); interleave(next,_uncompressed,0); if(hasMotion(_uncompressed)) { doBlend(_uncompressed,data); printf(" but there is still motion \n"); } else data->duplicate(_uncompressed); } // which chroma is better ? from current or from next ? // search for a transition and see if there is also one ? vidCache->unlockAll(); return 1; }
void blend(TToonzImageP ti, TRasterPT<PIXEL> rasOut, const std::vector<BlendParam> ¶ms) { assert(ti->getRaster()->getSize() == rasOut->getSize()); // Extract the interesting raster. It should be the savebox of passed cmap, // plus - if // some param has the 0 index as blending color - the intensity of that blend // param. unsigned int i, j; TRect saveBox(ti->getSavebox()); int enlargement = 0; for (i = 0; i < params.size(); ++i) for (j = 0; j < params[i].colorsIndexes.size(); ++j) if (params[i].colorsIndexes[j] == 0) enlargement = std::max(enlargement, tceil(params[i].intensity)); saveBox = saveBox.enlarge(enlargement); TRasterCM32P cmIn(ti->getRaster()->extract(saveBox)); TRasterPT<PIXEL> rasOutExtract = rasOut->extract(saveBox); // Ensure that cmIn and rasOut have the same size unsigned int lx = cmIn->getLx(), ly = cmIn->getLy(); // Build the pure colors infos SelectionRaster selectionRaster(cmIn); // Now, build a little group of BlurPatterns - and for each, one for passed // param. // A small number of patterns per param is needed to make the pattern look not // ever the same. const int blurPatternsPerParam = 10; std::vector<BlurPatternContainer> blurGroup(params.size()); for (i = 0; i < params.size(); ++i) { BlurPatternContainer &blurContainer = blurGroup[i]; blurContainer.reserve(blurPatternsPerParam); for (j = 0; j < blurPatternsPerParam; ++j) blurContainer.push_back(BlurPattern( params[i].intensity, params[i].smoothness, params[i].stopAtCountour)); } // Build the palette TPalette *palette = ti->getPalette(); std::vector<TPixel32> paletteColors; paletteColors.resize(palette->getStyleCount()); for (i = 0; i < paletteColors.size(); ++i) paletteColors[i] = premultiply(palette->getStyle(i)->getAverageColor()); // Build the 4 auxiliary rasters for the blending procedure: they are ink / // paint versus input / output in the blend. // The output raster is reused to spare some memory - it should be, say, the // inkLayer's second at the end of the overall // blending procedure. It could be the first, without the necessity of // clearing it before blending the layers, but things // get more complicated when PIXEL is TPixel64... RGBMRasterPair inkLayer, paintLayer; TRaster32P rasOut32P_1(lx, ly, lx, (TPixel32 *)rasOut->getRawData(), false); inkLayer.first = (params.size() % 2) ? rasOut32P_1 : TRaster32P(lx, ly); inkLayer.second = (params.size() % 2) ? TRaster32P(lx, ly) : rasOut32P_1; if (PIXEL::maxChannelValue >= TPixel64::maxChannelValue) { TRaster32P rasOut32P_2(lx, ly, lx, ((TPixel32 *)rasOut->getRawData()) + lx * ly, false); paintLayer.first = (params.size() % 2) ? rasOut32P_2 : TRaster32P(lx, ly); paintLayer.second = (params.size() % 2) ? TRaster32P(lx, ly) : rasOut32P_2; } else { paintLayer.first = TRaster32P(lx, ly); paintLayer.second = TRaster32P(lx, ly); } inkLayer.first->clear(); inkLayer.second->clear(); paintLayer.first->clear(); paintLayer.second->clear(); // Now, we have to perform the blur of each of the cm's pixels. cmIn->lock(); rasOut->lock(); inkLayer.first->lock(); inkLayer.second->lock(); paintLayer.first->lock(); paintLayer.second->lock(); // Convert the initial cmIn to fullcolor ink - paint layers buildLayers(cmIn, paletteColors, inkLayer.first, paintLayer.first); // Perform the blend on separated ink - paint layers for (i = 0; i < params.size(); ++i) { if (params[i].colorsIndexes.size() == 0) continue; selectionRaster.updateSelection(cmIn, params[i]); doBlend(cmIn, inkLayer, paintLayer, selectionRaster, blurGroup[i]); tswap(inkLayer.first, inkLayer.second); tswap(paintLayer.first, paintLayer.second); } // Release the unnecessary rasters inkLayer.second->unlock(); paintLayer.second->unlock(); inkLayer.second = TRaster32P(); paintLayer.second = TRaster32P(); // Clear rasOut - since it was reused to spare space... rasOut->clear(); // Add the ink & paint layers on the output raster double PIXELmaxChannelValue = PIXEL::maxChannelValue; double toPIXELFactor = PIXELmaxChannelValue / (double)TPixel32::maxChannelValue; double inkFactor, paintFactor; TPoint pos; PIXEL *outPix, *outBegin = (PIXEL *)rasOutExtract->getRawData(); TPixelCM32 *cmPix, *cmBegin = (TPixelCM32 *)cmIn->getRawData(); int wrap = rasOutExtract->getWrap(); TPixel32 *inkPix = (TPixel32 *)inkLayer.first->getRawData(); TPixel32 *paintPix = (TPixel32 *)paintLayer.first->getRawData(); for (i = 0; i < ly; ++i) { outPix = outBegin + wrap * i; cmPix = cmBegin + wrap * i; for (j = 0; j < lx; ++j, ++outPix, ++cmPix, ++inkPix, ++paintPix) { getFactors(cmPix->getTone(), inkFactor, paintFactor); outPix->r = tcrop( toPIXELFactor * (inkFactor * inkPix->r + paintFactor * paintPix->r), 0.0, PIXELmaxChannelValue); outPix->g = tcrop( toPIXELFactor * (inkFactor * inkPix->g + paintFactor * paintPix->g), 0.0, PIXELmaxChannelValue); outPix->b = tcrop( toPIXELFactor * (inkFactor * inkPix->b + paintFactor * paintPix->b), 0.0, PIXELmaxChannelValue); outPix->m = tcrop( toPIXELFactor * (inkFactor * inkPix->m + paintFactor * paintPix->m), 0.0, PIXELmaxChannelValue); } } inkLayer.first->unlock(); paintLayer.first->unlock(); cmIn->unlock(); rasOut->unlock(); // Destroy the auxiliary bitmaps selectionRaster.destroy(); }
uint8_t ADMVideoTelecide::getFrameNumberNoAlloc(uint32_t frame, uint32_t *len, uint8_t *data, uint32_t *flags) { uint32_t uvlen; uint32_t dummylen; uint8_t motion; uint32_t cmatch,nmatch,n2match; assert(frame<_info.nb_frames); assert(_uncompressed); uvlen= _info.width*_info.height; *len=uvlen+(uvlen>>1); if(_instock!=frame) { // read uncompressed frame if(!_in->getFrameNumberNoAlloc(frame, &dummylen,_uncompressed,flags)) return 0; } else { memcpy(_uncompressed,_next,*len); } // for u & v , no action -> copy it as is memcpy(data,_uncompressed,(uvlen*3)>>1); if(frame==_info.nb_frames-1) return 1; // No interleaving detected if(!(motion=hasMotion()) ) { printf("\n Not interlaced !\n"); return 1; // over ! } cmatch=getMatch(); /* ------------------------------------------------------------------------------------ Try to complete with next frame fields ------------------------------------------------------------------------------------ */ if(!_in->getFrameNumberNoAlloc(frame+1, &dummylen,_next,flags)) return 0; _instock=frame+1; interleave(_next,0); nmatch=getMatch(); memcpy(_uncompressed,data,_info.width*_info.height); interleave(_next,1); n2match=getMatch(); printf(" Cur : %lu \n",cmatch); printf(" Next : %lu \n",nmatch); printf(" NextP: %lu \n",n2match); if((cmatch<nmatch)&&(cmatch<n2match)) { printf("\n __ pure interlaced __\n"); memcpy(_uncompressed,data,_info.width*_info.height); hasMotion(); doBlend(data); return 1; } if( nmatch > n2match) { printf("\n -------Shifted-P is better \n"); if(hasMotion()) { doBlend(data); printf(" but there is still motion \n"); } } else { printf("\n -------Shifted-O is better \n"); memcpy(_uncompressed,data,_info.width*_info.height); interleave(_next,0); if(hasMotion()) { doBlend(data); printf(" but there is still motion \n"); } } // which chroma is better ? from current or from next ? // search for a transition and see if there is also one ? return 1; }