generated from OPCODE-Open-Spring-Fest/template
-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathimage_io.c
More file actions
117 lines (113 loc) · 3.57 KB
/
image_io.c
File metadata and controls
117 lines (113 loc) · 3.57 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
#include "image_io.h"
#include <string.h>
#include <ctype.h>
#include <stdint.h>
#include <stdlib.h>
// Detect image format by reading file signature
ImageFormat detect_image_format(const char *filename) {
FILE *file = fopen(filename, "rb");
if (!file) {
return IMAGE_FORMAT_UNKNOWN;
}
uint8_t header[8];
size_t bytes_read = fread(header, 1, 8, file);
fclose(file);
if (bytes_read < 2) return IMAGE_FORMAT_UNKNOWN;
//BMP: "BM"(0x42 0x4D)
if (header[0] == 0x42 && header[1] == 0x4D) {
return IMAGE_FORMAT_BMP;
}
//PNG: \x89PNG\r\n\x1a\n
if (bytes_read >= 8 && header[0] == 0x89 && header[1] == 0x50 && header[2] == 0x4E && header[3] == 0x47 && header[4] == 0x0D && header[5] == 0x0A && header[6] == 0x1A && header[7] == 0x0A) {
return IMAGE_FORMAT_PNG;
}
//JPEG: \xFF\xD8\xFF
if (bytes_read >= 3 && header[0] == 0xFF && header[1] == 0xD8 && header[2] == 0xFF) {
return IMAGE_FORMAT_JPEG;
}
return IMAGE_FORMAT_UNKNOWN;
}
// Get format from file extension
ImageFormat get_format_from_extension(const char *filename) {
const char *ext = strrchr(filename, '.');
if (!ext) {
return IMAGE_FORMAT_UNKNOWN;
}
ext++;
char lower_ext[10];
int i = 0;
while (ext[i] && i < 9) {
lower_ext[i] = tolower(ext[i]);
i++;
}
lower_ext[i] = '\0';
if (strcmp(lower_ext, "bmp") == 0) {
return IMAGE_FORMAT_BMP;
} else if (strcmp(lower_ext, "png") == 0) {
return IMAGE_FORMAT_PNG;
} else if (strcmp(lower_ext, "jpg") == 0 || strcmp(lower_ext, "jpeg") == 0) {
return IMAGE_FORMAT_JPEG;
}
return IMAGE_FORMAT_UNKNOWN;
}
extern int read_bmp(const char *filename, ImageData *img);
extern int read_png(const char *filename, ImageData *img);
extern int read_jpeg(const char *filename, ImageData *img);
extern int write_bmp(const char *filename, ImageData *img);
extern int write_png(const char *filename, ImageData *img);
extern int write_jpeg(const char *filename, ImageData *img);
// Read image from file
int read_image(const char *filename, ImageData *img) {
if (!filename || !img) {
return 1;
}
ImageFormat format = detect_image_format(filename);
if (format == IMAGE_FORMAT_UNKNOWN) {
format = get_format_from_extension(filename);
}
img->format = format;
switch (format) {
case IMAGE_FORMAT_BMP:
return read_bmp(filename, img);
case IMAGE_FORMAT_PNG:
return read_png(filename, img);
case IMAGE_FORMAT_JPEG:
return read_jpeg(filename, img);
default:
return 1;
}
}
// Write image to file
int write_image(const char *filename, ImageData *img, ImageFormat output_format) {
if (!filename || !img || !img->pixels) {
return 1;
}
if (output_format == IMAGE_FORMAT_UNKNOWN) {
output_format = get_format_from_extension(filename);
}
if (output_format == IMAGE_FORMAT_UNKNOWN) {
output_format = img->format;
}
switch (output_format) {
case IMAGE_FORMAT_BMP:
return write_bmp(filename, img);
case IMAGE_FORMAT_PNG:
return write_png(filename, img);
case IMAGE_FORMAT_JPEG:
return write_jpeg(filename, img);
default:
return 1;
}
}
// Free image data
void free_image(ImageData *img) {
if (img && img->pixels) {
if (img->height > 0 && img->pixels[0]) {
free(img->pixels[0]);
}
free(img->pixels);
img->pixels = NULL;
img->width = 0;
img->height = 0;
}
}