-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathjpeg.c
114 lines (103 loc) · 3.2 KB
/
jpeg.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
#include "jpeg.h"
#include <stdio.h>
char writejpeg(FILE *outfile, struct jpeg_stuff *src) {
struct jpeg_decompress_struct *injpeg = &src->cinfo;
jvirt_barray_ptr *src_coeffs = src->src_coeffs;
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
jpeg_copy_critical_parameters(injpeg, &cinfo);
if (jerr.num_warnings != 0) {
return -1;
}
cinfo.optimize_coding = TRUE;
jpeg_stdio_dest(&cinfo, outfile);
if (jerr.num_warnings != 0) {
return -1;
}
jpeg_write_coefficients(&cinfo, src_coeffs);
if (jerr.num_warnings != 0) {
return -1;
}
jpeg_finish_compress(&cinfo);
if (jerr.num_warnings != 0) {
return -1;
}
return 0;
}
char readjpeg(FILE *infile, struct jpeg_stuff *dest) {
struct jpeg_decompress_struct *cinfo = &dest->cinfo;
cinfo->err = jpeg_std_error(&dest->jerr);
jpeg_create_decompress(cinfo);
jpeg_stdio_src(cinfo, infile);
if (cinfo->err->num_warnings != 0) {
return -1;
}
char magic[2];
size_t len = fread(&magic, 1, 2, infile);
if (len != (size_t) 2 || magic[0] != (char)0xff || magic[1] != (char)0xd8) {
return -1;
}
fseek(infile, 0, SEEK_SET);
int header_status = jpeg_read_header(cinfo, FALSE);
if (header_status != JPEG_HEADER_OK || cinfo->err->num_warnings != 0) {
return -1;
}
jpeg_core_output_dimensions(cinfo);
if (cinfo->err->num_warnings != 0) {
return -1;
}
jvirt_barray_ptr *coeffs = jpeg_read_coefficients(cinfo);
if (cinfo->err->num_warnings != 0) {
return -1;
}
dest->src_coeffs = coeffs;
return 0;
}
void closejpeg(struct jpeg_stuff *src) {
jpeg_finish_decompress(&src->cinfo);
jpeg_destroy_decompress(&src->cinfo);
// should dispose of associated block arrays
}
char check_block_coords(struct jpeg_stuff *stuff, int x, int y, int comp) {
struct jpeg_decompress_struct *cinfo = &stuff->cinfo;
if (comp < 0 || comp > cinfo->num_components) {
return -1;
}
jpeg_component_info *ji = cinfo->comp_info + comp;
if (y < 0 || ((unsigned int) y) >= ji->height_in_blocks) {
return -1;
}
if (x < 0 || ((unsigned int) x) >= ji->width_in_blocks) {
return -1;
}
return 0;
}
JBLOCKARRAY get_coeff_barray_rows_internal(struct jpeg_stuff *stuff, int y, int comp, unsigned int rowcount) {
struct jpeg_decompress_struct *cinfo = &stuff->cinfo;
return cinfo->mem->access_virt_barray((j_common_ptr)cinfo,
stuff->src_coeffs[comp], y, rowcount, TRUE);
}
JBLOCKARRAY get_coeff_barray_rows(struct jpeg_stuff *stuff, int y, int comp, unsigned int rowcount) {
if (check_block_coords(stuff, 0, y, comp) != 0) {
return NULL;
}
if (y + rowcount > stuff->cinfo.comp_info[comp].height_in_blocks) {
return NULL;
}
return get_coeff_barray_rows_internal(stuff, y, comp, rowcount);
}
JCOEFPTR get_coeff_block(struct jpeg_stuff *stuff, int x, int y, int comp) {
if (check_block_coords(stuff, x, y, comp) != 0) {
return NULL;
}
jpeg_component_info *ji = stuff->cinfo.comp_info + comp;
int rowindex = y % ji->v_samp_factor;
int row = y - rowindex;
JBLOCKARRAY jb = get_coeff_barray_rows_internal(stuff, row, comp, ji->v_samp_factor);
if (jb == NULL) {
return NULL;
}
return jb[rowindex][x];
}