Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
8619 maxcodehac 1
/*
2
    jbig2dec
3
 
4
    Copyright (C) 2001-2005 Artifex Software, Inc.
5
 
6
    This software is distributed under license and may not
7
    be copied, modified or distributed except as expressly
8
    authorized under the terms of the license contained in
9
    the file LICENSE in this distribution.
10
 
11
    For further licensing information refer to http://artifex.com/ or
12
    contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
13
    San Rafael, CA  94903, U.S.A., +1(415)492-9861.
14
*/
15
 
16
#ifdef HAVE_CONFIG_H
17
#include "config.h"
18
#endif
19
#include "os_types.h"
20
 
21
#include 
22
#include 
23
#include  /* memcpy() */
24
 
25
#include "jbig2.h"
26
#include "jbig2_priv.h"
27
#include "jbig2_image.h"
28
 
29
 
30
/* allocate a Jbig2Image structure and its associated bitmap */
31
Jbig2Image* jbig2_image_new(Jbig2Ctx *ctx, int width, int height)
32
{
33
	Jbig2Image	*image;
34
	int		stride;
35
 
36
	image = (Jbig2Image *)jbig2_alloc(ctx->allocator, sizeof(*image));
37
	if (image == NULL) {
38
		jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
39
			       "could not allocate image structure");
40
		return NULL;
41
	}
42
 
43
	stride = ((width - 1) >> 3) + 1; /* generate a byte-aligned stride */
44
	image->data = (uint8_t *)jbig2_alloc(ctx->allocator, stride*height);
45
	if (image->data == NULL) {
46
                jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
47
                    "could not allocate image data buffer! [%d bytes]\n", stride*height);
48
		jbig2_free(ctx->allocator, image);
49
		return NULL;
50
	}
51
 
52
	image->width = width;
53
	image->height = height;
54
	image->stride = stride;
55
	image->refcount = 1;
56
 
57
	return image;
58
}
59
 
60
/* clone an image pointer by bumping its reference count */
61
Jbig2Image* jbig2_image_clone(Jbig2Ctx *ctx, Jbig2Image *image)
62
{
63
	image->refcount++;
64
	return image;
65
}
66
 
67
/* release an image pointer, freeing it it appropriate */
68
void jbig2_image_release(Jbig2Ctx *ctx, Jbig2Image *image)
69
{
70
	image->refcount--;
71
	if (!image->refcount) jbig2_image_free(ctx, image);
72
}
73
 
74
/* free a Jbig2Image structure and its associated memory */
75
void jbig2_image_free(Jbig2Ctx *ctx, Jbig2Image *image)
76
{
77
	jbig2_free(ctx->allocator, image->data);
78
	jbig2_free(ctx->allocator, image);
79
}
80
 
81
/* resize a Jbig2Image */
82
Jbig2Image *jbig2_image_resize(Jbig2Ctx *ctx, Jbig2Image *image,
83
				int width, int height)
84
{
85
	if (width == image->width) {
86
	    /* use the same stride, just change the length */
87
	    image->data = jbig2_realloc(ctx->allocator,
88
                image->data, image->stride*height);
89
            if (image->data == NULL) {
90
                jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
91
                    "could not resize image buffer!");
92
		return NULL;
93
            }
94
	    if (height > image->height) {
95
		memset(image->data + image->height*image->stride,
96
			0, (height - image->height)*image->stride);
97
	    }
98
            image->height = height;
99
 
100
	} else {
101
	    /* we must allocate a new image buffer and copy */
102
	    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1,
103
		"jbig2_image_resize called with a different width (NYI)");
104
	}
105
 
106
	return NULL;
107
}
108
 
109
/* composite one jbig2_image onto another
110
   slow but general version */
111
int jbig2_image_compose_unopt(Jbig2Ctx *ctx,
112
			Jbig2Image *dst, Jbig2Image *src,
113
                        int x, int y, Jbig2ComposeOp op)
