Rewriting JPEG images from RGB to HSL : how can i optimize this? - c

i'm on a project where i have to make a program that will draw an ASCII from a JPEG.
The program will chose a char according to the HSL value of a pixel : Hue, Saturation, Lightness
So, as a JPEG file is in RGB, i convert it into HSL.
But i find my program pretty slow and it slows my whole virtual machine lel
Do you know how i could improve it for making it a little bit faster ?
it's in my write i call the function that converts RGB into HSL
here it is :
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);
/* afficher 3 sous-pixels :
printf("\nBuffer case 1 : %d", buffer[0][0]);
printf("\nBuffer case 1 : %d", buffer[0][0+1]);
printf("\nBuffer case 1 : %d\n", buffer[0][0+2]);*/
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;
float** bufferHSL;
int n = 0; // parcoureurs pour écrire l'image
int i = 0; // parcoureurs pour transformer en HSL
int j = 0;
float h = 0; // variables pour stocker le résultat HSL
float s = 0;
float l = 0;
int r, g, b;
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
bufferHSL = (float **) malloc( (*H) *sizeof(long int*) );
while (i < *H){ // lecture des lignes pour transformation HSL
j = 0;
while (j < *W){
/*printf("i : %d /t j : %d \n",i , j);
fflush(stdout);*/
bufferHSL[i] = (float*)malloc( (*W) *sizeof(long int*) );
r = buffer[i][j];
g = buffer[i][j+1];
b = buffer[i][j+2];
rgbToHsl(r, g, b, &h, &s, &l);
bufferHSL[i][j] = h;
bufferHSL[i][j+1] = s;
bufferHSL[i][j+2] = l;
j++;
/*printf("TESTTEST\n");
fflush(stdout);*/
}
i++;
}
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 :
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;
}
}

