/** \file * \brief cdBitmap implementation * * See Copyright Notice in cd.h */ #include #include #include #include #include #include #include #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; } }