1 /* raster.c - main and other misc stuff
3 * Raster graphics library
5 * Copyright (c) 1997-2000 Alfredo K. Kojima
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33 char *WRasterLibVersion
="0.9";
35 int RErrorCode
=RERR_NONE
;
38 #define HAS_ALPHA(I) ((I)->format == RRGBAFormat)
42 RCreateImage(unsigned width
, unsigned height
, int alpha
)
46 assert(width
>0 && height
>0);
48 image
= malloc(sizeof(RImage
));
50 RErrorCode
= RERR_NOMEMORY
;
54 memset(image
, 0, sizeof(RImage
));
56 image
->height
= height
;
58 image
->format
= RRGBAFormat
;
60 image
->format
= RRGBFormat
;
62 /* the +4 is to give extra bytes at the end of the buffer,
63 * so that we can optimize image conversion for MMX(tm).. see convert.c
65 image
->data
= malloc(width
* height
* (alpha
? 4 : 3) + 4);
67 RErrorCode
= RERR_NOMEMORY
;
78 RCloneImage(RImage
*image
)
84 new_image
= RCreateImage(image
->width
, image
->height
, HAS_ALPHA(image
));
88 new_image
->background
= image
->background
;
89 memcpy(new_image
->data
, image
->data
,
90 image
->width
*image
->height
*(HAS_ALPHA(image
) ? 4 : 3));
97 RGetSubImage(RImage
*image
, int x
, int y
, unsigned width
, unsigned height
)
101 unsigned total_line_size
, line_size
;
104 assert(x
>=0 && y
>=0);
105 assert(x
<image
->width
&& y
<image
->height
);
106 assert(width
>0 && height
>0);
108 if (x
+width
> image
->width
)
109 width
= image
->width
-x
;
110 if (y
+height
> image
->height
)
111 height
= image
->height
-y
;
113 new_image
= RCreateImage(width
, height
, HAS_ALPHA(image
));
117 new_image
->background
= image
->background
;
119 total_line_size
= image
->width
* (HAS_ALPHA(image
) ? 4 : 3);
120 line_size
= width
* (HAS_ALPHA(image
) ? 4 : 3);
122 ofs
= x
*(HAS_ALPHA(image
) ? 4 : 3) + y
*total_line_size
;;
124 for (i
=0; i
<height
; i
++) {
125 memcpy(&new_image
->data
[i
*line_size
],
126 &image
->data
[i
*total_line_size
+ofs
], line_size
);
133 RDestroyImage(RImage
*image
)
143 *----------------------------------------------------------------------
145 * Combines two equal sized images with alpha image. The second
146 * image will be placed on top of the first one.
147 *----------------------------------------------------------------------
150 RCombineImages(RImage
*image
, RImage
*src
)
152 assert(image
->width
== src
->width
);
153 assert(image
->height
== src
->height
);
155 if (!HAS_ALPHA(src
)) {
156 if (!HAS_ALPHA(image
)) {
157 memcpy(image
->data
, src
->data
, image
->height
*image
->width
*3);
160 unsigned char *d
, *s
;
164 for (y
= 0; y
< image
->height
; y
++) {
165 for (x
= 0; x
< image
->width
; x
++) {
182 if (!HAS_ALPHA(image
)) {
183 for (i
=0; i
<image
->height
*image
->width
; i
++) {
185 calpha
= 255 - alpha
;
186 *d
= (((int)*d
* calpha
) + ((int)*s
* alpha
))/256;
188 *d
= (((int)*d
* calpha
) + ((int)*s
* alpha
))/256;
190 *d
= (((int)*d
* calpha
) + ((int)*s
* alpha
))/256;
195 for (i
=0; i
<image
->height
*image
->width
; i
++) {
197 calpha
= 255 - alpha
;
198 *d
= (((int)*d
* calpha
) + ((int)*s
* alpha
))/256;
200 *d
= (((int)*d
* calpha
) + ((int)*s
* alpha
))/256;
202 *d
= (((int)*d
* calpha
) + ((int)*s
* alpha
))/256;
214 RCombineImagesWithOpaqueness(RImage
*image
, RImage
*src
, int opaqueness
)
221 assert(image
->width
== src
->width
);
222 assert(image
->height
== src
->height
);
227 c_opaqueness
= 255 - opaqueness
;
228 #define OP opaqueness
229 if (!HAS_ALPHA(src
)) {
230 int dalpha
= HAS_ALPHA(image
);
231 #define COP c_opaqueness
232 for (i
=0; i
< image
->width
*image
->height
; i
++) {
233 *d
= (((int)*d
*(int)COP
) + ((int)*s
*(int)OP
))/256;
235 *d
= (((int)*d
*(int)COP
) + ((int)*s
*(int)OP
))/256;
237 *d
= (((int)*d
*(int)COP
) + ((int)*s
*(int)OP
))/256;
247 if (!HAS_ALPHA(image
)) {
248 for (i
=0; i
<image
->width
*image
->height
; i
++) {
249 tmp
= (*(s
+3) * opaqueness
)/256;
250 *d
= (((int)*d
* (255-tmp
)) + ((int)*s
* tmp
))/256;
252 *d
= (((int)*d
* (255-tmp
)) + ((int)*s
* tmp
))/256;
254 *d
= (((int)*d
* (255-tmp
)) + ((int)*s
* tmp
))/256;
259 for (i
=0; i
<image
->width
*image
->height
; i
++) {
260 tmp
= (*(s
+3) * opaqueness
)/256;
261 *d
= (((int)*d
* (255-tmp
)) + ((int)*s
* tmp
))/256;
263 *d
= (((int)*d
* (255-tmp
)) + ((int)*s
* tmp
))/256;
265 *d
= (((int)*d
* (255-tmp
)) + ((int)*s
* tmp
))/256;
277 RCombineArea(RImage
*image
, RImage
*src
, int sx
, int sy
, unsigned width
,
278 unsigned height
, int dx
, int dy
)
286 assert(dy
< image
->height
);
287 assert(dx
< image
->width
);
289 assert(sy
+ height
<= src
->height
);
290 assert(sx
+ width
<= src
->width
);
293 if (height
> image
->height
- dy
)
294 height
= image
->height
- dy
;
296 if (!HAS_ALPHA(src
)) {
297 if (!HAS_ALPHA(image
)) {
298 swi
= (src
->width
- width
) * 3;
299 dwi
= (image
->width
- width
) * 3;
301 d
= image
->data
+ dy
*(int)image
->width
*3 + dx
;
302 s
= src
->data
+ sy
*(int)src
->width
*3 + sx
;
304 for (y
=0; y
< height
; y
++) {
305 memcpy(d
, s
, width
*3);
310 swi
= (src
->width
- width
) * 3;
311 dwi
= (image
->width
- width
) * 4;
313 d
= image
->data
+ dy
*(int)image
->width
*4 + dx
;
314 s
= src
->data
+ sy
*(int)src
->width
*3 + sx
;
316 for (y
=0; y
< height
; y
++) {
317 for (x
=0; x
< width
; x
++) {
328 int dalpha
= HAS_ALPHA(image
);
330 swi
= (src
->width
- width
) * 4;
331 s
= src
->data
+ sy
*(int)src
->width
*4 + sx
;
332 if (!HAS_ALPHA(image
)) {
333 dwi
= (image
->width
- width
) * 3;
334 d
= image
->data
+ (dy
*(int)image
->width
+dx
)*3;
336 dwi
= (image
->width
- width
) * 4;
337 d
= image
->data
+ (dy
*(int)image
->width
+dx
)*4;
340 for (y
=0; y
< height
; y
++) {
341 for (x
=0; x
< width
; x
++) {
343 calpha
= 255 - alpha
;
344 *d
= (((int)*d
* calpha
) + ((int)*s
* alpha
))/256;
346 *d
= (((int)*d
* calpha
) + ((int)*s
* alpha
))/256;
348 *d
= (((int)*d
* calpha
) + ((int)*s
* alpha
))/256;
362 RCombineAreaWithOpaqueness(RImage
*image
, RImage
*src
, int sx
, int sy
,
363 unsigned width
, unsigned height
, int dx
, int dy
,
370 int dalpha
= HAS_ALPHA(image
);
371 int dch
= (dalpha
? 4 : 3);
373 assert(dy
<= image
->height
);
374 assert(dx
<= image
->width
);
376 assert(sy
<= height
);
384 if (height
> image
->height
- dy
)
385 height
= image
->height
- dy
;
387 d
= image
->data
+ dy
*image
->width
*dch
+ dx
;
388 dwi
= (image
->width
- width
)*dch
;
390 c_opaqueness
= 255 - opaqueness
;
391 #define OP opaqueness
392 if (!HAS_ALPHA(src
)) {
393 #define COP c_opaqueness
395 s
= src
->data
+ sy
*src
->width
*3;
396 swi
= (src
->width
- width
) * 3;
398 for (y
=0; y
< height
; y
++) {
399 for (x
=0; x
< width
; x
++) {
400 *d
= (((int)*d
*(int)COP
) + ((int)*s
*(int)OP
))/256;
402 *d
= (((int)*d
*(int)COP
) + ((int)*s
*(int)OP
))/256;
404 *d
= (((int)*d
*(int)COP
) + ((int)*s
*(int)OP
))/256;
415 s
= src
->data
+ sy
*src
->width
*4;
416 swi
= (src
->width
- width
) * 4;
418 for (y
=0; y
< height
; y
++) {
419 for (x
=0; x
< width
; x
++) {
420 tmp
= (*(s
+3) * opaqueness
)/256;
421 *d
= (((int)*d
*(int)(255-tmp
)) + ((int)*s
*(int)tmp
))/256;
423 *d
= (((int)*d
*(int)(255-tmp
)) + ((int)*s
*(int)tmp
))/256;
425 *d
= (((int)*d
*(int)(255-tmp
)) + ((int)*s
*(int)tmp
))/256;
441 RCombineImageWithColor(RImage
*image
, RColor
*color
)
445 int alpha
, nalpha
, r
, g
, b
;
449 if (!HAS_ALPHA(image
)) {
450 /* Image has no alpha channel, so we consider it to be all 255.
451 * Thus there are no transparent parts to be filled. */
458 for (i
=0; i
< image
->width
*image
->height
; i
++) {
460 nalpha
= 255 - alpha
;
462 *d
= (((int)*d
* alpha
) + (r
* nalpha
))/256;
464 *d
= (((int)*d
* alpha
) + (g
* nalpha
))/256;
466 *d
= (((int)*d
* alpha
) + (b
* nalpha
))/256;
476 RMakeTiledImage(RImage
*tile
, unsigned width
, unsigned height
)
480 unsigned long tile_size
= tile
->width
* tile
->height
;
481 unsigned long tx
= 0;
483 unsigned char *s
, *d
;
485 if (width
== tile
->width
&& height
== tile
->height
)
486 image
= RCloneImage(tile
);
487 else if (width
<= tile
->width
&& height
<= tile
->height
)
488 image
= RGetSubImage(tile
, 0, 0, width
, height
);
490 int has_alpha
= HAS_ALPHA(tile
);
492 image
= RCreateImage(width
, height
, has_alpha
);
497 for (y
= 0; y
< height
; y
++) {
498 for (x
= 0; x
< width
; x
+= tile
->width
) {
500 w
= (width
- x
< tile
->width
) ? width
- x
: tile
->width
;
504 memcpy(d
, s
+tx
*4, w
);
507 memcpy(d
, s
+tx
*3, w
);
512 tx
= (tx
+ tile
->width
) % tile_size
;
520 RMakeCenteredImage(RImage
*image
, unsigned width
, unsigned height
, RColor
*color
)
522 int x
, y
, w
, h
, sx
, sy
;
525 tmp
= RCreateImage(width
, height
, False
);
530 RClearImage(tmp
, color
);
532 if (image
->height
< height
) {
537 sy
= (image
->height
- height
)/2;
541 if (image
->width
< width
) {
546 sx
= (image
->width
- width
)/2;
550 RCombineArea(tmp
, image
, sx
, sy
, w
, h
, x
, y
);