debugging the use of layer list
This commit is contained in:
parent
3ce47f85ce
commit
78cdb55af8
@ -15,6 +15,7 @@ Possibly, rotoscoping applications are not considered commercially viable since
|
||||
|
||||
## Known Issues
|
||||
* complete first working version
|
||||
* audit & test getLayerImagePathMostRecent
|
||||
|
||||
## Planned Features
|
||||
* 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
|
||||
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
|
||||
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
BIN
images/tools.xcf
Normal file
Binary file not shown.
@ -52,7 +52,7 @@ void MainWindow::askOpen()
|
||||
{
|
||||
if (maybeSave()) {
|
||||
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\\ImageSequenceExamples";
|
||||
QDir tryDir=QDir(tryPath);
|
||||
@ -110,7 +110,7 @@ void MainWindow::askBrushRadius()
|
||||
double new_value = QInputDialog::getDouble(this, tr("RotoCanvas Paint"),
|
||||
tr("Select brush radius:"),
|
||||
rotocanvas->getBrushRadius(),
|
||||
0.0, 1.0, 2, &ok);
|
||||
0.0, 1000.0, 2, &ok);
|
||||
if (ok)
|
||||
rotocanvas->setBrushRadius(new_value);
|
||||
}
|
||||
@ -149,7 +149,7 @@ void MainWindow::createActions()
|
||||
openAct->setShortcuts(QKeySequence::Open);
|
||||
connect(openAct, SIGNAL(triggered()), this, SLOT(askOpen()));
|
||||
|
||||
saveFrameAct = new QAction(tr("&Save..."), this);
|
||||
saveFrameAct = new QAction(tr("&Save"), this);
|
||||
saveFrameAct->setShortcut(QKeySequence::Save);
|
||||
connect(saveFrameAct, SIGNAL(triggered()), this, SLOT(askSave()));
|
||||
|
||||
|
@ -615,63 +615,83 @@ void RotoCanvas::drawLineTo(const QPoint &endPoint)
|
||||
{
|
||||
if (outputSize.width()>0&&outputSize.height()>0) {
|
||||
if (selectedLayerIndex>=0) {
|
||||
//qInfo()<<"Draw line on layer "<<selectedLayerIndex<<"...";
|
||||
QString layersPath=getLayersFolderPath(getSeqFrameNumber(),true);
|
||||
QDir layersDir=QDir(layersPath);
|
||||
int thisLayerNumber=selectedLayerIndex;
|
||||
QString thisLayerPath=layersDir.filePath(QString::number(thisLayerNumber)+"."+RotoCanvas::getSeqFormatString(*this->loadedFI));
|
||||
QFileInfo thisLayerFI=QFileInfo(thisLayerPath);
|
||||
|
||||
while (layerPtrs.length()<selectedLayerIndex+1) {
|
||||
//qInfo()<<"Layer list length is "<<layerPtrs.length();
|
||||
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;
|
||||
newLayer = new RotoCanvasLayer;
|
||||
newLayer->frameNumber=getSeqFrameNumber();
|
||||
newLayer->image=QImage(outputSize, QImage::Format_ARGB32);
|
||||
layerPtrs.append(newLayer);
|
||||
this->layerPtrs[selectedLayerIndex]=newLayer; // layerPtrs.append(newLayer);
|
||||
}
|
||||
QPainter painter(&panelImage);
|
||||
int rad = (brushRadius) + 2;
|
||||
QRect rectBrush = QRect(lastPoint, endPoint).normalized()
|
||||
.adjusted(-rad, -rad, +rad, +rad);
|
||||
//QPen pen;
|
||||
//pen.setStyle(Qt::SolidLine);
|
||||
//pen.setWidth(1);
|
||||
//pen.setColor(brushColor);
|
||||
painter.setPen(brushColor);
|
||||
QColor thisColor;
|
||||
//qInfo()<<"this->layerPtrs[selectedLayerIndex]: "<<((this->layerPtrs[selectedLayerIndex]!=nullptr)?"<non-null>":"nullptr");
|
||||
if (this->layerPtrs[selectedLayerIndex]!=nullptr) {
|
||||
//qInfo()<<"this->layerPtrs[selectedLayerIndex].image.isNull(): "<<((this->layerPtrs[selectedLayerIndex]->image.isNull())?"Null":"non-Null");
|
||||
QPainter painter(&this->layerPtrs[selectedLayerIndex]->image);
|
||||
//QPainter painter(&panelImage);
|
||||
int rad = (brushRadius) + 2;
|
||||
QRect rectBrush = QRect(lastPoint, endPoint).normalized()
|
||||
.adjusted(-rad, -rad, +rad, +rad);
|
||||
//QPen pen;
|
||||
//pen.setStyle(Qt::SolidLine);
|
||||
//pen.setWidth(1);
|
||||
//pen.setColor(brushColor);
|
||||
QColor thisColor;
|
||||
|
||||
QPoint thisPoint;
|
||||
brushColor.setAlpha(this->brushOpacity);
|
||||
for (int y=rectBrush.top(); y<rectBrush.bottom(); y++) {
|
||||
for (int x=rectBrush.left(); x<rectBrush.right(); x++) {
|
||||
//todo: distance from line instead of points
|
||||
if (x>=0 && y>=0) {
|
||||
//thisPoint.setX(x);
|
||||
//thisPoint.setY(y);
|
||||
double this_distance = sqrt(pow(endPoint.x()-x, 2) + pow(endPoint.y()-y, 2));
|
||||
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;
|
||||
QPoint thisPoint;
|
||||
//qInfo()<<"this->brushOpacity: "<<this->brushOpacity;
|
||||
//painter.setPen(brushColor);
|
||||
//brushColor.setAlpha(this->brushOpacity); // sets to GRAY
|
||||
if (this->brushOpacity<0.0) this->brushOpacity=0.0;
|
||||
else if (this->brushOpacity>255.0) this->brushOpacity=255.0;
|
||||
int opacity_int = (int)(this->brushOpacity*255.0+.5); //+.5 for rounding
|
||||
brushColor = QColor(brushColor.red(),brushColor.green(),brushColor.blue(),opacity_int);
|
||||
//qInfo()<<"brushColor r,g,b,a: "<< brushColor.red()<<","<<brushColor.green()<<","<<brushColor.blue()<<","<<brushColor.alpha();
|
||||
for (int y=rectBrush.top(); y<rectBrush.bottom(); y++) {
|
||||
for (int x=rectBrush.left(); x<rectBrush.right(); x++) {
|
||||
//todo: distance from line instead of points
|
||||
if (x>=0 && y>=0) {
|
||||
//thisPoint.setX(x);
|
||||
//thisPoint.setY(y);
|
||||
double this_distance = sqrt(pow(endPoint.x()-x, 2) + pow(endPoint.y()-y, 2));
|
||||
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)
|
||||
{
|
||||
int checkerPxCount=((thisImage->width()>thisImage->height())?thisImage->width():thisImage->height()) / 200;
|
||||
if (checkerPxCount<8) checkerPxCount=8;
|
||||
if (thisImage!=nullptr) {
|
||||
//QSize newSize=thisImage->size();
|
||||
thisImage->fill(this->checkerDarkColor); //newImage.fill(qRgb(255, 255, 255));
|
||||
|
Loading…
x
Reference in New Issue
Block a user