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-2013 Cyril Hrubis <metan@ucw.cz> *
24 *****************************************************************************/
30 #include "GP_Transform.h"
32 #include "GP_GetPutPixel.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 GP_DEBUG(1, "Allocating context %u x %u - %s",
51 w
, h
, GP_PixelTypeName(type
));
53 pixels
= malloc(bpr
* h
);
54 context
= malloc(sizeof(GP_Context
));
56 if (pixels
== NULL
|| context
== NULL
) {
59 GP_WARN("Malloc failed :(");
64 context
->pixels
= pixels
;
66 context
->bytes_per_row
= bpr
;
72 context
->gamma
= NULL
;
74 context
->pixel_type
= type
;
75 #warning Hmm, bit endianity... Why is not this settled by different pixel types?
76 context
->bit_endian
= GP_PixelTypes
[type
].bit_endian
;
78 /* rotation and mirroring */
79 GP_ContextSetRotation(context
, 0, 0, 0);
81 context
->free_pixels
= 1;
86 void GP_ContextFree(GP_Context
*context
)
88 GP_DEBUG(1, "Freeing context (%p)", context
);
93 if (context
->free_pixels
)
94 free(context
->pixels
);
97 GP_GammaRelease(context
->gamma
);
102 GP_Context
*GP_ContextInit(GP_Context
*context
, GP_Size w
, GP_Size h
,
103 GP_PixelType type
, void *pixels
)
105 uint32_t bpp
= GP_PixelSize(type
);
106 uint32_t bpr
= get_bpr(bpp
, w
);
108 context
->pixels
= pixels
;
110 context
->bytes_per_row
= bpr
;
116 context
->pixel_type
= type
;
117 context
->bit_endian
= 0;
119 context
->gamma
= NULL
;
121 /* rotation and mirroring */
122 GP_ContextSetRotation(context
, 0, 0, 0);
124 context
->free_pixels
= 0;
129 int GP_ContextResize(GP_Context
*context
, GP_Size w
, GP_Size h
)
131 uint32_t bpr
= get_bpr(context
->bpp
, w
);
134 pixels
= realloc(context
->pixels
, bpr
* h
);
141 context
->bytes_per_row
= bpr
;
142 context
->pixels
= pixels
;
147 GP_Context
*GP_ContextCopy(const GP_Context
*src
, int flags
)
155 new = malloc(sizeof(GP_Context
));
156 pixels
= malloc(src
->bytes_per_row
* src
->h
);
158 if (pixels
== NULL
|| new == NULL
) {
161 GP_WARN("Malloc failed :(");
166 new->pixels
= pixels
;
168 if (flags
& GP_COPY_WITH_PIXELS
)
169 memcpy(pixels
, src
->pixels
, src
->bytes_per_row
* src
->h
);
172 new->bytes_per_row
= src
->bytes_per_row
;
178 new->pixel_type
= src
->pixel_type
;
179 new->bit_endian
= src
->bit_endian
;
181 if (flags
& GP_COPY_WITH_ROTATION
)
182 GP_ContextCopyRotation(src
, new);
184 GP_ContextSetRotation(new, 0, 0, 0);
186 //TODO: Copy the gamma too
189 new->free_pixels
= 1;
195 GP_Context
*GP_ContextConvertAlloc(const GP_Context
*src
,
196 GP_PixelType dst_pixel_type
)
198 int w
= GP_ContextW(src
);
199 int h
= GP_ContextH(src
);
201 GP_Context
*ret
= GP_ContextAlloc(w
, h
, dst_pixel_type
);
206 GP_Blit(src
, 0, 0, w
, h
, ret
, 0, 0);
211 GP_Context
*GP_ContextConvert(const GP_Context
*src
, GP_Context
*dst
)
214 int w
= GP_ContextW(src
);
215 int h
= GP_ContextH(src
);
217 GP_Blit(src
, 0, 0, w
, h
, dst
, 0, 0);
222 GP_Context
*GP_SubContextAlloc(const GP_Context
*context
,
223 GP_Coord x
, GP_Coord y
, GP_Size w
, GP_Size h
)
225 GP_Context
*res
= malloc(sizeof(GP_Context
));
228 GP_WARN("Malloc failed :(");
233 return GP_SubContext(context
, res
, x
, y
, w
, h
);
236 GP_Context
*GP_SubContext(const GP_Context
*context
, GP_Context
*subcontext
,
237 GP_Coord x
, GP_Coord y
, GP_Size w
, GP_Size h
)
239 GP_CHECK(context
, "NULL context");
241 GP_TRANSFORM_RECT(context
, x
, y
, w
, h
);
243 GP_CHECK(context
->w
>= x
+ w
, "Subcontext w out of original context.");
244 GP_CHECK(context
->h
>= y
+ h
, "Subcontext h out of original context.");
246 subcontext
->bpp
= context
->bpp
;
247 subcontext
->bytes_per_row
= context
->bytes_per_row
;
248 subcontext
->offset
= (context
->offset
+
249 GP_PixelAddrOffset(x
, context
->pixel_type
)) % 8;
254 subcontext
->pixel_type
= context
->pixel_type
;
255 subcontext
->bit_endian
= context
->bit_endian
;
258 subcontext
->gamma
= context
->gamma
;
260 /* rotation and mirroring */
261 GP_ContextCopyRotation(context
, subcontext
);
263 subcontext
->pixels
= GP_PIXEL_ADDR(context
, x
, y
);
265 subcontext
->free_pixels
= 0;
270 void GP_ContextPrintInfo(const GP_Context
*self
)
272 printf("Context info\n");
273 printf("------------\n");
274 printf("Size\t%ux%u\n", self
->w
, self
->h
);
275 printf("BPP\t%u\n", self
->bpp
);
276 printf("BPR\t%u\n", self
->bytes_per_row
);
277 printf("Pixel\t%s (%u)\n", GP_PixelTypeName(self
->pixel_type
),
279 printf("Offset\t%u (only unaligned pixel types)\n", self
->offset
);
280 printf("Flags\taxes_swap=%u x_swap=%u y_swap=%u free_pixels=%u\n",
281 self
->axes_swap
, self
->x_swap
, self
->y_swap
, self
->free_pixels
);
284 GP_GammaPrint(self
->gamma
);
288 * The context rotations consists of two cyclic permutation groups that are
291 * The flags change as follows:
295 * x_swap y_swap axes_swap
301 * And mirrored group:
303 * x_swap y_swap axes_swap
310 void GP_ContextRotateCW(GP_Context
*context
)
312 context
->axes_swap
= !context
->axes_swap
;
314 if (!context
->x_swap
&& !context
->y_swap
) {
319 if (context
->x_swap
&& !context
->y_swap
) {
324 if (context
->x_swap
&& context
->y_swap
) {
332 void GP_ContextRotateCCW(GP_Context
*context
)
334 context
->axes_swap
= !context
->axes_swap
;
336 if (!context
->x_swap
&& !context
->y_swap
) {
341 if (context
->x_swap
&& !context
->y_swap
) {
346 if (context
->x_swap
&& context
->y_swap
) {
354 int GP_ContextEqual(const GP_Context
*ctx1
, const GP_Context
*ctx2
)
356 if (ctx1
->pixel_type
!= ctx2
->pixel_type
)
359 if (GP_ContextW(ctx1
) != GP_ContextW(ctx2
))
362 if (GP_ContextH(ctx1
) != GP_ContextH(ctx2
))
365 GP_Coord x
, y
, w
= GP_ContextW(ctx1
), h
= GP_ContextH(ctx1
);
367 for (x
= 0; x
< w
; x
++)
368 for (y
= 0; y
< h
; y
++)
369 if (GP_GetPixel(ctx1
, x
, y
) != GP_GetPixel(ctx2
, x
, y
))