-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathimage.c
More file actions
212 lines (173 loc) · 4.63 KB
/
image.c
File metadata and controls
212 lines (173 loc) · 4.63 KB
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
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdarg.h>
#include <arpa/inet.h>
#include <strings.h>
#include "image.h"
void Image_construct(Image *this)
{
this->size_x = this->size_y = 0;
this->data = 0;
}
void Image_construct_size_channels(
Image *this,
uint_fast32_t size_x, uint_fast32_t size_y,
uint_fast8_t channels)
{
size_t bytes;
memset(this, 0, sizeof *this);
bytes = size_x * size_y * channels;
this->data = (uint8_t *)malloc(bytes);
if (!this->data) {
Image_log(this, IMAGE_LOGLEVEL_FATAL, "cannot allocate memory\n");
return;
}
this->size_x = size_x;
this->size_y = size_y;
this->total_x = size_x;
this->total_y = size_y;
this->channels = channels;
}
void Image_construct_size_total_channels(
Image *this,
uint_fast32_t size_x, uint_fast32_t size_y,
uint_fast32_t total_x, uint_fast32_t total_y,
uint_fast8_t channels)
{
size_t bytes;
memset(this, 0, sizeof *this);
if (size_x > total_x || size_y > total_y) {
Image_log(this, IMAGE_LOGLEVEL_FATAL, "can't create an image size greater than total pixel size\n");
}
bytes = total_x * total_y * channels;
this->data = (uint8_t *)malloc(bytes);
if (!this->data) {
Image_log(this, IMAGE_LOGLEVEL_FATAL, "cannot allocate memory\n");
return;
}
this->size_x = size_x;
this->size_y = size_y;
this->total_x = total_x;
this->total_y = total_y;
this->channels = channels;
}
void Image_destruct(Image *this)
{
if (this->data)
free(this->data);
}
Image_Result Image_write_format_filename(
Image *image,
const char *format,
const char *filename)
{
FILE *output_file;
const char *error_string;
Image_Result image_result = IMAGE_RESULT_SUCCESS;
output_file = fopen(filename, "wb");
if (!output_file) {
error_string = strerror(errno);
Image_log(image, IMAGE_LOGLEVEL_FATAL,
"cannot open '%s' for writing (reason: '%s'",
filename, error_string);
return IMAGE_RESULT_FAILURE;
}
if (strcasecmp(format, "TGA") == 0) {
Image_write_format_file_TGA(image, output_file);
} else {
Image_log(image, IMAGE_LOGLEVEL_FATAL, "could not find appropriate output handler\n");
image_result = IMAGE_RESULT_FAILURE;
}
fclose(output_file);
return image_result;
}
Image_Result Image_write_format_file_TGA(Image *this, FILE *file)
{
uint8_t header[18] = { 0 };
uint_fast16_t row;
header[2] = 2; /* image type */
header[7] = 32; /* colour map bits (we have no colour map but some apps
require this field to be set) */
header[12] = this->size_x % 256;
header[13] = this->size_x / 256;
header[14] = this->size_y % 256;
header[15] = this->size_y / 256;
header[16] = 24; /* bits per plane */
header[17] = 32; /* vflip flag : first row is top row */
fwrite(header, sizeof header, 1, file);
for (row = 0; row < this->size_y; row++)
{
fwrite(this->data + row*this->total_x * this->channels,
this->size_x * this->channels, 1, file);
}
return IMAGE_RESULT_SUCCESS;
}
extern int fileno(FILE *);
Image_Result Image_read_format_memory_wrap_file(
Image *image,
FILE *file,
Image_Result (*read_format_memory)(Image *, uint8_t *, uint8_t *))
{
struct stat file_stat;
size_t file_size;
uint8_t *file_data;
fstat(fileno(file), &file_stat);
file_size = file_stat.st_size;
file_data = (uint8_t *)malloc(file_size);
fread(file_data, file_size, 1, file);
read_format_memory(image, file_data, file_data + file_size);
return IMAGE_RESULT_SUCCESS;
}
Image_Result Image_read_format_file_JPEG(
Image *this,
FILE *file)
{
return Image_read_format_memory_wrap_file(this, file, Image_read_format_memory_JPEG);
}
void Image_log_level_set(Image *image, Image_LogLevel log_level) {
}
Image_Result Image_read_format_filename(
Image *image,
const char *format,
const char *file_name)
{
FILE *input_file;
const char *error_string;
Image_Result image_result = IMAGE_RESULT_FAILURE;
if (!format) {
Image_log(image, IMAGE_LOGLEVEL_FATAL, "format not specified\n");
return image_result;
}
input_file = fopen(file_name, "rb");
if (!input_file) {
error_string = strerror(errno);
Image_log(image, IMAGE_LOGLEVEL_FATAL,
"cannot open '%s' for writing (reason: '%s'",
file_name, error_string);
}
if (strcasecmp(format, "JPEG") == 0) {
image_result = Image_read_format_file_JPEG(image, input_file);
} else {
Image_log(image, IMAGE_LOGLEVEL_FATAL, "cannot find appropriate format handler\n");
}
fclose(input_file);
return image_result;
}
const char *Image_lasterror_string(Image *image)
{
return "unknown error";
}
void Image_log(
Image *image,
Image_LogLevel log_level,
const char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
}