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
#define OPJ_STATIC
4
#include 
5
 
6
static void fz_opj_error_callback(const char *msg, void *client_data)
7
{
8
	fprintf(stderr, "openjpeg error: %s", msg);
9
}
10
 
11
static void fz_opj_warning_callback(const char *msg, void *client_data)
12
{
13
	fprintf(stderr, "openjpeg warning: %s", msg);
14
}
15
 
16
static void fz_opj_info_callback(const char *msg, void *client_data)
17
{
18
	/* fprintf(stderr, "openjpeg info: %s", msg); */
19
}
20
 
21
fz_error
22
fz_load_jpx_image(fz_pixmap **imgp, unsigned char *data, int size, fz_colorspace *defcs)
23
{
24
	fz_pixmap *img;
25
	opj_event_mgr_t evtmgr;
26
	opj_dparameters_t params;
27
	opj_dinfo_t *info;
28
	opj_cio_t *cio;
29
	opj_image_t *jpx;
30
	fz_colorspace *colorspace;
31
	unsigned char *p;
32
	int format;
33
	int a, n, w, h, depth, sgnd;
34
	int x, y, k, v;
35
 
36
	if (size < 2)
37
		return fz_throw("not enough data to determine image format");
38
 
39
	/* Check for SOC marker -- if found we have a bare J2K stream */
40
	if (data[0] == 0xFF && data[1] == 0x4F)
41
		format = CODEC_J2K;
42
	else
43
		format = CODEC_JP2;
44
 
45
	memset(&evtmgr, 0, sizeof(evtmgr));
46
	evtmgr.error_handler = fz_opj_error_callback;
47
	evtmgr.warning_handler = fz_opj_warning_callback;
48
	evtmgr.info_handler = fz_opj_info_callback;
49
 
50
	opj_set_default_decoder_parameters(¶ms);
51
 
52
	info = opj_create_decompress(format);
53
	opj_set_event_mgr((opj_common_ptr)info, &evtmgr, stderr);
54
	opj_setup_decoder(info, ¶ms);
55
 
56
	cio = opj_cio_open((opj_common_ptr)info, data, size);
57
 
58
	jpx = opj_decode(info, cio);
59
 
60
	opj_cio_close(cio);
61
	opj_destroy_decompress(info);
62
 
63
	if (!jpx)
64
		return fz_throw("opj_decode failed");
65
 
66
	for (k = 1; k < jpx->numcomps; k++)
67
	{
68
		if (jpx->comps[k].w != jpx->comps[0].w)
69
			return fz_throw("image components have different width");
70
		if (jpx->comps[k].h != jpx->comps[0].h)
71
			return fz_throw("image components have different height");
72
		if (jpx->comps[k].prec != jpx->comps[0].prec)
73
			return fz_throw("image components have different precision");
74
	}
75
 
76
	n = jpx->numcomps;
77
	w = jpx->comps[0].w;
78
	h = jpx->comps[0].h;
79
	depth = jpx->comps[0].prec;
80
	sgnd = jpx->comps[0].sgnd;
81
 
82
	if (jpx->color_space == CLRSPC_SRGB && n == 4) { n = 3; a = 1; }
83
	else if (jpx->color_space == CLRSPC_SYCC && n == 4) { n = 3; a = 1; }
84
	else if (n == 2) { n = 1; a = 1; }
85
	else if (n > 4) { n = 4; a = 1; }
86
	else { a = 0; }
87
 
88
	if (defcs)
89
	{
90
		if (defcs->n == n)
91
		{
92
			colorspace = defcs;
93
		}
94
		else
95
		{
96
			fz_warn("jpx file and dict colorspaces do not match");
97
			defcs = NULL;
98
		}
99
	}
100
 
101
	if (!defcs)
102
	{
103
		switch (n)
104
		{
105
		case 1: colorspace = fz_device_gray; break;
106
		case 3: colorspace = fz_device_rgb; break;
107
		case 4: colorspace = fz_device_cmyk; break;
108
		}
109
	}
110
 
111
	img = fz_new_pixmap_with_limit(colorspace, w, h);
112
	if (!img)
113
	{
114
		opj_image_destroy(jpx);
115
		return fz_throw("out of memory");
116
	}
117
 
118
	p = img->samples;
119
	for (y = 0; y < h; y++)
120
	{
121
		for (x = 0; x < w; x++)
122
		{
123
			for (k = 0; k < n + a; k++)
124
			{
125
				v = jpx->comps[k].data[y * w + x];
126
				if (sgnd)
127
					v = v + (1 << (depth - 1));
128
				if (depth > 8)
129
					v = v >> (depth - 8);
130
				*p++ = v;
131
			}
132
			if (!a)
133
				*p++ = 255;
134
		}
135
	}
136
 
137
	if (a)
138
	{
139
		if (n == 4)
140
		{
141
			fz_pixmap *tmp = fz_new_pixmap(fz_device_rgb, w, h);
142
			fz_convert_pixmap(img, tmp);
143
			fz_drop_pixmap(img);
144
			img = tmp;
145
		}
146
		fz_premultiply_pixmap(img);
147
	}
148
 
149
	opj_image_destroy(jpx);
150
 
151
	*imgp = img;
152
	return fz_okay;
153
}