114
{
115
    int i, j;
116
    int sw = src->width;
117
    int sh = src->height;
118
    int sx = 0;
119
    int sy = 0;
120
 
121
    /* clip to the dst image boundaries */
122
    if (x < 0) { sx += -x; sw -= -x; x = 0; }
123
    if (y < 0) { sy += -y; sh -= -y; y = 0; }
124
    if (x + sw >= dst->width) sw = dst->width - x;
125
    if (y + sh >= dst->height) sh = dst->height - y;
126
 
127
    switch (op) {
128
	case JBIG2_COMPOSE_OR:
129
	    for (j = 0; j < sh; j++) {
130
		for (i = 0; i < sw; i++) {
131
		    jbig2_image_set_pixel(dst, i+x, j+y,
132
			jbig2_image_get_pixel(src, i+sx, j+sy) |
133
			jbig2_image_get_pixel(dst, i+x, j+y));
134
		}
135
    	    }
136
	    break;
137
	case JBIG2_COMPOSE_AND:
138
	    for (j = 0; j < sh; j++) {
139
		for (i = 0; i < sw; i++) {
140
		    jbig2_image_set_pixel(dst, i+x, j+y,
141
			jbig2_image_get_pixel(src, i+sx, j+sy) &
142
			jbig2_image_get_pixel(dst, i+x, j+y));
143
		}
144
    	    }
145
	    break;
146
	case JBIG2_COMPOSE_XOR:
147
	    for (j = 0; j < sh; j++) {
148
		for (i = 0; i < sw; i++) {
149
		    jbig2_image_set_pixel(dst, i+x, j+y,
150
			jbig2_image_get_pixel(src, i+sx, j+sy) ^
151
			jbig2_image_get_pixel(dst, i+x, j+y));
152
		}
153
    	    }
154
	    break;
155
	case JBIG2_COMPOSE_XNOR:
156
	    for (j = 0; j < sh; j++) {
157
		for (i = 0; i < sw; i++) {
158
		    jbig2_image_set_pixel(dst, i+x, j+y,
159
			~(jbig2_image_get_pixel(src, i+sx, j+sy) ^
160
			jbig2_image_get_pixel(dst, i+x, j+y)));
161
		}
162
    	    }
163
	    break;
164
	case JBIG2_COMPOSE_REPLACE:
165
	    for (j = 0; j < sh; j++) {
166
		for (i = 0; i < sw; i++) {
167
		    jbig2_image_set_pixel(dst, i+x, j+y,
168
			jbig2_image_get_pixel(src, i+sx, j+sy));
169
		}
170
    	    }
171
	    break;
172
    }
173
 
174
    return 0;
175
}
176
 
177
/* composite one jbig2_image onto another */
178
int jbig2_image_compose(Jbig2Ctx *ctx, Jbig2Image *dst, Jbig2Image *src,
179
			int x, int y, Jbig2ComposeOp op)
180
{
181
    int i, j;
182
    int w, h;
183
    int leftbyte, rightbyte;
184
    int shift;
185
    uint8_t *s, *ss;
186
    uint8_t *d, *dd;
187
    uint8_t mask, rightmask;
188
 
189
    if (op != JBIG2_COMPOSE_OR) {
190
	/* hand off the the general routine */
191
	return jbig2_image_compose_unopt(ctx, dst, src, x, y, op);
192
    }
193
 
194
    /* clip */
195
    w = src->width;
196
    h = src->height;
197
    ss = src->data;
198
    /* FIXME: this isn't sufficient for the < 0 cases */
199
    if (x < 0) { w += x; x = 0; }
200
    if (y < 0) { h += y; y = 0; }
201
    w = (x + w < dst->width) ? w : dst->width - x;
202
    h = (y + h < dst->height) ? h : dst->height - y;
203
#ifdef JBIG2_DEBUG
204
    jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1,
205
      "compositing %dx%d at (%d, %d) after clipping\n",
206
        w, h, x, y);
207
#endif
208
 
209
#if 0
210
    /* special case complete/strip replacement */
