debugging the use of layer list

This commit is contained in:
Jacob Gustafson 2016-08-20 19:03:33 -04:00
parent 3ce47f85ce
commit 78cdb55af8
4 changed files with 62 additions and 39 deletions

View File

@ -15,6 +15,7 @@ Possibly, rotoscoping applications are not considered commercially viable since
## Known Issues ## Known Issues
* complete first working version * complete first working version
* audit & test getLayerImagePathMostRecent
## Planned Features ## Planned Features
* use alpha.png for reducing opacity of parts of background layer * use alpha.png for reducing opacity of parts of background layer
@ -26,7 +27,9 @@ Possibly, rotoscoping applications are not considered commercially viable since
## Developer Notes ## Developer Notes
The RotoCanvas class is modular, with hopes that it can be used by various video editing applications in the future. The recommended use of RotoCanvas in a video editing application is for applying effects (primarily manual rotoscoping) to source videos (as frame sequences) as a preprocessing step before they are trimmed or other effects are added, since rotoscoping is highly dependent on the source frame (base layer) remaining the same. Using the RotoCanvas as a post-processing effect is possible, but accurate frame seeking must be assured somehow (such as by a frame-accurate video editing engine), and further edits to the previous layers will in some cases cause the rotoscoped parts (parts of the image edited by RotoCanvas) to no longer make sense (such as, if a lens pinch effect is added to a scene where there was a layer order error that has been rotoscoped out, instead of the error being rotoscoped out, there will be both the error and a corrected blotch that is the error's original position & shape), which in such cases would require redoing the rotoscoping. * The RotoCanvas class is modular, with hopes that it can be used by various video editing applications in the future. The recommended use of RotoCanvas in a video editing application is for applying effects (primarily manual rotoscoping) to source videos (as frame sequences) as a preprocessing step before they are trimmed or other effects are added, since rotoscoping is highly dependent on the source frame (base layer) remaining the same. Using the RotoCanvas as a post-processing effect is possible, but accurate frame seeking must be assured somehow (such as by a frame-accurate video editing engine), and further edits to the previous layers will in some cases cause the rotoscoped parts (parts of the image edited by RotoCanvas) to no longer make sense (such as, if a lens pinch effect is added to a scene where there was a layer order error that has been rotoscoped out, instead of the error being rotoscoped out, there will be both the error and a corrected blotch that is the error's original position & shape), which in such cases would require redoing the rotoscoping.
### RotoCanvas Paint Notes
* The save method is used by both the Save and the Save As actions. The save sender is pre-programmed with the format property
### Storage Method ### Storage Method
Folder and file structure is as follows, where `<sequenceName>` is sequence name (such as, if mygreatvideo0000.png is first frame, `<sequenceName>` is mygreatvideo) and where the base folder (containing `<sequenceName>` folder) is the folder where the images in an image sequence are stored: Folder and file structure is as follows, where `<sequenceName>` is sequence name (such as, if mygreatvideo0000.png is first frame, `<sequenceName>` is mygreatvideo) and where the base folder (containing `<sequenceName>` folder) is the folder where the images in an image sequence are stored:

BIN
images/tools.xcf Normal file

Binary file not shown.

View File

