Accept transparency channel
This commit is contained in:
parent
28a71c5dd2
commit
964d597bdd
@ -39,6 +39,7 @@ void export_image(const char* filename, const void* data, int width, int height,
|
|||||||
|
|
||||||
/** e_1 energy, energy is always normalized between 0 and 1 */
|
/** e_1 energy, energy is always normalized between 0 and 1 */
|
||||||
std::vector<float> energy_e1(std::vector<unsigned char> source, int width, int height, int nbChannels) {
|
std::vector<float> energy_e1(std::vector<unsigned char> source, int width, int height, int nbChannels) {
|
||||||
|
int nbColorChannels = nbChannels > 3 ? 3 : nbChannels; // nombre de canaux, excepté le alpha
|
||||||
std::vector<float> energy(width*height);
|
std::vector<float> energy(width*height);
|
||||||
|
|
||||||
float max_energy = 0;
|
float max_energy = 0;
|
||||||
@ -51,7 +52,7 @@ std::vector<float> energy_e1(std::vector<unsigned char> source, int width, int h
|
|||||||
auto indexPixel_right = (i+1 < width) ? nbChannels*(width*j+(i+1)) : indexPixel;
|
auto indexPixel_right = (i+1 < width) ? nbChannels*(width*j+(i+1)) : indexPixel;
|
||||||
|
|
||||||
energy[width*j+i] = 0;
|
energy[width*j+i] = 0;
|
||||||
for (auto ch=0; ch < nbChannels; ch++) {
|
for (auto ch=0; ch < nbColorChannels; ch++) { // Le alpha n'est pas pris en compte dans l'énergie
|
||||||
energy[width*j+i] += (
|
energy[width*j+i] += (
|
||||||
fabs((float)source[indexPixel_up+ch] - source[indexPixel+ch])
|
fabs((float)source[indexPixel_up+ch] - source[indexPixel+ch])
|
||||||
+fabs((float)source[indexPixel_down+ch] - source[indexPixel+ch])
|
+fabs((float)source[indexPixel_down+ch] - source[indexPixel+ch])
|
||||||
@ -160,12 +161,11 @@ std::vector<int> carving_step(const std::vector<unsigned char> source, std::vect
|
|||||||
int cur_j = 0;
|
int cur_j = 0;
|
||||||
for (auto j=0; cur_j < dim_large-1 && j < dim_large; j++) {
|
for (auto j=0; cur_j < dim_large-1 && j < dim_large; j++) {
|
||||||
if (!blacklist[im_index(i, j)]) {
|
if (!blacklist[im_index(i, j)]) {
|
||||||
int out_pixelIndex = 3*(vertical ? ((width-1)*i + cur_j) : (width*cur_j + i));
|
int out_pixelIndex = nbChannels*(vertical ? ((width-1)*i + cur_j) : (width*cur_j + i));
|
||||||
int src_pixelIndex = 3*im_index(i, j);
|
int src_pixelIndex = nbChannels*im_index(i, j);
|
||||||
|
|
||||||
output[ out_pixelIndex ] = source[ src_pixelIndex ];
|
for (auto ch=0; ch < nbChannels; ch++)
|
||||||
output[out_pixelIndex+1] = source[src_pixelIndex+1];
|
output[out_pixelIndex+ch] = source[src_pixelIndex+ch];
|
||||||
output[out_pixelIndex+2] = source[src_pixelIndex+2];
|
|
||||||
cur_j++;
|
cur_j++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -175,17 +175,18 @@ std::vector<int> carving_step(const std::vector<unsigned char> source, std::vect
|
|||||||
|
|
||||||
|
|
||||||
void seam_carving(unsigned char* source, int width, int height, int nbChannels, const char* out_filename, int nbSeams, bool vertical, bool test_energy=false) {
|
void seam_carving(unsigned char* source, int width, int height, int nbChannels, const char* out_filename, int nbSeams, bool vertical, bool test_energy=false) {
|
||||||
|
int nbColorChannels = nbChannels > 3 ? 3 : nbChannels;
|
||||||
int curWidth = width;
|
int curWidth = width;
|
||||||
int curHeight = height;
|
int curHeight = height;
|
||||||
|
|
||||||
int dim_large = vertical ? width : height;
|
int dim_large = vertical ? width : height;
|
||||||
int dim_long = vertical ? height : width;
|
int dim_long = vertical ? height : width;
|
||||||
|
|
||||||
std::vector<unsigned char> carve_output(width*height*3); // Receives at each step the newly carved image
|
std::vector<unsigned char> carve_output(width*height*nbChannels); // Receives at each step the newly carved image
|
||||||
std::vector<unsigned char> source_img(width*height*nbChannels); // Contains at each step the carved image
|
std::vector<unsigned char> source_img(width*height*nbChannels); // Contains at each step the carved image
|
||||||
std::vector<bool> complete_blacklist(width*height); // Contains all removed pixels, for "test_energy"
|
std::vector<bool> complete_blacklist(width*height); // Contains all removed pixels, for "test_energy"
|
||||||
std::vector<float> ini_energy; // Contains the initial energy, only for "test_energy"
|
std::vector<float> ini_energy; // Contains the initial energy, only for "test_energy"
|
||||||
std::vector<unsigned char> test_energy_output(width*height*3); // Final output for "test_energy"
|
std::vector<unsigned char> test_energy_output(width*height*nbChannels); // Final output for "test_energy"
|
||||||
|
|
||||||
|
|
||||||
for (auto i=0; i < width*height*nbChannels; i++) { source_img[i] = source[i]; }
|
for (auto i=0; i < width*height*nbChannels; i++) { source_img[i] = source[i]; }
|
||||||
@ -196,12 +197,13 @@ void seam_carving(unsigned char* source, int width, int height, int nbChannels,
|
|||||||
|
|
||||||
//* Prepare final output
|
//* Prepare final output
|
||||||
for (auto k=0; k < width*height; k++) {
|
for (auto k=0; k < width*height; k++) {
|
||||||
//output[3*k] = source_img[3*k]/3; //* Uncomment if you prefer to see darkened source image
|
//for (auto i=0; i < nbColorChannels; i++) //* Uncomment if you prefer to see darkened source image
|
||||||
//output[3*k+1] = source_img[3*k+1]/3;
|
// output[nbChannels*k+i] = source_img[nbChannels*k+i]/nbChannels;
|
||||||
//output[3*k+2] = source_img[3*k+2]/3;
|
for (auto i=0; i < nbColorChannels; i++)
|
||||||
test_energy_output[3*k] = ini_energy[k]*255;
|
test_energy_output[nbChannels*k+i] = ini_energy[k]*255;
|
||||||
test_energy_output[3*k+1] = ini_energy[k]*255;
|
|
||||||
test_energy_output[3*k+2] = ini_energy[k]*255;
|
if (nbChannels==4)
|
||||||
|
test_energy_output[nbChannels*k+3] = source_img[nbChannels*k+3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,7 +226,7 @@ void seam_carving(unsigned char* source, int width, int height, int nbChannels,
|
|||||||
assert(cur_j == opt_seam[i]); // Else, j == width and cur_j is not in the source image..
|
assert(cur_j == opt_seam[i]); // Else, j == width and cur_j is not in the source image..
|
||||||
|
|
||||||
complete_blacklist[im_index(i, j)] = true;
|
complete_blacklist[im_index(i, j)] = true;
|
||||||
test_energy_output[3*im_index(i, j)] = 255; // Set carved pixel to red
|
test_energy_output[nbChannels*im_index(i, j)] = 255; // Set carved pixel to red
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bar.increment();
|
bar.increment();
|
||||||
@ -261,10 +263,7 @@ int main(int argc, char **argv) {
|
|||||||
unsigned char *source = stbi_load(sourceImage.c_str(), &width, &height, &nbChannels, 0);
|
unsigned char *source = stbi_load(sourceImage.c_str(), &width, &height, &nbChannels, 0);
|
||||||
nbSeams = min(nbSeams, width);
|
nbSeams = min(nbSeams, width);
|
||||||
|
|
||||||
if (nbChannels < 3) { // TODO : really ?
|
//std::cout << "channels: " << nbChannels << std::endl;
|
||||||
std::cout<< "Input images must be RGB images."<<std::endl;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
seam_carving(source, width, height, nbChannels, outputImage.c_str(), nbSeams, vertical, test_energy=test_energy);
|
seam_carving(source, width, height, nbChannels, outputImage.c_str(), nbSeams, vertical, test_energy=test_energy);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user