Bonsoir,

j'essaie d'utiliser la libpng pour lire et écrire des custom chunks, en lisant la documentation j'ai trouvé les fonctions qu'il faut mais cela ne fonctionne pas. La fonction censée lire le chunk spécial n'est pas appelé comme si de rien n'étais. De plus décommenter png_read_end renvoie une erreur de CRC, je ne comprends pas. Voici le code :

Code C : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <png.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
FILE *fp;
png_structp png_ptr;
png_infop info_ptr, end_info;
png_byte magic[8];
png_byte custom_chunk[5] = { 116, 73, 77, 69, (png_byte)'\0' }; // tIME
png_byte unused_chunks[]=
{
	104,  73,  83,  84, (png_byte) '\0',   /* hIST */
	105,  84,  88, 116, (png_byte) '\0',   /* iTXt */
	112,  67,  65,  76, (png_byte) '\0',   /* pCAL */
	115,  67,  65,  76, (png_byte) '\0',   /* sCAL */
	115,  80,  76,  84, (png_byte) '\0',   /* sPLT */
	'I', 'D', 'A', 'T', (png_byte) '\0'
};
 
void readPNG(char *file);
void read_chunk_custom(png_structp ptr, png_unknown_chunkp chunk);
int main(int argc, char **argv);
 
void read_chunk_custom(png_structp ptr, png_unknown_chunkp chunk) {
	printf("Reading custom chunk @ %p\n", chunk->data);
 
	FILE *out = fopen("./out.jpg", "wb");
	if (!out) {
		fprintf(stderr, "Cannot write the chunk to ouput.\n");
		return;
	}
 
	fwrite(chunk->data, 1, sizeof(chunk->data), out);
	fclose(out);
 
	return;
}
 
void readPNG(char *file) {
	printf("read: %s\n", file);
 
	fp = fopen(file, "rb");
	if (!fp) {
		fprintf(stderr, "Cannot open %s.\n", file);
		return;
	}
 
	fread(magic, 1, sizeof(magic), fp);
	if (!png_check_sig(magic, sizeof(magic))) {
		fprintf(stderr, "error: %s isn't a valid PNG file.\n", file);
		return;
	}
	//fseek(fp, 0, SEEK_SET);
 
	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!png_ptr) {
		fprintf(stderr, "Cannot create read struct.\n");
		return;
	}
 
	info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr) {
		png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
		fprintf(stderr, "Cannot create info struct.\n");
		return;
	}
 
	end_info = png_create_info_struct(png_ptr);
	if (!end_info)
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
		fprintf(stderr, "Cannot create end info struct.\n");
		return;
	}
 
	if (setjmp(png_jmpbuf(png_ptr))) {
		fprintf(stderr, "Error: fatal.\n");
		return;
	}
 
	png_init_io(png_ptr, fp);
	png_set_sig_bytes(png_ptr, sizeof(magic));
 
	png_read_info(png_ptr, info_ptr);
	png_read_update_info (png_ptr, info_ptr);
 
	int width = png_get_image_width(png_ptr, info_ptr),
		height = png_get_image_height(png_ptr, info_ptr);
	printf("Image %i x %i\n", width, height);
 
	/* ignore all unknown chunks: */
	png_set_keep_unknown_chunks(png_ptr, 1, NULL, 0);
	/* except for our custom chunk: */
	png_set_keep_unknown_chunks(png_ptr, 2, custom_chunk, sizeof(custom_chunk)/5);
	/* also ignore unused known chunks: */
	png_set_keep_unknown_chunks(png_ptr, 1, unused_chunks, sizeof(unused_chunks)/5);
 
	png_set_read_user_chunk_fn(png_ptr, NULL, (png_user_chunk_ptr)read_chunk_custom);
	//png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, custom_chunk, sizeof(custom_chunk)/5);
 
	// Renvoie une erreur CRC si décommenter !
	//png_read_end(png_ptr, end_info);
	png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
 
	fclose(fp);
}
 
int main(int argc, char **argv) {
	if (strcmp(argv[1], "-r") || strcmp(argv[1], "--read")) {
		readPNG(argv[2]);
	}
	return 0;
}

Output:
$ ./png-embedder -r file.png
read: file.png
Image 400 x 400
J'ai bien vérifié, dans mon fichier j'ai bien un chunk tIME (déjà pour essayer). Le fichier est lisible avec plusieurs programmes pas de soucis. J'ai l'impression que png_read_end devrait être appelé pour que tout fonctionne. Que faire ? merci d'avance.