211
    /* disabled because it's only safe to do when the destination
212
       buffer is all-blank. */
213
    if ((x == 0) && (w == src->width)) {
214
        memcpy(dst->data + y*dst->stride, src->data, h*src->stride);
215
        return 0;
216
    }
217
#endif
218
 
219
    leftbyte = x >> 3;
220
    rightbyte = (x + w - 1) >> 3;
221
    shift = x & 7;
222
 
223
    /* general OR case */
224
    s = ss;
225
    d = dd = dst->data + y*dst->stride + leftbyte;
226
    if (leftbyte == rightbyte) {
227
	mask = 0x100 - (0x100 >> w);
228
        for (j = 0; j < h; j++) {
229
            *d |= (*s & mask) >> shift;
230
            d += dst->stride;
231
            s += src->stride;
232
        }
233
    } else if (shift == 0) {
234
	rightmask = (w & 7) ? 0x100 - (1 << (8 - (w & 7))) : 0xFF;
235
        for (j = 0; j < h; j++) {
236
	    for (i = leftbyte; i < rightbyte; i++)
237
		*d++ |= *s++;
238
	    *d |= *s & rightmask;
239
            d = (dd += dst->stride);
240
            s = (ss += src->stride);
241
	}
242
    } else {
243
	bool overlap = (((w + 7) >> 3) < ((x + w + 7) >> 3) - (x >> 3));
244
	mask = 0x100 - (1 << shift);
245
	if (overlap)
246
	    rightmask = (0x100 - (0x100 >> ((x + w) & 7))) >> (8 - shift);
247
	else
248
	    rightmask = 0x100 - (0x100 >> (w & 7));
249
        for (j = 0; j < h; j++) {
250
	    *d++ |= (*s & mask) >> shift;
251
            for(i = leftbyte; i < rightbyte - 1; i++) {
252
		*d |= ((*s++ & ~mask) << (8 - shift));
253
		*d++ |= ((*s & mask) >> shift);
254
	    }
255
	    if (overlap)
256
		*d |= (*s & rightmask) << (8 - shift);
257
	    else
258
		*d |= ((s[0] & ~mask) << (8 - shift)) |
259
		    ((s[1] & rightmask) >> shift);
260
	    d = (dd += dst->stride);
261
	    s = (ss += src->stride);
262
	}
263
    }
264
 
265
    return 0;
266
}
267
 
268
 
269
/* initialize an image bitmap to a constant value */
270
void jbig2_image_clear(Jbig2Ctx *ctx, Jbig2Image *image, int value)
271
{
272
    const uint8_t fill = value ? 0xFF : 0x00;
273
 
274
    memset(image->data, fill, image->stride*image->height);
275
}
276
 
277
/* look up a pixel value in an image.
278
   returns 0 outside the image frame for the convenience of
279
   the template code
280
*/
281
int jbig2_image_get_pixel(Jbig2Image *image, int x, int y)
282
{
283
  const int w = image->width;
284
  const int h = image->height;
285
  const int byte = (x >> 3) + y*image->stride;
286
  const int bit = 7 - (x & 7);
287
 
288
  if ((x < 0) || (x >= w)) return 0;
289
  if ((y < 0) || (y >= h)) return 0;
290
 
291
  return ((image->data[byte]>>bit) & 1);
292
}
293
 
294
/* set an individual pixel value in an image */
295
int jbig2_image_set_pixel(Jbig2Image *image, int x, int y, bool value)
296
{
297
  const int w = image->width;
298
  const int h = image->height;
299
  int scratch, mask;
300
  int bit, byte;
301
 
302
  if ((x < 0) || (x >= w)) return 0;
303
  if ((y < 0) || (y >= h)) return 0;
304
 
305
  byte = (x >> 3) + y*image->stride;
306
  bit = 7 - (x & 7);
307
  mask = (1 << bit) ^ 0xff;
308
 
309
  scratch = image->data[byte] & mask;
310
  image->data[byte] = scratch | (value << bit);
311
 
312
  return 1;
313
}