1 /************************************************************************
3 * voxelands - 3d voxel world sandbox game
4 * Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>
18 ************************************************************************/
26 static uint32_t merge_colours(uint32_t btm
, uint32_t top
)
32 f
.r
= (float)RED(top
);
33 f
.g
= (float)GREEN(top
);
34 f
.b
= (float)BLUE(top
);
35 f
.a
= (float)ALPHA(top
);
37 t
.r
= (float)RED(btm
);
38 t
.g
= (float)GREEN(btm
);
39 t
.b
= (float)BLUE(btm
);
40 t
.a
= (float)ALPHA(btm
);
48 r
.r
= f
.r
* (1.0 - t
.a
) + (f
.r
* f
.a
+ t
.r
* (1.0 - f
.a
)) * t
.a
;
49 r
.g
= f
.g
* (1.0 - t
.a
) + (f
.g
* f
.a
+ t
.g
* (1.0 - f
.a
)) * t
.a
;
50 r
.b
= f
.b
* (1.0 - t
.a
) + (f
.b
* f
.a
+ t
.b
* (1.0 - f
.a
)) * t
.a
;
54 r
.a
= t
.a
* f
.a
* 255.0;
60 static uint32_t colourise(uint32_t btm
, uint32_t top
)
66 f
.r
= (float)RED(top
);
67 f
.g
= (float)GREEN(top
);
68 f
.b
= (float)BLUE(top
);
69 f
.a
= (float)ALPHA(top
);
71 t
.r
= (float)RED(btm
);
72 t
.g
= (float)GREEN(btm
);
73 t
.b
= (float)BLUE(btm
);
74 t
.a
= (float)ALPHA(btm
);
77 if (ALPHA(btm
) == 0 || ALPHA(top
) == 0)
80 r
.r
= f
.r
* (1.0 - t
.a
) + (f
.r
* f
.a
+ t
.r
* (1.0 - f
.a
)) * t
.a
;
81 r
.g
= f
.g
* (1.0 - t
.a
) + (f
.g
* f
.a
+ t
.g
* (1.0 - f
.a
)) * t
.a
;
82 r
.b
= f
.b
* (1.0 - t
.a
) + (f
.b
* f
.a
+ t
.b
* (1.0 - f
.a
)) * t
.a
;
83 r
.a
= (float)ALPHA(btm
);
88 /* load an image to pixel data */
89 image_t
*image_load(char* type
, char* file
)
91 /* storage space for the image */
93 image_t
* image
= NULL
;
95 /* load the file data */
96 f
= file_load(type
,file
);
101 /* and make in image out of it */
102 image
= image_load_frommem(f
);
109 /* load an image to pixel data from memory */
110 image_t
*image_load_frommem(file_t
*f
)
112 image_t
* image
= malloc(sizeof(image_t
));
116 image
->pixels
= NULL
;
121 if (image_is_bmp(f
)) {
122 if (image_load_bmp(f
,image
)) {
123 vlprintf(CN_ERROR
, "Image Not Loaded: %s",f
->name
);
128 }else if (image_is_png(f
)) {
129 if (image_load_png(f
,image
)) {
130 vlprintf(CN_ERROR
, "Image Not Loaded: %s",f
->name
);
135 }else if (image_is_tga(f
)) {
136 if (image_load_tga(f
,image
)) {
137 vlprintf(CN_ERROR
, "Image Not Loaded: %s",f
->name
);
141 /* unsupported image */
143 vlprintf(CN_ERROR
, "Unsupported Image: %s",f
->name
);
151 /* load an image to pixel data from a section of the screen */
152 image_t
*image_load_fromscreen(int x
, int y
, int w
, int h
, int alpha
)
155 image_t
*image
= malloc(sizeof(image_t
));
161 image
->pixels
= malloc(size
);
165 /* if keeping alpha, just grab rgba */
167 glReadPixels(x
,(wm_data
.size
.height
-y
)-h
,w
,h
,GL_RGBA
,GL_UNSIGNED_BYTE
,image
->pixels
);
168 /* otherwise grab rgb, then reformat with alpha */
175 img
.pixels
= malloc(size
);
177 glReadPixels(x
,h
,w
,(wm_data
.size
.height
-y
)-h
,GL_RGB
,GL_UNSIGNED_BYTE
,img
.pixels
);
179 for (i
=0,o
=0; o
<size
;) {
180 image
->pixels
[o
++] = 0xFF;
181 image
->pixels
[o
++] = img
.pixels
[i
++];
182 image
->pixels
[o
++] = img
.pixels
[i
++];
183 image
->pixels
[o
++] = img
.pixels
[i
++];
192 /* create an image from rgba values */
193 image_t
*image_rgba(int x
, int y
, uint8_t r
, uint8_t g
, uint8_t b
, uint8_t a
)
200 snprintf(n
,100,"rgba-%u-%u-%u-%u-%d-%d",(uint32_t)r
,(uint32_t)g
,(uint32_t)b
,(uint32_t)a
,x
,y
);
202 img
= malloc(sizeof(image_t
));
211 img
->pixels
= malloc(sizeof(uint8_t)*size
);
219 img
->pixels
[i
++] = r
;
220 img
->pixels
[i
++] = g
;
221 img
->pixels
[i
++] = b
;
222 img
->pixels
[i
++] = a
;
228 /* create a copy of an image */
229 image_t
*image_copy(image_t
*img
)
232 image_t
*p
= malloc(sizeof(image_t
));
240 p
->pixels
= malloc(sizeof(unsigned char)*ds
);
246 memcpy(p
->pixels
,img
->pixels
,ds
);
251 /* clear an image - set all pixels black */
252 void image_clear(image_t
*img
)
256 uint32_t c
= 0xFF000000;
260 for (i
=0; i
<s
; i
++) {
265 /* draw an open rectangle of colour onto an image */
266 void image_draw_rect(image_t
*img
, colour_t
*c
, int width
, rect_t
*area
)
284 if (p
.x
+p
.w
> img
->w
)
286 if (p
.y
+p
.h
> img
->h
)
301 image_draw_line(img
,c
,width
,&f
,&t
);
306 image_draw_line(img
,c
,width
,&f
,&t
);
311 image_draw_line(img
,c
,width
,&f
,&t
);
316 image_draw_line(img
,c
,width
,&f
,&t
);
319 /* draw a line of colour onto an image */
320 void image_draw_line(image_t
*img
, colour_t
*c
, int width
, rect_t
*from
, rect_t
*to
)
336 if (!img
|| !from
|| !to
)
341 dx
=to
->x
-from
->x
; /* the horizontal distance of the line */
342 dy
=to
->y
-from
->y
; /* the vertical distance of the line */
354 if (dxabs
>=dyabs
) { /* the line is more horizontal than vertical */
355 for (i
=0;i
<dxabs
;i
++) {
362 if (px
>= img
->w
|| px
< 0)
364 for (w
=py
-width
; w
<=py
+width
; w
++) {
365 if (w
>= img
->h
|| w
< 0)
367 tclr
= GETPX(img
,px
,w
);
368 tclr
= merge_colours(tclr
,clr
);
369 SETPX(img
,px
,w
,tclr
);
372 }else{ /* the line is more vertical than horizontal */
373 for (i
=0;i
<dyabs
;i
++) {
380 if (py
>= img
->h
|| py
< 0)
382 for (w
=px
-width
; w
<=px
+width
; w
++) {
383 if (w
>= img
->w
|| w
< 0)
385 tclr
= GETPX(img
,w
,py
);
386 tclr
= merge_colours(tclr
,clr
);
387 SETPX(img
,w
,py
,tclr
);
393 /* draw a rectangle of colour onto an image */
394 void image_fill_rect(image_t
*img
, colour_t
*c
, rect_t
*area
)
412 if (p
.x
+p
.w
> img
->w
)
414 if (p
.y
+p
.h
> img
->h
)
425 for (y
=p
.y
; y
<p
.h
; y
++) {
426 for (x
=p
.x
; x
<p
.w
; x
++) {
432 /* copy pixels from one image to another */
433 void image_copy_area(image_t
*dest
, image_t
*src
, rect_t
*to
, rect_t
*from
)
456 if (f
.x
+f
.w
> src
->w
)
458 if (f
.y
+f
.h
> src
->h
)
476 if (t
.x
+t
.w
> dest
->w
)
478 if (t
.y
+t
.h
> dest
->h
)
504 for (y
=t
.y
,fy
=f
.y
; y
<t
.h
; y
++,fy
++) {
505 for (x
=t
.x
,fx
=f
.x
; x
<t
.w
; x
++,fx
++) {
506 clr
= GETPX(src
,fx
,fy
);
512 /* blit one image over another */
513 void image_blit(image_t
*dest
, image_t
*src
, rect_t
*to
, rect_t
*from
)
537 if (f
.x
+f
.w
> src
->w
)
539 if (f
.y
+f
.h
> src
->h
)
557 if (t
.x
+t
.w
> dest
->w
)
559 if (t
.y
+t
.h
> dest
->h
)
585 for (y
=t
.y
,fy
=f
.y
; y
<t
.h
; y
++,fy
++) {
586 for (x
=t
.x
,fx
=f
.x
; x
<t
.w
; x
++,fx
++) {
587 fclr
= GETPX(src
,fx
,fy
);
588 tclr
= GETPX(dest
,x
,y
);
589 tclr
= merge_colours(tclr
,fclr
);
590 SETPX(dest
,x
,y
,tclr
);
595 /* colourise an image */
596 void image_colourise(image_t
*img
, colour_t
*c
, rect_t
*area
)
615 if (t
.x
+t
.w
> img
->w
)
617 if (t
.y
+t
.h
> img
->h
)
627 for (y
=t
.y
; y
<t
.h
; y
++) {
628 for (x
=t
.x
; x
<t
.w
; x
++) {
630 tclr
= GETPX(img
,x
,y
);
631 tclr
= colourise(tclr
,fclr
);