Accept transparency channel

This commit is contained in:
augustin64 2025-04-01 11:38:18 +02:00
parent 28a71c5dd2
commit 964d597bdd

View File

@ -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);