1 /* raster.c - main and other misc stuff
3 * Raster graphics library
5 * Copyright (c) 1997 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
;
40 RCreateImage(unsigned width
, unsigned height
, int alpha
)
45 assert(width
>0 && height
>0);
47 image
= malloc(sizeof(RImage
));
49 RErrorCode
= RERR_NOMEMORY
;
53 memset(image
, 0, sizeof(RImage
));
55 image
->height
= height
;
56 for (i
=0; i
<3+(alpha
?1:0); i
++) {
57 image
->data
[i
] = malloc(width
*height
);
70 RErrorCode
= RERR_NOMEMORY
;
77 RCloneImage(RImage
*image
)
83 new_image
= RCreateImage(image
->width
, image
->height
, image
->data
[3]!=NULL
);
87 new_image
->background
= image
->background
;
88 memcpy(new_image
->data
[0], image
->data
[0], image
->width
*image
->height
);
89 memcpy(new_image
->data
[1], image
->data
[1], image
->width
*image
->height
);
90 memcpy(new_image
->data
[2], image
->data
[2], image
->width
*image
->height
);
92 memcpy(new_image
->data
[3], image
->data
[3], image
->width
*image
->height
);
99 RGetSubImage(RImage
*image
, int x
, int y
, unsigned width
, unsigned height
)
103 unsigned char *sr
, *sg
, *sb
, *sa
;
104 unsigned char *dr
, *dg
, *db
, *da
;
107 assert(x
>=0 && y
>=0);
108 assert(x
<image
->width
&& y
<image
->height
);
109 assert(width
>0 && height
>0);
111 if (x
+width
> image
->width
)
112 width
= image
->width
-x
;
113 if (y
+height
> image
->height
)
114 height
= image
->height
-y
;
116 new_image
= RCreateImage(width
, height
, image
->data
[3]!=NULL
);
119 new_image
->background
= image
->background
;
120 ofs
= image
->width
*y
+x
;
122 sr
= image
->data
[0]+ofs
;
123 sg
= image
->data
[1]+ofs
;
124 sb
= image
->data
[2]+ofs
;
125 sa
= image
->data
[3]+ofs
;
127 dr
= new_image
->data
[0];
128 dg
= new_image
->data
[1];
129 db
= new_image
->data
[2];
130 da
= new_image
->data
[3];
132 for (i
=0; i
<height
; i
++) {
133 memcpy(dr
, sr
, width
);
134 memcpy(dg
, sg
, width
);
135 memcpy(db
, sb
, width
);
143 memcpy(da
, sa
, width
);
153 RDestroyImage(RImage
*image
)
159 for (i
=0; i
<4; i
++) {
161 free(image
->data
[i
]);
168 *----------------------------------------------------------------------
170 * Combines two equal sized images with alpha image. The second
171 * image will be placed on top of the first one.
172 *----------------------------------------------------------------------
175 RCombineImages(RImage
*image
, RImage
*src
)
178 unsigned char *dr
, *dg
, *db
, *da
;
179 unsigned char *sr
, *sg
, *sb
, *sa
;
183 assert(image
->width
== src
->width
);
184 assert(image
->height
== src
->height
);
197 memcpy(dr
, sr
, image
->height
*image
->width
);
198 memcpy(dg
, sg
, image
->height
*image
->width
);
199 memcpy(db
, sb
, image
->height
*image
->width
);
201 for (i
=0; i
<image
->height
*image
->width
; i
++) {
204 *dr
= (((int)*dr
* calpha
) + ((int)*sr
* alpha
))/256;
205 *dg
= (((int)*dg
* calpha
) + ((int)*sg
* alpha
))/256;
206 *db
= (((int)*db
* calpha
) + ((int)*sb
* alpha
))/256;
220 RCombineImagesWithOpaqueness(RImage
*image
, RImage
*src
, int opaqueness
)
223 unsigned char *dr
, *dg
, *db
, *da
;
224 unsigned char *sr
, *sg
, *sb
, *sa
;
228 assert(image
->width
== src
->width
);
229 assert(image
->height
== src
->height
);
241 c_opaqueness
= 255 - opaqueness
;
242 #define OP opaqueness
244 #define COP c_opaqueness
245 for (i
=0; i
<image
->width
*image
->height
; i
++) {
246 *dr
= (((int)*dr
*(int)COP
) + ((int)*sr
*(int)OP
))/256;
247 *dg
= (((int)*dg
*(int)COP
) + ((int)*sg
*(int)OP
))/256;
248 *db
= (((int)*db
*(int)COP
) + ((int)*sb
*(int)OP
))/256;
256 if (image
->data
[3]) {
257 for (i
=0; i
<image
->width
*image
->height
; i
++) {
258 tmp
= (*sa
* opaqueness
)/256;
259 *dr
= (((int)*dr
* (255-tmp
)) + ((int)*sr
* tmp
))/256;
260 *dg
= (((int)*dg
* (255-tmp
)) + ((int)*sg
* tmp
))/256;
261 *db
= (((int)*db
* (255-tmp
)) + ((int)*sb
* tmp
))/256;
270 for (i
=0; i
<image
->width
*image
->height
; i
++) {
271 tmp
= (*sa
* opaqueness
)/256;
272 *dr
= (((int)*dr
* (255-tmp
)) + ((int)*sr
* tmp
))/256;
273 *dg
= (((int)*dg
* (255-tmp
)) + ((int)*sg
* tmp
))/256;
274 *db
= (((int)*db
* (255-tmp
)) + ((int)*sb
* tmp
))/256;
287 RCombineArea(RImage
*image
, RImage
*src
, int sx
, int sy
, unsigned width
,
288 unsigned height
, int dx
, int dy
)
291 unsigned char *dr
, *dg
, *db
;
292 unsigned char *sr
, *sg
, *sb
, *sa
;
296 assert(dy
< image
->height
);
297 assert(dx
< image
->width
);
299 assert(sy
+ height
<= src
->height
);
300 assert(sx
+ width
<= src
->width
);
302 dr
= image
->data
[0] + dy
*(int)image
->width
+ dx
;
303 dg
= image
->data
[1] + dy
*(int)image
->width
+ dx
;
304 db
= image
->data
[2] + dy
*(int)image
->width
+ dx
;
306 sr
= src
->data
[0] + sy
*(int)src
->width
+ sx
;
307 sg
= src
->data
[1] + sy
*(int)src
->width
+ sx
;
308 sb
= src
->data
[2] + sy
*(int)src
->width
+ sx
;
309 sa
= src
->data
[3] + sy
*(int)src
->width
+ sx
;
311 swi
= src
->width
- width
;
312 dwi
= image
->width
- width
;
314 if (height
> image
->height
- dy
)
315 height
= image
->height
- dy
;
318 for (y
=sy
; y
<height
+sy
; y
++) {
319 for (x
=sx
; x
<width
+sx
; x
++) {
324 dr
+= dwi
; dg
+= dwi
; db
+= dwi
;
325 sr
+= swi
; sg
+= swi
; sb
+= swi
;
328 for (y
=sy
; y
<height
+sy
; y
++) {
329 for (x
=sx
; x
<width
+sx
; x
++) {
331 calpha
= 255 - alpha
;
332 *dr
= (((int)*dr
* calpha
) + ((int)*sr
* alpha
))/256;
333 *dg
= (((int)*dg
* calpha
) + ((int)*sg
* alpha
))/256;
334 *db
= (((int)*db
* calpha
) + ((int)*sb
* alpha
))/256;
339 dr
+= dwi
; dg
+= dwi
; db
+= dwi
;
340 sr
+= swi
; sg
+= swi
; sb
+= swi
;
348 RCombineAreaWithOpaqueness(RImage
*image
, RImage
*src
, int sx
, int sy
,
349 unsigned width
, unsigned height
, int dx
, int dy
,
354 unsigned char *dr
, *dg
, *db
;
355 unsigned char *sr
, *sg
, *sb
, *sa
;
357 assert(dy
<= image
->height
);
358 assert(dx
<= image
->width
);
360 assert(sy
<= height
);
363 dr
= image
->data
[0] + dy
*image
->width
+ dx
;
364 dg
= image
->data
[1] + dy
*image
->width
+ dx
;
365 db
= image
->data
[2] + dy
*image
->width
+ dx
;
367 sr
= src
->data
[0] + sy
*src
->width
;
368 sg
= src
->data
[1] + sy
*src
->width
;
369 sb
= src
->data
[2] + sy
*src
->width
;
370 sa
= src
->data
[3] + sy
*src
->width
;
372 swi
= src
->width
- width
;
373 dwi
= image
->width
- width
;
379 if (height
> image
->height
- dy
)
380 height
= image
->height
- dy
;
382 c_opaqueness
= 255 - opaqueness
;
383 #define OP opaqueness
385 #define COP c_opaqueness
386 for (y
=0; y
<height
; y
++) {
387 for (x
=0; x
<width
; x
++) {
388 *dr
= (((int)*dr
*(int)COP
) + ((int)*sr
*(int)OP
))/256;
389 *dg
= (((int)*dg
*(int)COP
) + ((int)*sg
*(int)OP
))/256;
390 *db
= (((int)*db
*(int)COP
) + ((int)*sb
*(int)OP
))/256;
394 dr
+= dwi
; dg
+= dwi
; db
+= dwi
;
395 sr
+= swi
; sg
+= swi
; sb
+= swi
;
401 for (y
=0; y
<height
; y
++) {
402 for (x
=0; x
<width
; x
++) {
403 tmp
= (*sa
* opaqueness
)/256;
404 *dr
= (((int)*dr
*(int)(255-tmp
)) + ((int)*sr
*(int)tmp
))/256;
405 *dg
= (((int)*dg
*(int)(255-tmp
)) + ((int)*sg
*(int)tmp
))/256;
406 *db
= (((int)*db
*(int)(255-tmp
)) + ((int)*sb
*(int)tmp
))/256;
411 dr
+= dwi
; dg
+= dwi
; db
+= dwi
;
412 sr
+= swi
; sg
+= swi
; sb
+= swi
;
423 RCombineImageWithColor(RImage
*image
, RColor
*color
)
426 unsigned char *dr
, *dg
, *db
, *da
;
427 int alpha
, nalpha
, r
, g
, b
;
435 /* Image has no alpha channel, so we consider it to be all 255 */
442 for (i
=0; i
<image
->width
*image
->height
; i
++) {
444 nalpha
= 255 - alpha
;
446 *dr
= (((int)*dr
* alpha
) + (r
* nalpha
))/256;
447 *dg
= (((int)*dg
* alpha
) + (g
* nalpha
))/256;
448 *db
= (((int)*db
* alpha
) + (b
* nalpha
))/256;
449 dr
++; dg
++; db
++; da
++;
455 RMakeTiledImage(RImage
*tile
, unsigned width
, unsigned height
)
459 unsigned long tile_size
= tile
->width
* tile
->height
;
460 unsigned long tx
= 0;
461 int have_alpha
= (tile
->data
[3]!=NULL
);
463 unsigned char *sr
, *sg
, *sb
, *sa
;
464 unsigned char *dr
, *dg
, *db
, *da
;
466 if (width
== tile
->width
&& height
== tile
->height
)
467 image
= RCloneImage(tile
);
468 else if (width
<= tile
->width
&& height
<= tile
->height
)
469 image
= RGetSubImage(tile
, 0, 0, width
, height
);
472 image
= RCreateImage(width
, height
, have_alpha
);
484 for (y
= 0; y
< height
; y
++) {
485 for (x
= 0; x
< width
; x
+= tile
->width
) {
487 w
= (width
- x
< tile
->width
) ? width
- x
: tile
->width
;
489 memcpy(dr
, sr
+tx
, w
);
490 memcpy(dg
, sg
+tx
, w
);
491 memcpy(db
, sb
+tx
, w
);
493 memcpy(da
, sa
+tx
, w
);
502 tx
= (tx
+ tile
->width
) % tile_size
;
510 RMakeCenteredImage(RImage
*image
, unsigned width
, unsigned height
, RColor
*color
)
512 int x
, y
, w
, h
, sx
, sy
;
515 tmp
= RCreateImage(width
, height
, False
);
520 RClearImage(tmp
, color
);
522 if (image
->height
< height
) {
527 sy
= (image
->height
- height
)/2;
531 if (image
->width
< width
) {
536 sx
= (image
->width
- width
)/2;
540 RCombineArea(tmp
, image
, sx
, sy
, w
, h
, x
, y
);