1 /*****************************************************************************
2 * This file is part of gfxprim library. *
4 * Gfxprim is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU Lesser General Public *
6 * License as published by the Free Software Foundation; either *
7 * version 2.1 of the License, or (at your option) any later version. *
9 * Gfxprim is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12 * Lesser General Public License for more details. *
14 * You should have received a copy of the GNU Lesser General Public *
15 * License along with gfxprim; if not, write to the Free Software *
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17 * Boston, MA 02110-1301 USA *
19 * Copyright (C) 2009-2011 Jiri "BlueBear" Dluhos *
20 * <jiri.bluebear.dluhos@gmail.com> *
22 * Copyright (C) 2009-2012 Cyril Hrubis <metan@ucw.cz> *
24 *****************************************************************************/
30 #include "GP_Transform.h"
32 #include "GP_GetPutPixel.h"
33 #include "GP_GammaCorrection.h"
34 #include "GP_Context.h"
37 static uint32_t get_bpr(uint32_t bpp
, uint32_t w
)
39 return (bpp
* w
) / 8 + !!((bpp
* w
) % 8);
42 GP_Context
*GP_ContextAlloc(GP_Size w
, GP_Size h
, GP_PixelType type
)
44 GP_CHECK_VALID_PIXELTYPE(type
);
46 uint32_t bpp
= GP_PixelSize(type
);
47 uint32_t bpr
= get_bpr(bpp
, w
);
50 pixels
= malloc(bpr
* h
);
51 context
= malloc(sizeof(GP_Context
));
53 if (pixels
== NULL
|| context
== NULL
) {
56 GP_WARN("Malloc failed :(");
61 context
->pixels
= pixels
;
63 context
->bytes_per_row
= bpr
;
69 context
->gamma
= NULL
;
71 context
->pixel_type
= type
;
72 #warning Hmm, bit endianity... Why is not this settled by different pixel types?
73 context
->bit_endian
= 0;
75 /* rotation and mirroring */
76 GP_ContextSetRotation(context
, 0, 0, 0);
78 context
->free_pixels
= 1;
83 void GP_ContextFree(GP_Context
*context
)
85 GP_DEBUG(1, "Freeing context (%p)", context
);
90 if (context
->free_pixels
)
91 free(context
->pixels
);
94 GP_GammaRelease(context
->gamma
);
99 GP_Context
*GP_ContextInit(GP_Context
*context
, GP_Size w
, GP_Size h
,
100 GP_PixelType type
, void *pixels
)
102 uint32_t bpp
= GP_PixelSize(type
);
103 uint32_t bpr
= get_bpr(bpp
, w
);
105 context
->pixels
= pixels
;
107 context
->bytes_per_row
= bpr
;
113 context
->pixel_type
= type
;
114 context
->bit_endian
= 0;
116 context
->gamma
= NULL
;
118 /* rotation and mirroring */
119 GP_ContextSetRotation(context
, 0, 0, 0);
121 context
->free_pixels
= 0;
126 int GP_ContextResize(GP_Context
*context
, GP_Size w
, GP_Size h
)
128 uint32_t bpr
= get_bpr(context
->bpp
, w
);
131 pixels
= realloc(context
->pixels
, bpr
* h
);
138 context
->bytes_per_row
= bpr
;
139 context
->pixels
= pixels
;
144 GP_Context
*GP_ContextCopy(const GP_Context
*src
, int flags
)
152 new = malloc(sizeof(GP_Context
));
153 pixels
= malloc(src
->bytes_per_row
* src
->h
);
155 if (pixels
== NULL
|| new == NULL
) {
158 GP_WARN("Malloc failed :(");
163 new->pixels
= pixels
;
165 if (flags
& GP_COPY_WITH_PIXELS
)
166 memcpy(pixels
, src
->pixels
, src
->bytes_per_row
* src
->h
);
169 new->bytes_per_row
= src
->bytes_per_row
;
175 new->pixel_type
= src
->pixel_type
;
176 new->bit_endian
= src
->bit_endian
;
178 if (flags
& GP_COPY_WITH_ROTATION
)
179 GP_ContextCopyRotation(src
, new);
181 GP_ContextSetRotation(new, 0, 0, 0);
183 //TODO: Copy the gamma too
186 new->free_pixels
= 1;
192 GP_Context
*GP_ContextConvertAlloc(const GP_Context
*src
,
193 GP_PixelType dst_pixel_type
)
195 int w
= GP_ContextW(src
);
196 int h
= GP_ContextH(src
);
198 GP_Context
*ret
= GP_ContextAlloc(w
, h
, dst_pixel_type
);
203 GP_Blit(src
, 0, 0, w
, h
, ret
, 0, 0);
208 GP_Context
*GP_ContextConvert(const GP_Context
*src
, GP_Context
*dst
)
211 int w
= GP_ContextW(src
);
212 int h
= GP_ContextH(src
);
214 GP_Blit(src
, 0, 0, w
, h
, dst
, 0, 0);
219 GP_Context
*GP_SubContextAlloc(const GP_Context
*context
,
220 GP_Coord x
, GP_Coord y
, GP_Size w
, GP_Size h
)
222 GP_Context
*res
= malloc(sizeof(GP_Context
));
225 GP_WARN("Malloc failed :(");
230 return GP_SubContext(context
, res
, x
, y
, w
, h
);
233 GP_Context
*GP_SubContext(const GP_Context
*context
, GP_Context
*subcontext
,
234 GP_Coord x
, GP_Coord y
, GP_Size w
, GP_Size h
)
236 GP_CHECK(context
, "NULL context");
238 GP_TRANSFORM_RECT(context
, x
, y
, w
, h
);
240 GP_CHECK(context
->w
>= x
+ w
, "Subcontext w out of original context.");
241 GP_CHECK(context
->h
>= y
+ h
, "Subcontext h out of original context.");
243 subcontext
->bpp
= context
->bpp
;
244 subcontext
->bytes_per_row
= context
->bytes_per_row
;
245 subcontext
->offset
= (context
->offset
+
246 GP_PixelAddrOffset(x
, context
->pixel_type
)) % 8;
251 subcontext
->pixel_type
= context
->pixel_type
;
252 subcontext
->bit_endian
= context
->bit_endian
;
255 subcontext
->gamma
= context
->gamma
;
257 /* rotation and mirroring */
258 GP_ContextCopyRotation(context
, subcontext
);
260 subcontext
->pixels
= GP_PIXEL_ADDR(context
, x
, y
);
262 subcontext
->free_pixels
= 0;
267 void GP_ContextPrintInfo(const GP_Context
*self
)
269 printf("Context info\n");
270 printf("------------\n");
271 printf("Size\t%ux%u\n", self
->w
, self
->h
);
272 printf("BPP\t%u\n", self
->bpp
);
273 printf("BPR\t%u\n", self
->bytes_per_row
);
274 printf("Pixel\t%s (%u)\n", GP_PixelTypeName(self
->pixel_type
),
276 printf("Offset\t%u (only unaligned pixel types)\n", self
->offset
);
277 printf("Flags\taxes_swap=%u x_swap=%u y_swap=%u free_pixels=%u\n",
278 self
->axes_swap
, self
->x_swap
, self
->y_swap
, self
->free_pixels
);
279 printf("Gamma table %p", self
->gamma
);
283 * The context rotations consists of two cyclic permutation groups that are
286 * The flags change as follows:
290 * x_swap y_swap axes_swap
296 * And mirrored group:
298 * x_swap y_swap axes_swap
305 void GP_ContextRotateCW(GP_Context
*context
)
307 context
->axes_swap
= !context
->axes_swap
;
309 if (!context
->x_swap
&& !context
->y_swap
) {
314 if (context
->x_swap
&& !context
->y_swap
) {
319 if (context
->x_swap
&& context
->y_swap
) {
327 void GP_ContextRotateCCW(GP_Context
*context
)
329 context
->axes_swap
= !context
->axes_swap
;
331 if (!context
->x_swap
&& !context
->y_swap
) {
336 if (context
->x_swap
&& !context
->y_swap
) {
341 if (context
->x_swap
&& context
->y_swap
) {