#include <gint/gint.h>
#include <gint/display.h>
#include <gint/keyboard.h>
#include <stdio.h>
#include <stdlib.h>
#include <jpeglib.h>
#include <jerror.h>
struct imgRawImage
{
unsigned int numComponents;
unsigned long int width, height;
unsigned char* lpData;
};
struct imgRawImage* loadJpegImageFile(char* lpFilename)
{
struct jpeg_decompress_struct info;
struct jpeg_error_mgr err;
struct imgRawImage* lpNewImage;
unsigned long int imgWidth, imgHeight;
int numComponents;
unsigned long int dwBufferBytes;
unsigned char* lpData;
unsigned char* lpRowBuffer[1];
FILE* fHandle;
fHandle = fopen(lpFilename, "rb");
if(fHandle == NULL)
{
#ifdef DEBUG
fprintf(stderr, "%s:%u: Failed to read file %s\n", __FILE__, __LINE__, lpFilename);
#endif
return NULL; /* ToDo */
}
info.err = jpeg_std_error(&err);
jpeg_create_decompress(&info);
jpeg_stdio_src(&info, fHandle);
jpeg_read_header(&info, TRUE);
jpeg_start_decompress(&info);
imgWidth = info.output_width;
imgHeight = info.output_height;
numComponents = info.num_components;
dwBufferBytes = imgWidth * imgHeight * 3; /* We only read RGB, not A */
lpData = (unsigned char*)malloc(sizeof(unsigned char)*dwBufferBytes);
lpNewImage = (struct imgRawImage*)malloc(sizeof(struct imgRawImage));
lpNewImage->numComponents = numComponents;
lpNewImage->width = imgWidth;
lpNewImage->height = imgHeight;
lpNewImage->lpData = lpData;
/* Read scanline by scanline */
while(info.output_scanline < info.output_height)
{
lpRowBuffer[0] = (unsigned char *)(&lpData[3*info.output_width*info.output_scanline]);
jpeg_read_scanlines(&info, lpRowBuffer, 1);
}
jpeg_finish_decompress(&info);
jpeg_destroy_decompress(&info);
fclose(fHandle);
return lpNewImage;
}
size_t image_size_profile(int width, int height)
{
size_t size = sizeof(bopti_image_t);
size += width * height * 2;
return size;
}
void set_pixel(bopti_image_t *img, int x, int y, int color)
{
if((unsigned)x >= img->width || (unsigned)y >= img->height)
return;
uint8_t *bytes = (void *)img->data;
img->data[y * img->width + x] = color;
}
bopti_image_t *convert_jpg_to_bopti( char *filename )
{
struct imgRawImage* myJPEG;
myJPEG = (struct imgRawImage*) gint_world_switch( GINT_CALL( loadJpegImageFile, "testimg.jpg" ) );
if (myJPEG==NULL) return NULL;
int Wmax = myJPEG->width;
if (myJPEG->width%2==1) Wmax++; // si largeur impaire, on rajoute un pixel transparent
size_t size = image_size_profile(Wmax, myJPEG->height);
bopti_image_t *image_temp = malloc( size );
if(!image_temp) return NULL;
image_temp->profile = 0; // par defaut on a pas la transparence (on updatera si besoin après)
image_temp->alpha = 0x0001;
image_temp->width = Wmax;
image_temp->height = myJPEG->height;
uint16_t color;
for (long unsigned int v=0; v<myJPEG->height; v++ )
{
for( long unsigned int u=0; u<myJPEG->width; u++ )
{
if (myJPEG->numComponents == 1)
{
unsigned char Grey = myJPEG->lpData[v*myJPEG->width+u]>>3;
set_pixel(image_temp, u, v, C_RGB( Grey, Grey, Grey ) );
}
else if (myJPEG->numComponents == 3)
{
unsigned char R = myJPEG->lpData[(v*myJPEG->width+u)*3+0]>>3;
unsigned char G = myJPEG->lpData[(v*myJPEG->width+u)*3+1]>>3;
unsigned char B = myJPEG->lpData[(v*myJPEG->width+u)*3+2]>>3;
color = C_RGB( R, G, B );
if (color!=0x0001) set_pixel(image_temp, u, v, color);
else set_pixel(image_temp, u, v, 0x0000);
}
else if (myJPEG->numComponents == 4)
{
unsigned char R = myJPEG->lpData[(v*myJPEG->width+u)*4+0]>>3;
unsigned char G = myJPEG->lpData[(v*myJPEG->width+u)*4+1]>>3;
unsigned char B = myJPEG->lpData[(v*myJPEG->width+u)*4+2]>>3;
unsigned char A = myJPEG->lpData[(v*myJPEG->width+u)*4+3];
if (A>=128) set_pixel(image_temp, u, v, C_RGB( R, G, B ) );
else
{
set_pixel(image_temp, u, v, 0x0001); // set transparency
image_temp->profile = 1; // on mets à jour le profil car il y a de la transparence
}
}
}
if (Wmax!=myJPEG->width) // si on doit ajouter un pixel supplémentaire sur la largeur
{
set_pixel(image_temp, Wmax, v, 0x0001);
}
}
free(myJPEG->lpData);
free(myJPEG);
return image_temp;
}
bopti_image_t *image = NULL;
bopti_image_t *image2 = NULL;
int main(void)
{
// Jute ici pour désactiver le triple buffering par défaut
uint16_t *vram1, *vram2;
dgetvram(&vram1, &vram2);
dsetvram(vram1, vram1);
dclear(C_WHITE);
dtext(1, 190, C_BLACK, "Sample libcJPG to bopti test :");
dupdate();
image = convert_jpg_to_bopti( "testimg.jpg" );
image2 = convert_jpg_to_bopti( "nofile.jpg" ); // fichier qui n'existe pas, controle de la stabilité
dimage( 0, 0, image );
dimage( 0, 0, image2 ); // ne doit pas planter
dsubimage( 200, 50, image, 21,15, 120, 88, DIMAGE_NONE );
dsubimage( 200, 50, image2, 21,15, 120, 88, DIMAGE_NONE ); // idem, sans plantage
dupdate();
getkey();
if (image!=NULL) free(image);
if (image2!=NULL) free(image2);
return 1;
}
Citer : Posté le 09/05/2022 18:38 | #
Le dépôt Gitea est désormais opérationnel.
La libJPEG peut donc être installée via un
de manière automatique (ou presque).
Ciao
Sly
Citer : Posté le 28/05/2022 12:37 | #
Hello,
suite au changement de gint <2.7.1 vers 2.8 avec l'introduction des nouvelles routines image et du nouveau format image_t en remplacement du "vieux" format bopti_image_t, je vous fais une MàJ de la routine d'import de libJPG vers ce nouveau format image_t.
Donc si vous êtes en gint <2.7.1, c'est l'ancienne routine qu'il faut utiliser (voir deux posts plus haut), si vous êtes en gint 2.8 (ou ultérieur, cela viendra), il vous faudra désormais utiliser le code suivant :
#include <gint/gint.h>
#include <gint/display.h>
#include <gint/keyboard.h>
#include <stdio.h>
#include <stdlib.h>
#include <jpeglib.h>
#include <jerror.h>
struct imgRawImage
{
unsigned int numComponents;
unsigned long int width, height;
unsigned char* lpData;
};
struct imgRawImage* loadJpegImageFile(char* lpFilename)
{
struct jpeg_decompress_struct info;
struct jpeg_error_mgr err;
struct imgRawImage* lpNewImage;
unsigned long int imgWidth, imgHeight;
int numComponents;
unsigned long int dwBufferBytes;
unsigned char* lpData;
unsigned char* lpRowBuffer[1];
FILE* fHandle;
fHandle = fopen(lpFilename, "rb");
if(fHandle == NULL)
{
return NULL;
}
info.err = jpeg_std_error(&err);
jpeg_create_decompress(&info);
jpeg_stdio_src(&info, fHandle);
jpeg_read_header(&info, TRUE);
jpeg_start_decompress(&info);
imgWidth = info.output_width;
imgHeight = info.output_height;
numComponents = info.num_components;
dwBufferBytes = imgWidth * imgHeight * 3;
lpData = (unsigned char*)malloc(sizeof(unsigned char)*dwBufferBytes);
lpNewImage = (struct imgRawImage*)malloc(sizeof(struct imgRawImage));
lpNewImage->numComponents = numComponents;
lpNewImage->width = imgWidth;
lpNewImage->height = imgHeight;
lpNewImage->lpData = lpData;
while(info.output_scanline < info.output_height)
{
lpRowBuffer[0] = (unsigned char *)(&lpData[3*info.output_width*info.output_scanline]);
jpeg_read_scanlines(&info, lpRowBuffer, 1);
}
jpeg_finish_decompress(&info);
jpeg_destroy_decompress(&info);
fclose(fHandle);
return lpNewImage;
}
image_t *convert_jpg_to_image_t( char *filename )
{
struct imgRawImage* myJPEG;
myJPEG = (struct imgRawImage*) gint_world_switch( GINT_CALL( loadJpegImageFile, "testimg.jpg" ) );
if (myJPEG==NULL) return NULL;
image_t *image_temp;
int Wmax = myJPEG->width;
if (Wmax%2==1)
{
Wmax++; // si largeur impaire, on rajoute un pixel transparent
image_temp = image_alloc( Wmax, myJPEG->height, IMAGE_RGB565A ); // le format devient avec couleur transparente
}
else
image_temp = image_alloc( Wmax, myJPEG->height, IMAGE_RGB565 ); // sinon le format est sans transparence
if(!image_temp) return NULL;
uint16_t color;
for (long unsigned int v=0; v<myJPEG->height; v++ )
{
for( long unsigned int u=0; u<myJPEG->width; u++ )
{
if (myJPEG->numComponents == 1)
{
unsigned char Grey = myJPEG->lpData[v*myJPEG->width+u]>>3;
image_set_pixel(image_temp, u, v, C_RGB( Grey, Grey, Grey ) );
}
else if (myJPEG->numComponents == 3)
{
unsigned char R = myJPEG->lpData[(v*myJPEG->width+u)*3+0]>>3;
unsigned char G = myJPEG->lpData[(v*myJPEG->width+u)*3+1]>>3;
unsigned char B = myJPEG->lpData[(v*myJPEG->width+u)*3+2]>>3;
color = C_RGB( R, G, B );
if (color!=0x0001) image_set_pixel(image_temp, u, v, color);
else image_set_pixel(image_temp, u, v, 0x0000);
}
else if (myJPEG->numComponents == 4) // il y a un canal alpha dans l'image (exotique pour du JPEG), donc on update le format
{
unsigned char R = myJPEG->lpData[(v*myJPEG->width+u)*4+0]>>3;
unsigned char G = myJPEG->lpData[(v*myJPEG->width+u)*4+1]>>3;
unsigned char B = myJPEG->lpData[(v*myJPEG->width+u)*4+2]>>3;
unsigned char A = myJPEG->lpData[(v*myJPEG->width+u)*4+3];
if (A>=128) image_set_pixel(image_temp, u, v, C_RGB( R, G, B ) );
else
{
image_temp->format = IMAGE_RGB565A; // on mets à jour le profil car il y a de la transparence
image_set_pixel(image_temp, u, v, image_alpha(IMAGE_RGB565A)); // set transparency
}
}
}
if (Wmax!=myJPEG->width) // si on doit ajouter un pixel supplémentaire sur la largeur
{
image_set_pixel(image_temp, Wmax-1, v, image_alpha(IMAGE_RGB565A));
}
}
free(myJPEG->lpData);
free(myJPEG);
return image_temp;
}
image_t *image = NULL;
image_t *image2 = NULL;
int main(void)
{
// Jute ici pour désactiver le triple buffering par défaut
uint16_t *vram1, *vram2;
dgetvram(&vram1, &vram2);
dsetvram(vram1, vram1);
dclear(C_WHITE);
dtext(1, 190, C_BLACK, "Simple libcJPG to image_t (gint 2.8) test :");
dupdate();
image = convert_jpg_to_image_t( "testimg.jpg" );
image2 = convert_jpg_to_image_t( "nofile.jpg" ); // fichier qui n'existe pas, controle de la stabilité
dimage( 0, 0, image );
dimage( 0, 0, image2 );
dsubimage( 200, 50, image, 21,15, 120, 88, DIMAGE_NONE );
dsubimage( 200, 50, image2, 21,15, 120, 88, DIMAGE_NONE ); // idem, sans plantage
dupdate();
getkey();
if (image!=NULL) free(image);
if (image2!=NULL) free(image2);
return 1;
}
a priori l'inversion (ou mix entre les versions de gint/cette routine) n'est pas possible, vous aurez forcément une erreur à la compilation soit pour cause de membre .profil absent (remplacé par .format dans gint 2.8), soit pour cause d'absence de définition de image_t.
A plus
Sly