2
votes

I'm trying to convert a JPEG from RGB into HSL. I made a read and a write function for opening the file (I use libjpeg functions) and making an ASCII draw from this pic from its HSL values (Hue, Saturation, Luminance) so I found a pseudocode for converting RGB to HSL : http://pastebin.com/2sf1b25L and I converted it in C. My question is : now how can I do to convert each pixel one by one from RGB to HSL ? will it work if I use this RGB_to_HSL function in my "write", and I apply it to each box of the buffer array ?

main.c :

#include <stdio.h>
#include <stdlib.h>
#include <jpeglib.h>
#include "fonctions.h"


int main (int argc, char** argv){


    int H;
    int W;
    int C;
    FILE *fichier = NULL; //file pour l'image entrée
    FILE *image = NULL; //file pou l'image à la sortie
    unsigned char **buffer; //buffer où sera contenue l'image

    buffer = malloc(256*(sizeof(unsigned char*)));

    if (argv[1] == NULL)
        fichier = fopen("cara.jpg", "r");
    else
        fichier = fopen(argv[1], "r");
    image = fopen("cara_image_cree.jpg", "wb");

    if (fichier == NULL)
        printf("Probleme lecture");

    printf("Cara Delevingne\n");
    buffer = lire(fichier, &H, &W, &C);
    ecrire(&H, &W, &C, buffer, image);

    fclose(fichier);
    fclose(image);
    return 0;
}   

read.c :

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <jpeglib.h>
#include <jerror.h>

unsigned char** lire (FILE* file, int *H, int *W, int *C){

struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;

int n = 0;
unsigned char** buffer; // buffer qui va contenir l'image

/*printf("SHITSHITSHITSHITDEBUG\n");
fflush(stdout);*/
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo); // Initialisation de la structure

jpeg_stdio_src(&cinfo,file);  // file est de type FILE * (descripteur de fichier
                              // sur le fichier jpega decompresser)
jpeg_read_header(&cinfo,TRUE);// lecture des infos sur l'image jpeg


jpeg_start_decompress(&cinfo);// lancement du processus de decompression


*H = cinfo.output_height; // on récupère la hauteur
*W = cinfo.output_width; // on récupère la largeur
*C = cinfo.output_components; // on regarde si l'image est en couleurs ou N&B


buffer=malloc( (*H) *sizeof(unsigned char*) ); // on alloue de la mémoire au buffer selon le nb de lignes de pixels qu'il va devoir prendre

while (n < *H) // tant que le compteur n'a pas dépassé l'image
 {
    buffer[n] = (unsigned char*) malloc( (*W) * (*C) *sizeof(unsigned char *) ); // on alloue à chaque ligne, la taille de la largeur

     jpeg_read_scanlines(&cinfo,buffer+n,1); // lecture des n lignes suivantes de l'image
                                          // dans le buffer (de type unsigned char *)
     n++;
}

jpeg_finish_decompress(&cinfo);

jpeg_destroy_decompress(&cinfo);

return buffer;
}

write.c

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <jpeglib.h>
#include <jerror.h>

void ecrire (int *H, int *W, int *C, unsigned char **buffer, FILE *file){

struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;

int n = 0;

cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo); // Initialisation de la structure

jpeg_stdio_dest(&cinfo,file);  // file est de type FILE * (descripteur de fichier
                              // sur le fichier jpeg compressé final)
cinfo.image_width= *W;          // nombre de ligne de l'image
cinfo.image_height= *H;         // nombre de pixel par ligne
cinfo.input_components = *C;      // 3 pour une image couleur, 1 pour une N&B
cinfo.in_color_space= JCS_RGB;
                              // JCS_GRAYSCALE pour une image N&B
jpeg_set_defaults(&cinfo);    // initialisation des paramètres de compression
jpeg_start_compress(&cinfo,TRUE); // lancement du processus de decompression


while (n < *H)
{
    jpeg_write_scanlines(&cinfo,buffer+n,1); // écriture des n lignes suivantes de l'image
                                          // stockées dans le buffer (de type unsigned char *)
     n++;
}

jpeg_finish_compress(&cinfo);

jpeg_destroy_compress(&cinfo);

}

RGB_to_HSL.c (I didn't use it anywhere for now ! I don't know where I have to use it) :

void rgbToHsl(int r, int g, int b, int *h, int *s, int *l){
    r/=255; g /= 255; b/=255;
    int max = maximum(r, g, b);
    int min = minimum(r, g, b);
    *l = (max + min)/2;

    if (max == min) 
        *h = *s = 0; // achromatique
    else{
        int d = max - min;
        *s = *l > 0.5 ? d / (2 - max - min) : d / (max + min);
        if (max == r)
            *h = (g-b) / d + (g < b ? 6 : 0);
        if (max == g)
            *h = (b-r) / d + 2;
        if (max == b)
            *h = (r-g) / d + 4;

            /*case r: *h = r;
            case g: *h = g;
            case b: *h = b; */
        }
        *h /= 6;





    }

int maximum (int a, int b, int c){
    if (a > b){
        if (a > c)
            return a;
        else
            return c;
    }
    else{
        if (b > c)
            return b;
        if (c > b)
            return c;
    }
}

int minimum (int a, int b, int c){
    if (a < b){
        if (a < c)
            return a;
        else
            return c;
    }
    else{
        if (b < c)
            return b;
        if (c < b)
            return c;
    }


}

excuse-me for the comments in french it's because it is for college and my teacher wants us to comment our programms (normal)

Thank you guys for your help.

1
I am not sure, but I did something similar some years ago. Can you access the uncompressed values of the image? If yes, in theory you should be able to loop over them, and apply the conversion. For simplification you can start with a monochromatic image, and just print the content of the buffer.arc_lupus

1 Answers

1
votes

I'm not a specialist in everything, but it seems that after the decompression you have an array of scanlines in buffer with buffer[i] being the i-th scanline (zero based). The scanlines contain the individual pixels.

Because each pixel is converted independently from other pixels in your algorithm, you now just convert the pixels to HSL: loop over scanlines, loop over pixels of scanline, converting each, putting pixels back in scanline.

Once done, you can write the image back. I do not know if you need to set diferent compression options to compress HSL or compress RGB.