Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4680 right-hear 1
#include "fitz.h"
2
 
3
#include 
4
#include 
5
 
6
typedef struct fz_dctd_s fz_dctd;
7
 
8
struct fz_dctd_s
9
{
10
	fz_stream *chain;
11
	int color_transform;
12
	int init;
13
	int stride;
14
	unsigned char *scanline;
15
	unsigned char *rp, *wp;
16
	struct jpeg_decompress_struct cinfo;
17
	struct jpeg_source_mgr srcmgr;
18
	struct jpeg_error_mgr errmgr;
19
	jmp_buf jb;
20
	char msg[JMSG_LENGTH_MAX];
21
};
22
 
23
static void error_exit(j_common_ptr cinfo)
24
{
25
	fz_dctd *state = cinfo->client_data;
26
	cinfo->err->format_message(cinfo, state->msg);
27
	longjmp(state->jb, 1);
28
}
29
 
30
static void init_source(j_decompress_ptr cinfo)
31
{
32
	/* nothing to do */
33
}
34
 
35
static void term_source(j_decompress_ptr cinfo)
36
{
37
	/* nothing to do */
38
}
39
 
40
static boolean fill_input_buffer(j_decompress_ptr cinfo)
41
{
42
	struct jpeg_source_mgr *src = cinfo->src;
43
	fz_dctd *state = cinfo->client_data;
44
	fz_stream *chain = state->chain;
45
 
46
	chain->rp = chain->wp;
47
	fz_fill_buffer(chain);
48
	src->next_input_byte = chain->rp;
49
	src->bytes_in_buffer = chain->wp - chain->rp;
50
 
51
	if (src->bytes_in_buffer == 0)
52
	{
53
		static unsigned char eoi[2] = { 0xFF, JPEG_EOI };
54
		fz_warn("premature end of file in jpeg");
55
		src->next_input_byte = eoi;
56
		src->bytes_in_buffer = 2;
57
	}
58
 
59
	return 1;
60
}
61
 
62
static void skip_input_data(j_decompress_ptr cinfo, long num_bytes)
63
{
64
	struct jpeg_source_mgr *src = cinfo->src;
65
	if (num_bytes > 0)
66
	{
67
		while ((size_t)num_bytes > src->bytes_in_buffer)
68
		{
69
			num_bytes -= src->bytes_in_buffer;
70
			(void) src->fill_input_buffer(cinfo);
71
		}
72
		src->next_input_byte += num_bytes;
73
		src->bytes_in_buffer -= num_bytes;
74
	}
75
}
76
 
77
static int
78
read_dctd(fz_stream *stm, unsigned char *buf, int len)
79
{
80
	fz_dctd *state = stm->state;
81
	j_decompress_ptr cinfo = &state->cinfo;
82
	unsigned char *p = buf;
83
	unsigned char *ep = buf + len;
84
 
85
	if (setjmp(state->jb))
86
	{
87
		if (cinfo->src)
88
			state->chain->rp = state->chain->wp - cinfo->src->bytes_in_buffer;
89
		return fz_throw("jpeg error: %s", state->msg);
90
	}
91
 
92
	if (!state->init)
93
	{
94
		cinfo->client_data = state;
95
		cinfo->err = &state->errmgr;
96
		jpeg_std_error(cinfo->err);
97
		cinfo->err->error_exit = error_exit;
98
		jpeg_create_decompress(cinfo);
99
 
100
		cinfo->src = &state->srcmgr;
101
		cinfo->src->init_source = init_source;
102
		cinfo->src->fill_input_buffer = fill_input_buffer;
103
		cinfo->src->skip_input_data = skip_input_data;
104
		cinfo->src->resync_to_restart = jpeg_resync_to_restart;
105
		cinfo->src->term_source = term_source;
106
		cinfo->src->next_input_byte = state->chain->rp;
107
		cinfo->src->bytes_in_buffer = state->chain->wp - state->chain->rp;
108
 
109
		jpeg_read_header(cinfo, 1);
110
 
111
		/* speed up jpeg decoding a bit */
112
		cinfo->dct_method = JDCT_FASTEST;
113
		cinfo->do_fancy_upsampling = FALSE;
114
 
115
		/* default value if ColorTransform is not set */
116
		if (state->color_transform == -1)
117
		{
118
			if (state->cinfo.num_components == 3)
119
				state->color_transform = 1;
120
			else
121
				state->color_transform = 0;
122
		}
123
 
124
		if (cinfo->saw_Adobe_marker)
125
			state->color_transform = cinfo->Adobe_transform;
126
 
127
		/* Guess the input colorspace, and set output colorspace accordingly */
128
		switch (cinfo->num_components)
129
		{
130
		case 3:
131
			if (state->color_transform)
132
				cinfo->jpeg_color_space = JCS_YCbCr;
133
			else
134
				cinfo->jpeg_color_space = JCS_RGB;
135
			break;
136
		case 4:
137
			if (state->color_transform)
138
				cinfo->jpeg_color_space = JCS_YCCK;
139
			else
140
				cinfo->jpeg_color_space = JCS_CMYK;
141
			break;
142
		}
143
 
144
		jpeg_start_decompress(cinfo);
145
 
146
		state->stride = cinfo->output_width * cinfo->output_components;
147
		state->scanline = fz_malloc(state->stride);
148
		state->rp = state->scanline;
149
		state->wp = state->scanline;
150
 
151
		state->init = 1;
152
	}
153
 
154
	while (state->rp < state->wp && p < ep)
155
		*p++ = *state->rp++;
156
 
157
	while (p < ep)
158
	{
159
		if (cinfo->output_scanline == cinfo->output_height)
160
			break;
161
 
162
		if (p + state->stride <= ep)
163
		{
164
			jpeg_read_scanlines(cinfo, &p, 1);
165
			p += state->stride;
166
		}
167
		else
168
		{
169
			jpeg_read_scanlines(cinfo, &state->scanline, 1);
170
			state->rp = state->scanline;
171
			state->wp = state->scanline + state->stride;
172
		}
173
 
174
		while (state->rp < state->wp && p < ep)
175
			*p++ = *state->rp++;
176
	}
177
 
178
	return p - buf;
179
}
180
 
181
static void
182
close_dctd(fz_stream *stm)
183
{
184
	fz_dctd *state = stm->state;
185
 
186
	if (setjmp(state->jb))
187
	{
188
		state->chain->rp = state->chain->wp - state->cinfo.src->bytes_in_buffer;
189
		fz_warn("jpeg error: %s", state->msg);
190
		goto skip;
191
	}
192
 
193
	if (state->init)
194
		jpeg_finish_decompress(&state->cinfo);
195
 
196
skip:
197
	state->chain->rp = state->chain->wp - state->cinfo.src->bytes_in_buffer;
198
	jpeg_destroy_decompress(&state->cinfo);
199
	fz_free(state->scanline);
200
	fz_close(state->chain);
201
	fz_free(state);
202
}
203
 
204
fz_stream *
205
fz_open_dctd(fz_stream *chain, fz_obj *params)
206
{
207
	fz_dctd *state;
208
	fz_obj *obj;
209
 
210
	state = fz_malloc(sizeof(fz_dctd));
211
	memset(state, 0, sizeof(fz_dctd));
212
	state->chain = chain;
213
	state->color_transform = -1; /* unset */
214
	state->init = 0;
215
 
216
	obj = fz_dict_gets(params, "ColorTransform");
217
	if (obj)
218
		state->color_transform = fz_to_int(obj);
219
 
220
	return fz_new_stream(state, read_dctd, close_dctd);
221
}