diff --git a/relightlab/mainwindow.cpp b/relightlab/mainwindow.cpp index 5fcc23d..9200112 100644 --- a/relightlab/mainwindow.cpp +++ b/relightlab/mainwindow.cpp @@ -139,6 +139,7 @@ void MainWindow::clear() { void MainWindow::init() { image_frame->init(); + align_frame->init(); scale_frame->init(); lights_frame->init(); crop_frame->init(); diff --git a/relightlab/normalstask.cpp b/relightlab/normalstask.cpp index db11934..b140c5c 100644 --- a/relightlab/normalstask.cpp +++ b/relightlab/normalstask.cpp @@ -59,10 +59,8 @@ void NormalsTask::initFromProject(Project &project) { imageset.initImages(project.dir.absolutePath().toStdString().c_str()); imageset.initFromDome(project.dome); assert(imageset.lights().size() == imageset.images.size()); - QRect &crop = project.crop; - if(!crop.isNull()) { - imageset.crop(crop.left(), crop.top(), crop.width(), crop.height()); - } + imageset.setCrop(project.crop, project.offsets); + pixelSize = project.pixelSize; } void NormalsTask::setParameters(NormalsParameters ¶m) { diff --git a/relightlab/roadmap.md b/relightlab/roadmap.md index 63fc1d9..992baae 100644 --- a/relightlab/roadmap.md +++ b/relightlab/roadmap.md @@ -27,7 +27,7 @@ * shadow removal * 3d lights on sphere should take into account sphere posistion/ * allow rescaling when building rti and normals - +* rotate and crop an existing rti. ## Bugs diff --git a/relightlab/rtiframe.cpp b/relightlab/rtiframe.cpp index 67ead1d..aa2eb09 100644 --- a/relightlab/rtiframe.cpp +++ b/relightlab/rtiframe.cpp @@ -116,7 +116,7 @@ void RtiFrame::exportRti() { QMessageBox::warning(this, "Destination path is missing.", "Fill in the output folder or the filename for the RTI."); return; } - RtiTask *rti_task = new RtiTask(qRelightApp->project()); + RtiTask *rti_task = new RtiTask(project); rti_task->setParameters(parameters); rti_task->output = parameters.path; rti_task->crop = project.crop; diff --git a/relightlab/rtitask.cpp b/relightlab/rtitask.cpp index 3ef5ec5..b81b37e 100644 --- a/relightlab/rtitask.cpp +++ b/relightlab/rtitask.cpp @@ -60,6 +60,7 @@ void RtiTask::run() { status = RUNNING; std::function callback = [this](QString s, int n)->bool { return this->progressed(s, n); }; + //TODO mnove all this to the constructor (except what parameters can set. builder = new RtiBuilder; builder->imageset.pixel_size = project.pixelSize; @@ -84,15 +85,16 @@ void RtiTask::run() { imageset.images = project.getImages(); imageset.pixel_size = project.pixelSize; imageset.initImages(input_folder.toStdString().c_str()); - imageset.initFromDome(project.dome); //lights after images + imageset.initFromDome(project.dome); //lights after images + imageset.setCrop(crop,project.offsets); + //TODO too many crop locations! if(!crop.isNull()) { - builder->crop[0] = crop.left(); - builder->crop[1] = crop.top(); - builder->crop[2] = crop.width(); - builder->crop[3] = crop.height(); - imageset.crop(crop.left(), crop.top(), crop.width(), crop.height()); + builder->crop[0] = imageset.left; + builder->crop[1] = imageset.top; + builder->crop[2] = imageset.width; + builder->crop[3] = imageset.height; } builder->width = imageset.width; diff --git a/src/imageset.cpp b/src/imageset.cpp index 6f256ff..577656b 100644 --- a/src/imageset.cpp +++ b/src/imageset.cpp @@ -278,11 +278,12 @@ void ImageSet::readLine(PixelArray &pixels) { for(size_t i = 0; i < decoders.size(); i++) { decoders[i]->readRows(1, row.data()); + int x_offset = offsets.size() ? offsets[i].x() : 0; for(int x = left; x < right; x++) { - pixels[x - left][i].r = row[x*3 + 0]; - pixels[x - left][i].g = row[x*3 + 1]; - pixels[x - left][i].b = row[x*3 + 2]; + pixels[x - left][i].r = row[(x + x_offset)*3 + 0]; + pixels[x - left][i].g = row[(x + x_offset)*3 + 1]; + pixels[x - left][i].b = row[(x + x_offset)*3 + 2]; } } if(light3d) { @@ -387,11 +388,40 @@ void ImageSet::restart() { current_line = 0; } +void ImageSet::setCrop(QRect &_crop, std::vector &_offsets) { + std::vector int_offsets; + for(QPointF &p: _offsets) + int_offsets.push_back(p.toPoint()); + + //find min and max of offsets to adjust the maxCrop; + int l = 0; + int r = 0; + int t = image_width; + int b = image_height; + for(QPoint &o: int_offsets) { + l = std::max(l, -o.x()); + r = std::min(image_width, -o.x()); + t = std::max(b, -o.y()); + b = std::min(image_height, -o.y()); + } + //TODO check +1 problem + QRect max_crop(l, t, r -l, t - b); + if(_crop.isNull()) + _crop = max_crop; + else + _crop = max_crop.intersected(_crop); + + left =_crop.left(); + crop(_crop.left(), _crop.top(), _crop.width(), _crop.height()); + offsets = int_offsets; +} + void ImageSet::skipToTop() { std::vector row(image_width*3); for(uint32_t i = 0; i < decoders.size(); i++) { - for(int y = 0; y < top; y++) + int y_offset = offsets.size() ? offsets[i].y() : 0; + for(int y = 0; y < top + y_offset; y++) decoders[i]->readRows(1, row.data()); if(callback && !(*callback)("Skipping cropped lines...", 100*i/(decoders.size()-1))) @@ -400,3 +430,4 @@ void ImageSet::skipToTop() { current_line += top; } + diff --git a/src/imageset.h b/src/imageset.h index f97046b..3db8776 100644 --- a/src/imageset.h +++ b/src/imageset.h @@ -10,10 +10,12 @@ #include #include +#include class QJsonObject; class JpegDecoder; class QImage; +class QRect; class ImageSet { public: @@ -31,6 +33,7 @@ class ImageSet { float idealLightDistance2 = 0.0f; //squared, used when rescaling intensity int current_line = 0; + std::vector offsets; //align offsets ImageSet(const char *path = nullptr); ~ImageSet(); @@ -51,6 +54,9 @@ class ImageSet { //open images and starts the decoders bool initImages(const char *path); //path points to the dir of the images. + void setCrop(QRect &crop, std::vector &offsets); + + void setLights(std::vector &lights, Dome::LightConfiguration configuration); std::vector &lights() { return lights1; } diff --git a/src/project.cpp b/src/project.cpp index 5f32e92..4c8ebfe 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -50,6 +50,7 @@ void Project::operator=(const Project& project) { whites.push_back(new White(*w)); crop = project.crop; + offsets = project.offsets; pixelSize = project.pixelSize; name = project.name; authors = project.authors;