You should run some profiling tool to see exactly which parts take how long to execute and optimize that.
Without that, a quick look shows you are calling malloc a lot in an inner loop, here:
bufferHSL = (float **) malloc( (*H) *sizeof(long int*) );
while (i < *H){ // lecture des lignes pour transformation HSL
j = 0;
while (j < *W){
bufferHSL[i] = (float*)malloc( (*W) *sizeof(long int*) );
Actually, that seems just wrong - You are calling it for every j < *W iteration, but you only need it once per i. You are leaking the allocation, and only doing anything on it in the last iteration - are you sure your output is correct?
As a first step, I recommend moving that line out of the inner while loop.
There is room for several other microoptimizations, but I don't think you need to do them. Just make sure the code is first correct, and then find the part that is slow (usually it is the innermost loop), and focus just on that.

Related

Hello , I think I have a problem with the pointers , I need help ! , can you fix my code

#include <stdio.h>
void chercherVal(int tab[], int N, int A, int *pos, int *nb_occ) {
int i = 0;
while (i < N) {
if (tab[i] == A) {
*pos = i;
*nb_occ = *nb_occ + 1;
}
i++;
}
printf("la position est %d et le nombre d'occurence est %d", pos, nb_occ);
}
int main() {
int pos = -1, nb_occ = 0;
char A;
int i, N;
int tab[100];
printf("saisir le nombre d'elements de tab :");
scanf("%d", &N);
for (i = 0; i < N; i++) {
printf("saisir l'element %d du tableau tab :", i + 1);
scanf("%d", &tab[i]);
}
printf("saisir la valeur a rechercher :");
scanf("%s", &A);
chercherVal(tab, N, A, &pos, &nb_occ);
}
Here is one pointer problem (or lack of)
printf("la position est %d et le nombre d'occurence est %d", pos, nb_occ);
should be
printf("la position est %d et le nombre d'occurence est %d", *pos, *nb_occ);
The compiler should have warned that the wrong argument types are being passed.
Reading a string with scanf("%s", &A); into a single char has undefined behavior because scanf() will store the bytes and a null terminator, writing beyond the destination variable.
You should either make A and int and read a number: scanf("%d", &A);
Or you should read a single char with scanf(" %c", &A); (note the space before the % to skip pending white space, including the newline left in the standard input by previous calls to scanf().
Here is a modified version:
#include <stdio.h>
void chercherVal(const int tab[], int N, int A, int *posp, int *nb_occp) {
int pos = -1, occ = 0;
for (int i = 0; i < N; i++) {
if (tab[i] == A) {
occ++;
if (pos < 0) { /* only store the first position */
pos = i;
}
}
}
/* always store the return values */
*posp = pos;
*nb_occp = occ;
}
int main() {
int tab[100];
int N, A, pos, nb_occ;
printf("saisir le nombre d'elements de tab : ");
if (scanf("%d", &N) != 1)
return 1;
if (N > 100) /* prevent buffer overflow */
N = 100;
for (int i = 0; i < N; i++) {
printf("saisir l'element %d du tableau tab : ", i + 1);
if (scanf("%d", &tab[i]) != 1)
return 1;
}
printf("saisir la valeur a rechercher : ");
if (scanf("%d", &A) != 1)
return 1;
chercherVal(tab, N, A, &pos, &nb_occ);
printf("la position est %d et le nombre d'occurences est %d\n", pos, nb_occ);
return 0;
}

finding repetitions of integer X in an array and deleting them using pointers minus array

int A[50]; /* tableau donné */
int N; /* dimension du tableau */
int X; /* valeur à éliminer */
int *P1, *P2; /* pointeurs d'aide */
/* Saisie des données */
printf("Dimension du tableau (max.50) : ");
scanf("%d", &N);
for (P1 = A; P1 < A + N; P1++)
{
printf("Elément %d : ", P1 - A);
scanf("%d", P1);
}
printf("Introduire l'élément X à éliminer du tableau : ");
scanf("%d", &X);
/* Affichage du tableau */
for (P1 = A; P1 < A + N; P1++)
{
printf("%d ", *P1);
}
printf("\n");
/* Effacer toutes les occurrences de X et comprimer : */
/* Copier tous les éléments de P1 vers P2 et augmenter */
/* P2 pour tous les éléments différents de X. */
for (P1 = P2 = A; P1 < A + N; P1++)
{
*P2 = *P1;
if (*P2 != X)
P2++;
}
/* Nouvelle dimension de A */
N = P2 - A;
/* Edition du résultat */
for (P1 = A; P1 < A + N; P1++)
printf("%d ", *P1);
printf("\n");
system("pause");
return 0;
"N=P2-A" how does this one line deletes all repetitions of X and shrinks the array, I can't seem to understand it . P2 points on P1 which basically points on the whole array. how is it that P2(adress)minus A(adress of the first case in the array). deletes the occ and shrinks it .

Trouble using fscanf with a dynamic array

Soy try to make a code that take a .txt in imput and create dynamically a list of particle (with the structure particle created in a header file). The problem here is that when I try to printf the values of the list after it's values are implemented with the scanf function, the only thing gcc return is a list of int 0. Do you know what is wrong with my code?
Thank you by advance and sorry for my bad english(I'm French)
int main(int argc, char **argv) {
FILE *p_file = NULL;
p_file = fopen(argv[1], "r");
if (p_file == NULL) {
fprintf(stderr, "Cannot read file %s!\n", argv[1]);
exit(EXIT_FAILURE);
}
int particle_number;
int fscanf_result = fscanf(p_file, "%d\n", &particle_number);
printf("nombre de particules : %d\n", particle_number);
double px;
double py;
double vx;
double vy;
double mass;
double radius;
double color;
int line_nbr = 0;
particle *list_of_particle;
list_of_particle = (particle*)malloc(particle_number * sizeof(particle));
fscanf_result = fscanf(p_file, "%lf,%lf,%lf,%lf,%lf,%lf,%lf\n", &px, &py, &vx, &vy, &mass, &radius, &color);
while (fscanf_result != EOF) {
if (fscanf_result != 7) {
printf("Line number %d is not syntactically correct in particles-tests!\n",
line_nbr);
exit(EXIT_FAILURE);
}
particle *p = malloc(sizeof(particle));
(p -> position).x = px;
(p -> position).y = py;
(p -> velocity).x = vx;
(p -> velocity).y = vy;
p -> mass = mass;
p -> radius = radius;
p -> color = color;
printf("couleur du pointeur : %d\n", (p -> color));
list_of_particle[line_nbr] = *p;
line_nbr ++;
printf("vérification de la couleur de la liste : %d\n", (list_of_particle[line_nbr]).color);
printf("valeur du fscanf : %d\n", fscanf_result);
//printf("vérification du rayon de la particule numéro %d : %lf\n", line_nbr, (list_of_particle[line_nbr] -> radius));
fscanf_result = fscanf(p_file, "%lf,%lf,%lf,%lf,%lf,%lf,%lf\n", &px, &py, &vx, &vy, &mass, &radius, &color);
free(p);
}
fclose(p_file);
p_file = NULL;
}

invalid conversion from *void to *int [-fpermissive] using malloc(sizeof())

I'm writing a program that calculates the greatest common denominator of two numbers, but i'm getting problem with malloc function and pointers. Actually it's clear how the stack and the heap segments work in the memory and why. But yet i'm not yet able to understand when declaring a pointer and using malloc is functional or not, is necessary or not, in a program. here is the code :
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
int *calcolaDivisori(int);
int main(int argc, char** argv) {
int foundCounter = 0;
int i,j,s1,s2;
int n1,n2;
int mcd = 1,mcm;
int *pn1,*pn2;
int d1[100],d2[100];
// INPUT dei due interi
printf("Inserisci il primo numero :");
scanf(" %d", &n1);
printf("\nInserisci il secondo numero :");
scanf(" %d", &n2);
// calcolo divisori del primo e del secondo numero e li assegno ai relativi array
pn1 = calcolaDivisori(n1);
if (!pn1) return 1;
pn2 = calcolaDivisori(n2);
if (!pn2) return 1;
for (i=0;i<n1;i++) {
d1[i] = pn1[i];
}
for (i=0;i<n2;i++) {
d2[i] = pn2[i];
}
free(pn1);
free(pn2);
// confronto i divisori e calcolo il MCD
s1 = sizeof(d1) / sizeof(int);
s2 = sizeof(d2) / sizeof(int);
for(i=0; i<s1; i++) {
for (j=foundCounter; j<s2;j++) {
if (d1[i] == d2[j]) {
mcd*= d1[1];
foundCounter = j+1;
break;
}
}
}
printf("\n\nIl minimo comune divisore e' : %d", mcd);
return 0;
}
int *calcolaDivisori(int num) {
int i;
int *a = malloc(num * sizeof(int));
if (!a) return NULL;
for (i=2;i<num;i++) {
if (num%i == 0) {
num/=i;
a[i-2]=i;
}
}
return a;
}
I get the error in the title when is run the command :
int *a = malloc(sizeof(int));
You need to cast:
int *a = (int*)malloc(num * sizeof(int));
Because there's no implicit conversion from void* to type * in C++.
Note that this cast is not required in C and could potentially be dangerous to do so in C.
Except for #include <iostream>, nothing in your code is C++. So remove it and compile it with a C compiler and you wouldn't need this cast.

Errors while creating a graph in C

I'm trying to generate a graph from a matrix but I'm having some problems, here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_N 10
#define MAX_P 20
//Declaracion del TDA cola
typedef struct Node {
int rafaga;
int id;
struct Node *dret;
struct Node *esq;
int fiscals;
int funcionaris;
int advocats;
} tipoNodo;
typedef tipoNodo *pNodo; // tipo para declarar nodos a un entero
int nodes = 0, funcionarisTotals = 0, advocatsTotals = 0, fiscalsTotals = 0;
Node llista[MAX_N];
int graf[MAX_N*2][3];
void crearGraf(int graf[MAX_N*2][3]) {
FILE *pf;
char caracter; // variable de tipo caracter que va a servir para almacenar los caracteres leidos del archivo
int valor, o, d;
pf = fopen ("graf.txt","r"); // se abre el archivo en forma de lectura
if (!pf) { //en el caso que no se pueda abrir el archivo se manda un mensaje de error
printf ("ERROR: el fichero no existe o no se puede abrir\n");
exit(-1); //mensaje "presiona una tecla para continuar"
}
else {
int arestes = 0;
while (!feof (pf)) {
int j = 0;
nodes = int ((caracter=fgetc(pf))-'0');
printf ("El graf te %d\n nodes", nodes);
for(int i = 0 ; i < nodes ; i++) {
llista->[i].id = i;
llista.[i].rafaga = 1;
}
caracter = fgetc(pf);
o = int ((caracter = fgetc(pf))-'0'); //nodo origen
caracter = fgetc(pf);
d = int ((caracter = fgetc(pf))-'0');//nodo destino
caracter = fgetc(pf);
valor = int ((caracter =fgetc(pf))-'0');//pes de l'aresta
if (o < 0 || d < 0 || valor < 0) break;
printf ("%d %d %d\n",o,d,valor);
graf[o][d] = valor; // es guarda el pes de l'aresta que va de X -> Y a la matriu
arestes++;
}
fclose (pf);//se cierra el fichero
for(int j = 0; j<arestes ; j++) {
if(j == 0) {
llista[graf[j][0]]->dret = llista[graf[j][1]]; // enllacem l'aresta primera
}
if(j != 0 && (graf[j-1][0] == graf[j][0])) {
llista[graf[j][0]]->esq = llista[graf[j][1]]; // enllacem l'aresta esquerra
}
else {
llista[graf[j][0]]->dret = llista[graf[j][1]]; // enllacem l'aresta dreta
}
}
}
}
int main (void)
{
int graf[MAX_N][MAX_N];
crearGraf(graf);
return 0;
}
The error I'm getting is:
SC.c:57: error: expected unqualified-id before ‘[’ token
SC.c:58: error: expected unqualified-id before ‘[’ token
Which are these two lines in the for loop:
for(int i = 0 ; i < nodes ; i++) {
llista->[i].id = i;
llista.[i].rafaga = 1;
}
I think I don't understand really the TYPE of variable I'mworking with here.
Could someone give me a hand? I've been trying to look for similar problems but I couldn't fix mine.
Thanks!
Change these 2 lines to
llista[i].id = i;
llista[i].rafaga = 1;
and you will be accessing the things that you appear to be trying to access.
Using the -> operator dereferences a pointer while it appears that you just want to access array elements which is done as above. I cannot speak for the correctness of the remainder of your code but these changes at the least should remove your compiler errors.

Resources