diff options
Diffstat (limited to 'src/cd_bitmap.c')
-rw-r--r-- | src/cd_bitmap.c | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/src/cd_bitmap.c b/src/cd_bitmap.c new file mode 100644 index 0000000..234668c --- /dev/null +++ b/src/cd_bitmap.c @@ -0,0 +1,293 @@ +/** \file + * \brief cdBitmap implementation + * + * See Copyright Notice in cd.h + */ + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <assert.h> +#include <memory.h> +#include <math.h> +#include <stdarg.h> + + +#include "cd.h" +#include "cdirgb.h" + +#include "cd_private.h" + + +typedef struct _cdBitmapData +{ + void *buffer; + + unsigned char *index; /* pointers into buffer */ + unsigned char *r; + unsigned char *g; + unsigned char *b; + unsigned char *a; + + long* colors; + + int xmin, xmax, ymin, ymax; +} cdBitmapData; + + +cdBitmap* cdCreateBitmap(int w, int h, int type) +{ + int num_channel; + int size = w * h; + cdBitmap* bitmap; + cdBitmapData* data; + + assert(w>0); + assert(h>0); + if (w <= 0) return NULL; + if (h <= 0) return NULL; + + switch (type) + { + case CD_RGB: + num_channel = 3; + break; + case CD_RGBA: + num_channel = 4; + break; + case CD_MAP: + num_channel = 1; + break; + default: + return NULL; + } + + bitmap = (cdBitmap*)malloc(sizeof(cdBitmap)); + data = (cdBitmapData*)malloc(sizeof(cdBitmapData)); + memset(data, 0, sizeof(cdBitmapData)); + + bitmap->w = w; + bitmap->h = h; + bitmap->type = type; + bitmap->data = data; + + data->buffer = malloc(size*num_channel); + if (!data->buffer) + { + free(data); + free(bitmap); + return NULL; + } + + if (type == CD_RGB) + { + data->r = data->buffer; + data->g = data->r + size; + data->b = data->g + size; + memset(data->r, 255, 3*size); /* white */ + } + + if (type == CD_RGBA) + { + data->a = data->b + size; + memset(data->a, 0, size); /* transparent */ + } + + if (type == CD_MAP) + { + data->index = data->buffer; + data->colors = (long*)calloc(256, sizeof(long)); + memset(data->index, 0, size); /* index=0 */ + } + + data->xmin = 0; + data->ymin = 0; + data->xmax = bitmap->w-1; + data->ymax = bitmap->h-1; + + return bitmap; +} + +cdBitmap* cdInitBitmap(int w, int h, int type, ...) +{ + va_list arglist; + cdBitmap* bitmap; + cdBitmapData* data; + + assert(w>0); + assert(h>0); + if (w <= 0) return NULL; + if (h <= 0) return NULL; + + if (type != CD_RGB && + type != CD_RGBA && + type != CD_MAP) + return NULL; + + bitmap = (cdBitmap*)malloc(sizeof(cdBitmap)); + data = (cdBitmapData*)malloc(sizeof(cdBitmapData)); + memset(data, 0, sizeof(cdBitmapData)); + + bitmap->w = w; + bitmap->h = h; + bitmap->type = type; + bitmap->data = data; + + va_start(arglist, type); + + if (type == CD_RGB) + { + data->r = va_arg(arglist, unsigned char*); + data->g = va_arg(arglist, unsigned char*); + data->b = va_arg(arglist, unsigned char*); + } + + if (type == CD_RGBA) + data->a = va_arg(arglist, unsigned char*); + + if (type == CD_MAP) + { + data->index = va_arg(arglist, unsigned char*); + data->colors = va_arg(arglist, long*); + } + + data->xmin = 0; + data->ymin = 0; + data->xmax = bitmap->w-1; + data->ymax = bitmap->h-1; + + return bitmap; +} + +void cdKillBitmap(cdBitmap* bitmap) +{ + cdBitmapData* data; + + assert(bitmap); + assert(bitmap->data); + if (!bitmap) return; + if (!bitmap->data) return; + + data = (cdBitmapData*)bitmap->data; + + if (data->buffer) + { + free(data->buffer); + + if (bitmap->type == CD_MAP) + free(data->colors); + } + + free(data); + free(bitmap); +} + +void cdCanvasGetBitmap(cdCanvas* canvas, cdBitmap* bitmap, int x, int y) +{ + cdBitmapData* data; + + assert(bitmap); + assert(bitmap->data); + if (!bitmap) return; + if (!bitmap->data) return; + + data = (cdBitmapData*)bitmap->data; + + if (bitmap->type == CD_RGB || bitmap->type == CD_RGBA) + cdCanvasGetImageRGB(canvas, data->r, data->g, data->b, x, y, bitmap->w, bitmap->h); +} + +void cdBitmapRGB2Map(cdBitmap* bitmap_rgb, cdBitmap* bitmap_map) +{ + cdBitmapData* data_rgb; + cdBitmapData* data_map; + + assert(bitmap_rgb); + assert(bitmap_rgb->data); + assert(bitmap_map); + assert(bitmap_map->data); + if (!bitmap_rgb) return; + if (!bitmap_rgb->data) return; + if (!bitmap_map) return; + if (!bitmap_map->data) return; + + data_rgb = (cdBitmapData*)bitmap_rgb->data; + data_map = (cdBitmapData*)bitmap_map->data; + + if ((bitmap_rgb->type != CD_RGB && bitmap_rgb->type != CD_RGBA) || (bitmap_map->type != CD_MAP)) + return; + + cdRGB2Map(bitmap_rgb->w, bitmap_rgb->h, data_rgb->r, data_rgb->g, data_rgb->b, data_map->index, bitmap_map->type, data_map->colors); +} + +unsigned char* cdBitmapGetData(cdBitmap* bitmap, int dataptr) +{ + cdBitmapData* data; + + assert(bitmap); + assert(bitmap->data); + if (!bitmap) return NULL; + if (!bitmap->data) return NULL; + + data = (cdBitmapData*)bitmap->data; + + switch(dataptr) + { + case CD_IRED: + return data->r; + case CD_IGREEN: + return data->g; + case CD_IBLUE: + return data->b; + case CD_IALPHA: + return data->a; + case CD_INDEX: + return data->index; + case CD_COLORS: + return (unsigned char*)data->colors; + } + + return NULL; +} + +void cdBitmapSetRect(cdBitmap* bitmap, int xmin, int xmax, int ymin, int ymax) +{ + cdBitmapData* data; + + assert(bitmap); + assert(bitmap->data); + if (!bitmap) return; + if (!bitmap->data) return; + + data = (cdBitmapData*)bitmap->data; + + data->xmin = xmin; + data->xmax = xmax; + data->ymin = ymin; + data->ymax = ymax; +} + +void cdCanvasPutBitmap(cdCanvas* canvas, cdBitmap* bitmap, int x, int y, int w, int h) +{ + cdBitmapData* data; + + assert(bitmap); + assert(bitmap->data); + if (!bitmap) return; + if (!bitmap->data) return; + + data = (cdBitmapData*)bitmap->data; + + switch(bitmap->type) + { + case CD_RGB: + cdCanvasPutImageRectRGB(canvas, bitmap->w, bitmap->h, data->r, data->g, data->b, x, y, w, h, data->xmin, data->xmax, data->ymin, data->ymax); + break; + case CD_RGBA: + cdCanvasPutImageRectRGBA(canvas, bitmap->w, bitmap->h, data->r, data->g, data->b, data->a, x, y, w, h, data->xmin, data->xmax, data->ymin, data->ymax); + break; + case CD_MAP: + cdCanvasPutImageRectMap(canvas, bitmap->w, bitmap->h, data->index, data->colors, x, y, w, h, data->xmin, data->xmax, data->ymin, data->ymax); + break; + } +} |