summaryrefslogtreecommitdiff
path: root/src/cd_bitmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cd_bitmap.c')
-rw-r--r--src/cd_bitmap.c293
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;
+ }
+}