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 */
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);
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;
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] += (
fabs((float)source[indexPixel_up+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;
for (auto j=0; cur_j < dim_large-1 && j < dim_large; j++) {
if (!blacklist[im_index(i, j)]) {
int out_pixelIndex = 3*(vertical ? ((width-1)*i + cur_j) : (width*cur_j + i));
int src_pixelIndex = 3*im_index(i, j);
int out_pixelIndex = nbChannels*(vertical ? ((width-1)*i + cur_j) : (width*cur_j + i));
int src_pixelIndex = nbChannels*im_index(i, j);
output[ out_pixelIndex ] = source[ src_pixelIndex ];
output[out_pixelIndex+1] = source[src_pixelIndex+1];
output[out_pixelIndex+2] = source[src_pixelIndex+2];
for (auto ch=0; ch < nbChannels; ch++)
output[out_pixelIndex+ch] = source[src_pixelIndex+ch];
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) {
int nbColorChannels = nbChannels > 3 ? 3 : nbChannels;
int curWidth = width;
int curHeight = height;
int dim_large = vertical ? width : height;
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<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<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]; }
@ -196,12 +197,13 @@ void seam_carving(unsigned char* source, int width, int height, int nbChannels,
//* Prepare final output
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
//output[3*k+1] = source_img[3*k+1]/3;
//output[3*k+2] = source_img[3*k+2]/3;
test_energy_output[3*k] = ini_energy[k]*255;
test_energy_output[3*k+1] = ini_energy[k]*255;
test_energy_output[3*k+2] = ini_energy[k]*255;
//for (auto i=0; i < nbColorChannels; i++) //* Uncomment if you prefer to see darkened source image
// output[nbChannels*k+i] = source_img[nbChannels*k+i]/nbChannels;
for (auto i=0; i < nbColorChannels; i++)
test_energy_output[nbChannels*k+i] = 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..
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();
@ -261,10 +263,7 @@ int main(int argc, char **argv) {
unsigned char *source = stbi_load(sourceImage.c_str(), &width, &height, &nbChannels, 0);
nbSeams = min(nbSeams, width);
if (nbChannels < 3) { // TODO : really ?
std::cout<< "Input images must be RGB images."<<std::endl;
exit(1);
}
//std::cout << "channels: " << nbChannels << std::endl;
seam_carving(source, width, height, nbChannels, outputImage.c_str(), nbSeams, vertical, test_energy=test_energy);