diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index 6442a3091..74602f319 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -11,7 +11,7 @@ set (RTENGINESOURCEFILES colortemp.cc curves.cc dcraw.cc iccstore.cc dfmanager.c image8.cc image16.cc imagedata.cc imageio.cc improcfun.cc init.cc dcrop.cc loadinitial.cc procparams.cc rawimagesource.cc shmap.cc simpleprocess.cc refreshmap.cc stdimagesource.cc myfile.cc iccjpeg.c hlmultipliers.cc improccoordinator.cc - processingjob.cc rtthumbnail.cc utils.cc labimage.cc + processingjob.cc rtthumbnail.cc utils.cc labimage.cc slicer.cc iplab2rgb.cc ipsharpen.cc iptransform.cc ipresize.cc wavelet_dec.cc ipequalizer.cc) diff --git a/rtengine/slicer.cc b/rtengine/slicer.cc new file mode 100644 index 000000000..a53e0fc11 --- /dev/null +++ b/rtengine/slicer.cc @@ -0,0 +1,171 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2010 Gabor Horvath + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ + +#include +#include +#include + +using namespace rtengine; + +// If no parameter set, everything = 0 -> process all the image +Block::Block() { + posX = 0; + posY = 0; + width = 0; + height = 0; +} + +Block::Block(unsigned int x, unsigned int y, unsigned int w, unsigned int h) { + posX = x; + posY = y; + width = w; + height = h; +} + +/* + * Slice a sub-region to process in blocks who's size is given by the number of processor + * and the number of pixel per block (and hence the memory footprint) + */ +Slicer::Slicer(unsigned int imageWidth, unsigned int imageHeight, Block *subRegion, unsigned int pixels, const char* nomFichier) { + maxPixelNumberR = 0; + // If the sub-region has a portrait shape, X and Y coordinates are swapped for better result + // It will be swapped back when sending back the block coordinates + region.width = !(subRegion->width) ? imageWidth : subRegion->width; + region.height = !(subRegion->height) ? imageHeight : subRegion->height; // Assuming that the sub-region is under posY + if (region.width < region.height) { + region.width = !(subRegion->height) ? imageHeight : subRegion->height; + region.height = !(subRegion->width) ? imageWidth : subRegion->width; // Assuming that the sub-region is under posY + portrait = true; + imWidth = imageHeight; + imHeight = imageWidth; + region.posX = subRegion->posY; + region.posY = subRegion->posX; + } + else { + portrait = false; + imWidth = imageWidth; + imHeight = imageHeight; + region.posX = subRegion->posX; + region.posY = subRegion->posY; + } + double subRegionRatio = (double)(region.width) / (double)(region.height); + + //total number of core/processor +#ifdef _OPENMP + procNumber = omp_get_num_procs(); +#else + procNumber = 1; +#endif + + //calculate the number of block + blockNumber = (double(region.width*region.height) / (double)pixels); + blockNumber = int((MAX(blockNumber, 1) + (double)procNumber/2.)/procNumber)*procNumber; + vBlockNumber = (unsigned int)(sqrt((double)blockNumber / subRegionRatio)+0.5); + vBlockNumber = CLAMP(vBlockNumber, 1, blockNumber); + hBlockNumber = (double)blockNumber / (double)vBlockNumber; + blockWidth = 1.0 / hBlockNumber; + blockHeight = 1.0 / (double)vBlockNumber; + + double maxPixelNumberX = (double)region.height / (double)vBlockNumber; + double maxPixelNumberY = (double)region.width / (double)((unsigned int)hBlockNumber); + if (maxPixelNumberX - (double)((unsigned int)maxPixelNumberX) != 0) maxPixelNumberX += 1.; + if (maxPixelNumberY - (double)((unsigned int)maxPixelNumberY) != 0) maxPixelNumberY += 1.; + maxPixelNumber = (unsigned int)maxPixelNumberX * (unsigned int)maxPixelNumberY; + + printf ("\n*****************\nimageWidth : %d\nimageHeight : %d\nregion.width : %d\nregion.height : %d\npixels : %d\n\n", imageWidth, imageHeight, region.width, region.height, pixels); + printf ("subRegionRatio=%.5f\nPortrait = %d\n", (float)subRegionRatio, portrait); + printf ("Total block number : %d\nHorizontal block number : %.3f\nVertical block number : %d\nmaxPixelNumber : %d\n", blockNumber, hBlockNumber, vBlockNumber, maxPixelNumber); + fichierSortie = fopen(nomFichier, "wt"); + fprintf(fichierSortie,"\n"); + fprintf(fichierSortie,"\n", (portrait?imageHeight:imageWidth), (portrait?imageWidth:imageHeight)); + + fprintf(fichierSortie,"\n"); + +} + +Slicer::~Slicer() { + printf("maxPixelNumberR = %d (block #%d)\n", maxPixelNumberR, maxPixBlockNumber); + fprintf(fichierSortie,"\n"); + fclose(fichierSortie); +} + +// return the absolute position and size of the requested block +void Slicer::get_block(unsigned int numBlock, Block *block) { + volatile double roundingTradeOff = (hBlockNumber - (double)((int)hBlockNumber)) == 0.5 ? 2.1 : 2.0; + volatile unsigned int nbrLigneDejaComplete = (unsigned int)((double)(numBlock) * blockWidth + (blockWidth/roundingTradeOff)); + + volatile unsigned int prevLigneFin = (unsigned int)((double)nbrLigneDejaComplete * hBlockNumber + 0.5); + volatile unsigned int maLigneFin = (unsigned int)((double)(nbrLigneDejaComplete+1) * hBlockNumber + 0.5); + + volatile unsigned int nbCelluleSurMaLigne = maLigneFin - prevLigneFin; + volatile unsigned int celluleSurMaLigne = numBlock - prevLigneFin; + + volatile unsigned int blockStart = (unsigned int)(((double)region.width / (double)nbCelluleSurMaLigne)*(double)(celluleSurMaLigne)); + volatile unsigned int blockEnd = (unsigned int)(((double)region.width / (double)nbCelluleSurMaLigne)*(double)(celluleSurMaLigne+1)); + block->width = blockEnd - blockStart; + block->posX = region.posX + blockStart; + if (celluleSurMaLigne == (nbCelluleSurMaLigne-1)) { + // We make sure that the last block of the row take the rest of the remaining X space + block->width = region.posX + region.width - block->posX; + } + + blockStart = (unsigned int)(((double)region.height / (double)vBlockNumber)*(double)(nbrLigneDejaComplete)); + blockEnd = (unsigned int)(((double)region.height / (double)vBlockNumber)*(double)(nbrLigneDejaComplete+1)); + block->height = blockEnd - blockStart; + block->posY = region.posY + blockStart; + if (nbrLigneDejaComplete == (vBlockNumber-1)) { + block->height = region.posY + region.height - block->posY; + } + + if (portrait) { + // we swap back the X/Y coordinates + unsigned int temp; + + temp = block->posX; + block->posX = block->posY; + block->posY = temp; + + temp = block->width; + block->width = block->height; + block->height = temp; + + } + unsigned int currBlockSize = block->width * block->height; + if (currBlockSize > maxPixelNumberR) { + maxPixelNumberR = currBlockSize; + maxPixBlockNumber = numBlock+1; + } + + char *couleur[4] = {"70d26e", "3ba6c3", "d0d26e", "3b62c3"}; + char *coul = couleur[(nbrLigneDejaComplete%2)*2 + celluleSurMaLigne%2]; + fprintf(fichierSortie,"width-2), (block->height-2), (block->posX+1), (block->posY+1)); + fprintf(fichierSortie," id='rect%d' style='opacity:0.3;fill:#%s;fill-opacity:1;fill-rule:evenodd;stroke:#%s;stroke-width:2;stroke-linecap:square;", numBlock, coul, coul); + fprintf(fichierSortie,"stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1' />\n", numBlock); + fprintf(fichierSortie,"posX + block->width/2), (block->posY + block->height/2)); + fprintf(fichierSortie," id='text%d' xml:space='preserve' style='font-size:15px;font-style:normal;", numBlock); + fprintf(fichierSortie,"font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;text-anchor:start;fill:#000000;"); + fprintf(fichierSortie,"fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;"); + fprintf(fichierSortie,"font-family:Arial;-inkscape-font-specification:Arial'>\n"); + fprintf(fichierSortie,"posX + block->width/2), (block->posY + block->height/2)); + fprintf(fichierSortie," id='tspan%d'>%d\n\n", numBlock, (numBlock+1)); +} diff --git a/rtengine/slicer.h b/rtengine/slicer.h new file mode 100644 index 000000000..4a76cc55e --- /dev/null +++ b/rtengine/slicer.h @@ -0,0 +1,76 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2010 Gabor Horvath + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#ifndef _SLICER_ +#define _SLICER_ + +//The image is divided in blocks even on single processor machine, mainly to decrease memory consumption +//maximum number of pixel per block +#define PIXELS_PER_BLOCK 1000000 + +// DEBUG! +#include +#include +//#include + + +namespace rtengine { + +class Block { + public: + unsigned int posX; + unsigned int posY; + unsigned int width; // If 0, use the full width of the image + unsigned int height; // If 0, use the full height of the image + Block(); + Block(unsigned int x, unsigned int y, unsigned int w, unsigned int h); +}; + +/* + * This class handle the best slicing of the image with a given number of pixels per block and the number of + * processor, and tries to create block as square as possible. There can be a different number of block on + * each line. + */ +class Slicer { + protected: + bool portrait; // Orientation of the sub-region + unsigned int procNumber; // Number of processor + unsigned int imWidth; // Image width + unsigned int imHeight; // Image height + Block region; // Sub-region to process + double hBlockNumber; // Horizontal number of block for the sub-region + unsigned int vBlockNumber; // Vertical number of block for the sub-region + double blockWidth; + double blockHeight; + // DEBUG below + unsigned int maxPixelNumberR; + int maxPixBlockNumber; + FILE *fichierSortie; + + public: + unsigned int blockNumber; // number of block for the sub-region + unsigned int maxPixelNumber; // number of pixel of the biggest block (for memory allocation purpose) + Slicer(unsigned int imageWidth, unsigned int imageHeight, Block *subRegion, unsigned int pixels, const char* nomFichier); + ~Slicer(void); + void get_block(unsigned int blockId, Block *block); + void drawRectSVG(unsigned int numBlock, Block *block); +}; + +}; + +#endif