-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathok_jpg.h
233 lines (202 loc) · 8.18 KB
/
ok_jpg.h
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
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/*
ok-file-formats
https://github.com/brackeen/ok-file-formats
Copyright (c) 2014-2020 David Brackeen
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef OK_JPG_H
#define OK_JPG_H
/**
* @file
* Functions to read JPEG files.
*
* This JPEG decoder:
* - Reads most JPEG files (baseline and progressive).
* - Interprets EXIF orientation tags.
* - Option to get the image dimensions without decoding.
* - Option to flip the image vertically.
* - Returns data in RGBA or BGRA format.
*
* Caveats:
* - No CMYK or YCCK support.
*
* Example:
*
* #include <stdio.h>
* #include "ok_jpg.h"
*
* int main() {
* FILE *file = fopen("my_image.jpg", "rb");
* ok_jpg image = ok_jpg_read(file, OK_JPG_COLOR_FORMAT_RGBA);
* fclose(file);
* if (image.data) {
* printf("Got image! Size: %li x %li\n", (long)image.width, (long)image.height);
* free(image.data);
* }
* return 0;
* }
*/
#include <stdbool.h>
#include <stdint.h>
#ifndef OK_NO_STDIO
#include <stdio.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
OK_JPG_SUCCESS = 0,
OK_JPG_ERROR_API, // Invalid argument sent to public API function
OK_JPG_ERROR_INVALID, // Not a valid JPG file
OK_JPG_ERROR_UNSUPPORTED, // Unsupported JPG file (CMYK)
OK_JPG_ERROR_ALLOCATION, // Couldn't allocate memory
OK_JPG_ERROR_IO, // Couldn't read or seek the file
} ok_jpg_error;
/**
* The data returned from #ok_jpg_read() .
*/
typedef struct {
uint32_t width;
uint32_t height;
uint32_t stride;
uint8_t bpp; // Always 4
ok_jpg_error error_code:24;
uint8_t *data;
} ok_jpg;
/**
* JPG decode flags. Use `OK_JPG_COLOR_FORMAT_RGBA` for the most cases.
*/
typedef enum {
/// Set for RGBA color format. The alpha is always 255.
OK_JPG_COLOR_FORMAT_RGBA = (0 << 0),
/// Set for BGRA color format. The alpha is always 255.
OK_JPG_COLOR_FORMAT_BGRA = (1 << 0),
/// Set to flip the image data along the horizontal axis, so that the first row of data is
/// the last row in the image.
OK_JPG_FLIP_Y = (1 << 2),
/// Set to read an image's dimensions and color format without reading the image data.
OK_JPG_INFO_ONLY = (1 << 3)
} ok_jpg_decode_flags;
// MARK: Reading from a FILE
#if !defined(OK_NO_STDIO) && !defined(OK_NO_DEFAULT_ALLOCATOR)
/**
* Reads a JPEG image using the default "stdlib" allocator.
* On success, #ok_jpg.data contains the packed image data, with a size of
* (`width * height * 4`). On failure, #ok_jpg.data is `NULL` and #ok_jpg.error_code is nonzero.
*
* The returned `data` must be freed by the caller (using stdlib's `free()`).
*
* @param file The file to read.
* @param decode_flags The JPG decode flags. Use `OK_JPG_COLOR_FORMAT_RGBA` for the most cases.
* @return a #ok_jpg object.
*/
ok_jpg ok_jpg_read(FILE *file, ok_jpg_decode_flags decode_flags);
#endif
// MARK: Reading from a FILE, using a custom allocator
typedef struct {
/**
* Allocates uninitilized memory.
*
* @param user_data The pointer passed to #ok_jpg_read_with_allocator.
* @param size The size of the memory to allocate.
* @return the pointer to the newly allocated memory, or `NULL` if the memory could not be allocated.
*/
void *(*alloc)(void *user_data, size_t size);
/**
* Frees memory previously allocated with `alloc`.
*
* @param user_data The pointer passed to #ok_jpg_read_with_allocator.
* @param memory The memory to free.
*/
void (*free)(void *user_data, void *memory);
/**
* Allocates memory for the decoded image.
* This function may be `NULL`, in which case `alloc` is used instead.
*
* @param user_data The pointer passed to #ok_jpg_read_with_allocator.
* @param width The image's width, in pixels.
* @param height The image's height, in pixels.
* @param bpp The image's number of bytes per pixel.
* @param out_buffer The buffer to output data. The buffer must have a minimum size of
* (`out_stride * height`) bytes. Set to `NULL` if the memory could not be allocated.
* @param out_stride The stride of the buffer, in bytes.
* By default, `out_stride` is `width * bpp`, but can be changed if needed.
* The value must be greater than or equal to `width * bpp` or an error will occur.
*/
void (*image_alloc)(void *user_data, uint32_t width, uint32_t height, uint8_t bpp,
uint8_t **out_buffer, uint32_t *out_stride);
} ok_jpg_allocator;
#if !defined(OK_NO_DEFAULT_ALLOCATOR)
/// The default allocator using stdlib's `malloc` and `free`.
extern const ok_jpg_allocator OK_JPG_DEFAULT_ALLOCATOR;
#endif
#if !defined(OK_NO_STDIO)
/**
* Reads a JPG image using a custom allocator.
* On success, #ok_jpg.data contains the packed image data, with a size of
* (`width * height * 4`). On failure, #ok_jpg.data is `NULL` and #ok_jpg.error_code is nonzero.
*
* The returned `data` must be freed by the caller.
*
* @param file The file to read.
* @param decode_flags The JPG decode flags. Use `OK_JPG_COLOR_FORMAT_RGBA` for the most cases.
* @param allocator The allocator to use.
* @param allocator_user_data The pointer to pass to the allocator functions.
* If using `OK_JPG_DEFAULT_ALLOCATOR`, this value should be `NULL`.
* @return a #ok_jpg object.
*/
ok_jpg ok_jpg_read_with_allocator(FILE *file, ok_jpg_decode_flags decode_flags,
ok_jpg_allocator allocator, void *allocator_user_data);
#endif
// MARK: Reading from custom input
typedef struct {
/**
* Reads bytes from its source (typically `user_data`), copying the data to `buffer`.
*
* @param user_data The parameter that was passed to the #ok_jpg_read_from_input()
* @param buffer The data buffer to copy bytes to.
* @param count The number of bytes to read.
* @return The number of bytes read.
*/
size_t (*read)(void *user_data, uint8_t *buffer, size_t count);
/**
* Skips bytes from its source (typically `user_data`).
*
* @param user_data The parameter that was passed to the #ok_jpg_read_from_input().
* @param count The number of bytes to skip.
* @return `true` if success.
*/
bool (*seek)(void *user_data, long count);
} ok_jpg_input;
/**
* Reads a JPG image. On success, #ok_jpg.data contains the packed image data, with a size of
* (`width * height * 4`). On failure, #ok_jpg.data is `NULL` and #ok_jpg.error_code is nonzero.
*
* The returned `data` must be freed by the caller.
*
* @param decode_flags The JPG decode flags. Use `OK_JPG_COLOR_FORMAT_RGBA` for the most cases.
* @param input_callbacks The custom input functions.
* @param input_callbacks_user_data The parameter to be passed to the input's `read` and `seek` functions.
* @param allocator The allocator to use.
* @param allocator_user_data The pointer to pass to the allocator functions.
* If using `OK_JPG_DEFAULT_ALLOCATOR`, this value should be `NULL`.
* @return a #ok_jpg object.
*/
ok_jpg ok_jpg_read_from_input(ok_jpg_decode_flags decode_flags,
ok_jpg_input input_callbacks, void *input_callbacks_user_data,
ok_jpg_allocator allocator, void *allocator_user_data);
#ifdef __cplusplus
}
#endif
#endif