-
Notifications
You must be signed in to change notification settings - Fork 3
/
util.c
214 lines (184 loc) · 6.3 KB
/
util.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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#include <GL/glew.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "jpeglib.h"
/*
* Boring, non-OpenGL-related utility functions
*/
void *file_contents(const char *filename, GLint *length)
{
FILE *f = fopen(filename, "r");
void *buffer;
if (!f) {
fprintf(stderr, "Unable to open %s for reading\n", filename);
return NULL;
}
fseek(f, 0, SEEK_END);
*length = ftell(f);
fseek(f, 0, SEEK_SET);
buffer = malloc(*length+1);
*length = fread(buffer, 1, *length, f);
fclose(f);
((char*)buffer)[*length] = '\0';
return buffer;
}
static short le_short(unsigned char *bytes)
{
return bytes[0] | ((char)bytes[1] << 8);
}
void *read_tga(const char *filename, int *width, int *height)
{
struct tga_header {
char id_length;
char color_map_type;
char data_type_code;
unsigned char color_map_origin[2];
unsigned char color_map_length[2];
char color_map_depth;
unsigned char x_origin[2];
unsigned char y_origin[2];
unsigned char width[2];
unsigned char height[2];
char bits_per_pixel;
char image_descriptor;
} header;
int i, color_map_size, pixels_size;
FILE *f;
size_t read;
void *pixels;
f = fopen(filename, "rb");
if (!f) {
fprintf(stderr, "Unable to open %s for reading\n", filename);
return NULL;
}
read = fread(&header, 1, sizeof(header), f);
if (read != sizeof(header)) {
fprintf(stderr, "%s has incomplete tga header\n", filename);
fclose(f);
return NULL;
}
if (header.data_type_code != 2) {
fprintf(stderr, "%s is not an uncompressed RGB tga file\n", filename);
fclose(f);
return NULL;
}
if (header.bits_per_pixel != 24) {
fprintf(stderr, "%s is not a 24-bit uncompressed RGB tga file\n", filename);
fclose(f);
return NULL;
}
for (i = 0; i < header.id_length; ++i)
if (getc(f) == EOF) {
fprintf(stderr, "%s has incomplete id string\n", filename);
fclose(f);
return NULL;
}
color_map_size = le_short(header.color_map_length) * (header.color_map_depth/8);
for (i = 0; i < color_map_size; ++i)
if (getc(f) == EOF) {
fprintf(stderr, "%s has incomplete color map\n", filename);
fclose(f);
return NULL;
}
*width = le_short(header.width); *height = le_short(header.height);
pixels_size = *width * *height * (header.bits_per_pixel/8);
pixels = malloc(pixels_size);
read = fread(pixels, 1, pixels_size, f);
fclose(f);
if (read != pixels_size) {
fprintf(stderr, "%s has incomplete image\n", filename);
free(pixels);
return NULL;
}
return pixels;
}
unsigned char *read_jpeg(const char *filename, int *width, int *height ) {
unsigned char *pixels;
/* these are standard libjpeg structures for reading(decompression) */
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
/* libjpeg data structure for storing one row, that is, scanline of an image */
JSAMPROW row_pointer[1];
FILE *infile = fopen( filename, "rb" );
unsigned long location = 0;
int i = 0;
if ( !infile )
{
printf("Error opening jpeg file %s\n!", filename );
exit(-1);
}
/* here we set up the standard libjpeg error handler */
cinfo.err = jpeg_std_error( &jerr );
/* setup decompression process and source, then read JPEG header */
jpeg_create_decompress( &cinfo );
/* this makes the library read from infile */
jpeg_stdio_src( &cinfo, infile );
/* reading the image header which contains image information */
jpeg_read_header( &cinfo, TRUE );
/* Uncomment the following to output image information, if needed. */
/*--
printf( "JPEG File Information: \n" );
printf( "Image width and height: %d pixels and %d pixels.\n", cinfo.image_width, cinfo.image_height );
printf( "Color components per pixel: %d.\n", cinfo.num_components );
printf( "Color space: %d.\n", cinfo.jpeg_color_space );
--*/
/* Start decompression jpeg here */
jpeg_start_decompress( &cinfo );
*width = cinfo.output_width;
*height = cinfo.output_height;
/* allocate memory to hold the uncompressed image */
pixels = (unsigned char*)malloc( cinfo.output_width*cinfo.output_height*cinfo.num_components );
/* now actually read the jpeg into the raw buffer */
row_pointer[0] = (unsigned char *)malloc( cinfo.output_width*cinfo.num_components );
/* read one scan line at a time */
while( cinfo.output_scanline < cinfo.image_height )
{
jpeg_read_scanlines( &cinfo, row_pointer, 1 );
for( i=0; i<cinfo.image_width*cinfo.num_components;i++)
pixels[location++] = row_pointer[0][i];
}
/* wrap up decompression, destroy objects, free pointers and close open files */
jpeg_finish_decompress( &cinfo );
jpeg_destroy_decompress( &cinfo );
free( row_pointer[0] );
fclose( infile );
/* yup, we succeeded! */
return pixels;
}
int write_jpeg(const char *filename, unsigned char* raw_image, int width, int height){
int bytes_per_pixel = 3; /* or 1 for GRACYSCALE images */
int color_space = JCS_RGB; /* or JCS_GRAYSCALE for grayscale images */
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
/* this is a pointer to one row of image data */
JSAMPROW row_pointer[1];
FILE *outfile = fopen( filename, "wb" );
if ( !outfile )
{
printf("Error opening output jpeg file %s\n!", filename );
exit(-1);
}
cinfo.err = jpeg_std_error( &jerr );
jpeg_create_compress(&cinfo);
jpeg_stdio_dest(&cinfo, outfile);
/* Setting the parameters of the output file here */
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = bytes_per_pixel;
cinfo.in_color_space = (J_COLOR_SPACE)color_space;
/* default compression parameters, we shouldn't be worried about these */
jpeg_set_defaults( &cinfo );
/* Now do the compression .. */
jpeg_start_compress( &cinfo, TRUE );
/* like reading a file, this time write one row at a time */
while( cinfo.next_scanline < cinfo.image_height )
{
row_pointer[0] = &raw_image[ cinfo.next_scanline * cinfo.image_width * cinfo.input_components];
jpeg_write_scanlines( &cinfo, row_pointer, 1 );
}
/* similar to read file, clean up after we're done compressing */
jpeg_finish_compress( &cinfo );
jpeg_destroy_compress( &cinfo );
fclose( outfile );
}