-
Notifications
You must be signed in to change notification settings - Fork 5
/
pngread.c
103 lines (86 loc) · 2.75 KB
/
pngread.c
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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <png.h>
#include <unistd.h>
char *readimage(char *filename, png_uint_32 *width, png_uint_32 *height,
int *bitdepth, int *channels);
char *readimage(char *filename, png_uint_32 *width, png_uint_32 *height,
int *bitdepth, int *channels){
FILE *image;
png_uint_32 i, j, rowbytes;
png_structp png;
png_infop info;
png_bytepp row_pointers = NULL;
unsigned char sig[8];
char *raster;
int colourtype;
// Open the file
if ((image = fopen (filename, "rb")) == NULL){
fprintf(stderr, "Could not open the specified PNG file.");
goto error;
}
// Check that it really is a PNG file
fread(sig, 1, 8, image);
if(!png_sig_cmp(sig, 0, 8) == 0){
fprintf(stderr, "This file is not a valid PNG file\n");
goto error;
}
// Start decompressing
if((png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
NULL, NULL)) == NULL){
fprintf(stderr, "Could not create a PNG read structure (out of memory?)");
goto error;
}
if((info = png_create_info_struct(png)) == NULL){
fprintf(stderr, "Could not create PNG info structure (out of memory?)");
png_destroy_read_struct (&png, &info, NULL);
goto error;
}
// If pnginfo_error did not exit, we would have to call
// png_destroy_read_struct
if(setjmp(png_jmpbuf(png))){
fprintf(stderr, "Could not set PNG jump value");
goto error;
}
// Get ready for IO and tell the API we have already read the image signature
png_init_io(png, image);
png_set_sig_bytes(png, 8);
png_read_info(png, info);
png_get_IHDR(png, info, width, height, bitdepth, &colourtype, NULL,
NULL, NULL);
if(*bitdepth < 8)
png_set_packing(png);
if (colourtype == PNG_COLOR_TYPE_PALETTE)
png_set_expand (png);
// The channels bit has to be after here, so that the number of channels within the
// palette is correctly reported...
//png_set_strip_alpha (png);
png_read_update_info (png, info);
*channels = png_get_channels(png, info);
rowbytes = png_get_rowbytes (png, info);
if((row_pointers = malloc (*height * sizeof (png_bytep))) == NULL){
fprintf(stderr, "Could not allocate memory\n");
goto error;
}
// Space for the bitmap
if((raster = (unsigned char *) malloc ((rowbytes * *height) + 1)) == NULL){
fprintf(stderr, "Could not allocate memory\n");
goto error;
}
// Get the image bitmap
for (i = 0; i < *height; ++i)
row_pointers[i] = raster + (i * rowbytes);
png_read_image (png, row_pointers);
goto cleanup;
error:
free(raster);
raster = NULL;
cleanup:
if(row_pointers != NULL) free(row_pointers);
png_read_end (png, NULL);
fclose (image);
png_destroy_read_struct (&png, &info, NULL);
// And return the raster
return raster;
}