-
Notifications
You must be signed in to change notification settings - Fork 1
/
ujpeg.h
196 lines (169 loc) · 8.81 KB
/
ujpeg.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
// uJPEG (MicroJPEG) -- KeyJ's Small Baseline JPEG Decoder
// based on NanoJPEG -- KeyJ's Tiny Baseline JPEG Decoder
// version 1.3.5 (2016-11-14)
// Copyright (c) 2009-2016 Martin J. Fiedler <martin.fiedler@gmx.net>
// published under the terms of the MIT license
//
// 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.
//
////////////////////////////////////////////////////////////////////////////////
//
// This is a minimal decoder for baseline JPEG images. It accepts JPEG files as
// input and generates either 8-bit grayscale or packed 24-bit RGB images as
// output. It does not fully parse JFIF or Exif headers; all JPEG files
// are assumed to be either grayscale or YCbCr. CMYK or other color spaces are
// not supported. All YCbCr subsampling schemes with power-of-two ratios are
// supported, as are restart intervals. Progressive or lossless JPEG is not
// supported.
// Summed up, uJPEG should be able to decode all images from digital cameras
// and most common forms of other non-progressive JPEG images.
//
// The decoder is not optimized for speed, it's optimized for simplicity and
// small code. Image quality should be at a reasonable level. A bicubic chroma
// upsampling filter ensures that subsampled YCbCr images are rendered in
// decent quality. If Exif information is present, uJPEG automatically detects
// whether centered or co-sited chroma sample positioning is used.
//
// The decoder offers only a minimal amount of error resilience. If anything is
// wrong with the image's headers, it will reject the complete image. If
// there's an error within the coefficient bitstream, the decoder will stop
// decoding at the error position and leave the remainder of the image gray.
//
// The code should work with every modern C compiler without problems and
// should not emit any warnings. It uses only (at least) 32-bit integer
// arithmetic and is supposed to be endianness independent, 64-bit clean and
// thread-safe. It uses no external libraries except the C runtime (libc).
#include "pch.h"
#ifndef _UJPEG_H_
#define _UJPEG_H_
// result codes for ujDecode()
typedef enum _uj_result {
UJ_OK = 0, // no error, decoding successful
UJ_NO_CONTEXT = 1, // called uj* function without image handle
UJ_NOT_DECODED = 2, // image has not yet been decoded
UJ_INVALID_ARG = 3, // invalid argument
UJ_IO_ERROR = 4, // file I/O error
UJ_OUT_OF_MEM = 5, // out of memory
UJ_NO_JPEG = 6, // not a JPEG file
UJ_UNSUPPORTED = 7, // unsupported format
UJ_SYNTAX_ERROR = 8, // syntax error
UJ_INTERNAL_ERR = 9, // internal error
__UJ_FINISHED // used internally, will never be reported
} ujResult;
// plane (color component) structure
typedef struct _uj_plane {
int width; // visible width
int height; // visible height
int stride; // line size in bytes
unsigned char* pixels; // pixel data
} ujPlane;
////////////////////////////////////////////////////////////////////////////////
// C INTERFACE //
////////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
extern "C" {
#endif
// data type for uJPEG image handles
typedef void* ujImage;
// return the error code of the last uJPEG operation
extern ujResult ujGetError(void);
// create a uJPEG image context
extern ujImage ujCreate(void);
// tell the context not to decode image data (only parse headers)
extern void ujDisableDecoding(ujImage img);
// tell the context whether which chroma upsampling mode to use
#define UJ_CHROMA_MODE_FAST 1 // low-quality pixel repetition (fast)
#define UJ_CHROMA_MODE_ACCURATE 0 // accurate bicubic upsampling (slower)
#define UJ_CHROMA_MODE_DEFAULT 0 // default mode: accurate
extern void ujSetChromaMode(ujImage img, int mode);
// decode a JPEG image from memory
// img: the handle to the uJPEG image to decode to;
// if it is NULL, a new instance will be created
// jpeg: a pointer to the JPEG image file in memory
// size: the size of the JPEG image file in memory
// returns the image handle on success or NULL on failure; use ujGetError to
// get a more detailed error description
extern ujImage ujDecode(ujImage img, const void* jpeg, const int size, bool mapx);
// decode a JPEG image from a file
// img: the handle to the uJPEG image to decode to;
// if it is NULL, a new instance will be created
// filename: the name of the file to load
// returns the image handle on success or NULL on failure; use ujGetError to
// get a more detailed error description
extern ujImage ujDecodeFile(ujImage img, const char* filename);
// determine whether a picture has been successfully decoded
extern int ujIsValid(ujImage img);
// determine the dimensions of a decoded picture
extern int ujGetWidth(ujImage img);
extern int ujGetHeight(ujImage img);
// determine whether a decoded picture is grayscale (0) or color (1)
extern int ujIsColor(ujImage img);
// determine the amount of memory required to hold a decoded and converted
// picture
extern int ujGetImageSize(ujImage img);
// retrieve a pointer to the internal buffer of a decoded plane
// num is the plane number: 0 = Y (luminance), 1 = Cb, 2 = Cr.
// returns a pointer or NULL in case of failure
extern ujPlane* ujGetPlane(ujImage img, int num);
// retrieve decoded and converted picture
// If called with dest == NULL, uJPEG will create an internal buffer to hold
// the decoded and converted picture and returns the pointer to this buffer.
// If called with dest != NULL, uJPEG will convert the image into a user-
// supplied buffer and return the address of that buffer.
// This function can be called with dest=NULL multiple times without performance
// penalty.
// If conversion failed, this function returns NULL; use ujGetError to get a
// more detailed error description.
extern unsigned char* ujGetImage(ujImage img, unsigned char* dest);
// destroy a uJPEG image handle
extern void ujDestroy(ujImage img);
// destroy a uJPEG image handle and make the handle variable unusable
// (preferred to ujDestroy)
#define ujFree(img) do { ujDestroy(img); img = NULL; } while (0)
#ifdef __cplusplus
}
#endif
////////////////////////////////////////////////////////////////////////////////
// C++ INTERFACE //
////////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
class uJPEG {
public:
uJPEG() { img = ujCreate(); }
virtual ~uJPEG() { ujFree(img); }
static ujResult getError() { return ujGetError(); }
void disableDecoding() { ujDisableDecoding(img); }
void setChromaMode(int mode) { ujSetChromaMode(img, mode); }
bool decode(const void* jpeg, const int size, bool mapx) { return ujDecode(img, jpeg, size, mapx) != NULL; }
bool decodeFile(const char* filename) { return ujDecodeFile(img, filename) != NULL; }
bool isValid() { return (ujIsValid(img) != 0); }
bool good() { return isValid(); }
bool bad() { return !isValid(); }
int getWidth() { return ujGetWidth(img); }
int getHeight() { return ujGetHeight(img); }
bool isColor() { return (ujIsColor(img) != 0); }
int getImageSize() { return ujGetImageSize(img); }
ujPlane* getPlane(int num) { return ujGetPlane(img, num); }
const unsigned char* getImage() { return ujGetImage(img, NULL); }
bool getImage(unsigned char* dest) { return ujGetImage(img, dest) != NULL; }
private:
ujImage img;
};
#endif//__cplusplus
#endif//_UJPEG_H_