@ -52,7 +52,7 @@ void MainWindow::askOpen()
{ {
if (maybeSave()) { if (maybeSave()) {
qInfo()<<"maybeSave ok so askOpen continues..."; qInfo()<<"maybeSave ok so askOpen continues...";
QString defaultPaths=QDir::currentPath(); QString defaultPath=QDir::currentPath();
//QString tryPath="C:\\Users\\Owner\\Videos\\NTWAOG (Music Video)\\Media\\Sequence 00092 hovering\\00092a"; //QString tryPath="C:\\Users\\Owner\\Videos\\NTWAOG (Music Video)\\Media\\Sequence 00092 hovering\\00092a";
QString tryPath="C:\\Users\\Owner\\Videos\\ImageSequenceExamples"; QString tryPath="C:\\Users\\Owner\\Videos\\ImageSequenceExamples";
QDir tryDir=QDir(tryPath); QDir tryDir=QDir(tryPath);
@ -110,7 +110,7 @@ void MainWindow::askBrushRadius()
double new_value = QInputDialog::getDouble(this, tr("RotoCanvas Paint"), double new_value = QInputDialog::getDouble(this, tr("RotoCanvas Paint"),
tr("Select brush radius:"), tr("Select brush radius:"),
rotocanvas->getBrushRadius(), rotocanvas->getBrushRadius(),
0.0, 1.0, 2, &ok); 0.0, 1000.0, 2, &ok);
if (ok) if (ok)
rotocanvas->setBrushRadius(new_value); rotocanvas->setBrushRadius(new_value);
} }
@ -149,7 +149,7 @@ void MainWindow::createActions()
openAct->setShortcuts(QKeySequence::Open); openAct->setShortcuts(QKeySequence::Open);
connect(openAct, SIGNAL(triggered()), this, SLOT(askOpen())); connect(openAct, SIGNAL(triggered()), this, SLOT(askOpen()));
saveFrameAct = new QAction(tr("&Save..."), this); saveFrameAct = new QAction(tr("&Save"), this);
saveFrameAct->setShortcut(QKeySequence::Save); saveFrameAct->setShortcut(QKeySequence::Save);
connect(saveFrameAct, SIGNAL(triggered()), this, SLOT(askSave())); connect(saveFrameAct, SIGNAL(triggered()), this, SLOT(askSave()));

View File

@ -615,63 +615,83 @@ void RotoCanvas::drawLineTo(const QPoint &endPoint)
{ {
if (outputSize.width()>0&&outputSize.height()>0) { if (outputSize.width()>0&&outputSize.height()>0) {
if (selectedLayerIndex>=0) { if (selectedLayerIndex>=0) {
//qInfo()<<"Draw line on layer "<<selectedLayerIndex<<"...";
QString layersPath=getLayersFolderPath(getSeqFrameNumber(),true); QString layersPath=getLayersFolderPath(getSeqFrameNumber(),true);
QDir layersDir=QDir(layersPath); QDir layersDir=QDir(layersPath);
int thisLayerNumber=selectedLayerIndex; int thisLayerNumber=selectedLayerIndex;
QString thisLayerPath=layersDir.filePath(QString::number(thisLayerNumber)+"."+RotoCanvas::getSeqFormatString(*this->loadedFI)); QString thisLayerPath=layersDir.filePath(QString::number(thisLayerNumber)+"."+RotoCanvas::getSeqFormatString(*this->loadedFI));
QFileInfo thisLayerFI=QFileInfo(thisLayerPath); QFileInfo thisLayerFI=QFileInfo(thisLayerPath);
//qInfo()<<"Layer list length is "<<layerPtrs.length();
while (layerPtrs.length()<selectedLayerIndex+1) { while (this->layerPtrs.length()<selectedLayerIndex+1) {
layerPtrs.append((RotoCanvasLayer*)nullptr);
//qInfo()<<"Had to add blank layer (now list length is "<<layerPtrs.length()<<")";
}
if (this->layerPtrs[selectedLayerIndex]==nullptr) {
RotoCanvasLayer* newLayer; RotoCanvasLayer* newLayer;
newLayer = new RotoCanvasLayer; newLayer = new RotoCanvasLayer;
newLayer->frameNumber=getSeqFrameNumber(); newLayer->frameNumber=getSeqFrameNumber();
newLayer->image=QImage(outputSize, QImage::Format_ARGB32); newLayer->image=QImage(outputSize, QImage::Format_ARGB32);
layerPtrs.append(newLayer); this->layerPtrs[selectedLayerIndex]=newLayer; // layerPtrs.append(newLayer);
} }
QPainter painter(&panelImage); //qInfo()<<"this->layerPtrs[selectedLayerIndex]: "<<((this->layerPtrs[selectedLayerIndex]!=nullptr)?"<non-null>":"nullptr");
int rad = (brushRadius) + 2; if (this->layerPtrs[selectedLayerIndex]!=nullptr) {
QRect rectBrush = QRect(lastPoint, endPoint).normalized() //qInfo()<<"this->layerPtrs[selectedLayerIndex].image.isNull(): "<<((this->layerPtrs[selectedLayerIndex]->image.isNull())?"Null":"non-Null");
.adjusted(-rad, -rad, +rad, +rad); QPainter painter(&this->layerPtrs[selectedLayerIndex]->image);
//QPen pen; //QPainter painter(&panelImage);
//pen.setStyle(Qt::SolidLine); int rad = (brushRadius) + 2;
//pen.setWidth(1); QRect rectBrush = QRect(lastPoint, endPoint).normalized()
//pen.setColor(brushColor); .adjusted(-rad, -rad, +rad, +rad);
painter.setPen(brushColor); //QPen pen;
QColor thisColor; //pen.setStyle(Qt::SolidLine);
//pen.setWidth(1);
//pen.setColor(brushColor);
QColor thisColor;
QPoint thisPoint; QPoint thisPoint;
brushColor.setAlpha(this->brushOpacity); //qInfo()<<"this->brushOpacity: "<<this->brushOpacity;
for (int y=rectBrush.top(); y<rectBrush.bottom(); y++) { //painter.setPen(brushColor);
for (int x=rectBrush.left(); x<rectBrush.right(); x++) { //brushColor.setAlpha(this->brushOpacity); // sets to GRAY
//todo: distance from line instead of points if (this->brushOpacity<0.0) this->brushOpacity=0.0;
if (x>=0 && y>=0) { else if (this->brushOpacity>255.0) this->brushOpacity=255.0;
//thisPoint.setX(x); int opacity_int = (int)(this->brushOpacity*255.0+.5); //+.5 for rounding
//thisPoint.setY(y); brushColor = QColor(brushColor.red(),brushColor.green(),brushColor.blue(),opacity_int);
double this_distance = sqrt(pow(endPoint.x()-x, 2) + pow(endPoint.y()-y, 2)); //qInfo()<<"brushColor r,g,b,a: "<< brushColor.red()<<","<<brushColor.green()<<","<<brushColor.blue()<<","<<brushColor.alpha();
double fade_length = brushRadius-brushHardRadius; for (int y=rectBrush.top(); y<rectBrush.bottom(); y++) {
double this_opacity = (fade_length>0.0) ? ((brushRadius-this_distance) / fade_length) : ((brushRadius-this_distance) / 0.000001) ; for (int x=rectBrush.left(); x<rectBrush.right(); x++) {
if (this_opacity>1.0) this_opacity=1.0; //todo: distance from line instead of points
else if (this_opacity<0.0) this_opacity=0.0; if (x>=0 && y>=0) {
if (selectedLayerIndex>=0&&layerPtrs[selectedLayerIndex]!=nullptr) { //thisPoint.setX(x);
RotoCanvas::drawAlphaPix(&panelImage, x, y, this->brushColor, this_opacity); //thisPoint.setY(y);
RotoCanvas::drawAlphaPix(&layerPtrs[selectedLayerIndex]->image, x, y, this->brushColor, this_opacity); double this_distance = sqrt(pow(endPoint.x()-x, 2) + pow(endPoint.y()-y, 2));
layerPtrs[selectedLayerIndex]->isModified=true; double fade_length = brushRadius-brushHardRadius;
double this_opacity = (fade_length>0.0) ? ((brushRadius-this_distance) / fade_length) : ((brushRadius-this_distance) / 0.000001) ;
if (this_opacity>1.0) this_opacity=1.0;
else if (this_opacity<0.0) this_opacity=0.0;
if (selectedLayerIndex>=0&&layerPtrs[selectedLayerIndex]!=nullptr) {
RotoCanvas::drawAlphaPix(&panelImage, x, y, this->brushColor, this_opacity);
RotoCanvas::drawAlphaPix(&layerPtrs[selectedLayerIndex]->image, x, y, this->brushColor, this_opacity);
layerPtrs[selectedLayerIndex]->isModified=true;
}
} }
} }
} }
//isModified = true;
update(rectBrush);
lastPoint = endPoint;
}
else {
qInfo()<<"image "<<selectedLayerIndex<<" on layer list is null";
} }
//isModified = true;
update(rectBrush);
lastPoint = endPoint;
} }
//else no layer is selected else qInfo()<<"no layer is selected";
} }
//else a dimension is 0--no video loaded else qInfo()<<"a dimension is 0--no video loaded";
} }
void RotoCanvas::fillCheckered(QImage *thisImage) void RotoCanvas::fillCheckered(QImage *thisImage)
{ {
int checkerPxCount=((thisImage->width()>thisImage->height())?thisImage->width():thisImage->height()) / 200; int checkerPxCount=((thisImage->width()>thisImage->height())?thisImage->width():thisImage->height()) / 200;
if (checkerPxCount<8) checkerPxCount=8;
if (thisImage!=nullptr) { if (thisImage!=nullptr) {
//QSize newSize=thisImage->size(); //QSize newSize=thisImage->size();
thisImage->fill(this->checkerDarkColor); //newImage.fill(qRgb(255, 255, 255)); thisImage->fill(this->checkerDarkColor); //newImage.fill(qRgb(255, 255, 255));