aboutsummaryrefslogtreecommitdiff
path: root/system/type/pdp_bitmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'system/type/pdp_bitmap.c')
-rw-r--r--system/type/pdp_bitmap.c583
1 files changed, 583 insertions, 0 deletions
diff --git a/system/type/pdp_bitmap.c b/system/type/pdp_bitmap.c
new file mode 100644
index 0000000..7b093aa
--- /dev/null
+++ b/system/type/pdp_bitmap.c
@@ -0,0 +1,583 @@
+/*
+ * Pure Data Packet system implementation. : 8 bit image packet implementation
+ * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include "pdp.h"
+#include "pdp_internals.h"
+#include <stdio.h>
+
+
+/* the class object */
+static t_pdp_class* bitmap_class;
+
+
+t_bitmap *pdp_packet_bitmap_info(int packet)
+{
+ return (t_bitmap *)pdp_packet_subheader(packet);
+}
+
+/* check if packet is a valid image packet */
+int pdp_packet_bitmap_isvalid(int packet)
+{
+ t_pdp *header = pdp_packet_header(packet);
+ t_bitmap *image = pdp_packet_bitmap_info(packet);
+ if (!header) return 0;
+ if (PDP_BITMAP != header->type) return 0;
+
+ return 1;
+
+}
+
+
+
+/* bitmap constructors */
+t_pdp_symbol *pdp_packet_bitmap_get_description(int packet)
+{
+ t_pdp *header = pdp_packet_header(packet);
+ t_bitmap *bitmap = pdp_packet_bitmap_info(packet);
+ char description[1024];
+ char *c = description;
+ int encoding;
+
+ if (!header) return pdp_gensym("invalid");
+ else if (!header->desc){
+ /* if description is not defined, try to reconstruct it (for backwards compat) */
+ if (header->type == PDP_BITMAP){
+ c += sprintf(c, "bitmap");
+ encoding = bitmap->encoding;
+ switch(encoding){
+ case PDP_BITMAP_RGB: c += sprintf(c, "/rgb"); break;
+ case PDP_BITMAP_RGBA: c += sprintf(c, "/rgba"); break;
+ case PDP_BITMAP_GREY: c += sprintf(c, "/grey"); break;
+ case PDP_BITMAP_YV12: c += sprintf(c, "/yv12"); break;
+ default:
+ c += sprintf(c, "/unknown"); goto exit;
+ }
+ c += sprintf(c, "/%dx%d",
+ bitmap->width,
+ bitmap->height);
+ exit:
+ return pdp_gensym(description);
+ }
+ else return pdp_gensym("unknown");
+ }
+ else return header->desc;
+}
+
+int pdp_packet_new_bitmap_yv12(u32 w, u32 h)
+{
+ t_pdp *header;
+ t_bitmap *bitmap;
+ int packet;
+
+
+ u32 size = w*h;
+ u32 totalnbpixels = size;
+ u32 packet_size = size + (size >> 1);
+
+ packet = pdp_packet_new(PDP_BITMAP, packet_size);
+ header = pdp_packet_header(packet);
+ bitmap = pdp_packet_bitmap_info(packet);
+ if (!header) return -1;
+
+ bitmap->encoding = PDP_BITMAP_YV12;
+ bitmap->width = w;
+ bitmap->height = h;
+ header->desc = pdp_packet_bitmap_get_description(packet);
+ header->theclass = bitmap_class;
+
+ return packet;
+}
+
+int pdp_packet_new_bitmap_grey(u32 w, u32 h)
+{
+ t_pdp *header;
+ t_bitmap *bitmap;
+ int packet;
+
+ u32 size = w*h;
+ u32 totalnbpixels = size;
+ u32 packet_size = totalnbpixels;
+
+ packet = pdp_packet_new(PDP_BITMAP, packet_size);
+ header = pdp_packet_header(packet);
+ bitmap = pdp_packet_bitmap_info(packet);
+ if (!header) return -1;
+
+ bitmap->encoding = PDP_BITMAP_GREY;
+ bitmap->width = w;
+ bitmap->height = h;
+ header->desc = pdp_packet_bitmap_get_description(packet);
+ header->theclass = bitmap_class;
+
+ return packet;
+}
+
+int pdp_packet_new_bitmap_rgb(u32 w, u32 h)
+{
+ t_pdp *header;
+ t_bitmap *bitmap;
+ int packet;
+
+
+ u32 size = w*h;
+ u32 totalnbpixels = size;
+ u32 packet_size = totalnbpixels * 3;
+
+ packet = pdp_packet_new(PDP_BITMAP, packet_size);
+ header = pdp_packet_header(packet);
+ bitmap = pdp_packet_bitmap_info(packet);
+ if (!header) return -1;
+
+ bitmap->encoding = PDP_BITMAP_RGB;
+ bitmap->width = w;
+ bitmap->height = h;
+ header->desc = pdp_packet_bitmap_get_description(packet);
+ header->theclass = bitmap_class;
+
+ return packet;
+}
+
+int pdp_packet_new_bitmap_rgba(u32 w, u32 h)
+{
+ t_pdp *header;
+ t_bitmap *bitmap;
+ int packet;
+
+
+ u32 size = w*h;
+ u32 totalnbpixels = size;
+ u32 packet_size = totalnbpixels * 4;
+
+ packet = pdp_packet_new(PDP_BITMAP, packet_size);
+ header = pdp_packet_header(packet);
+ bitmap = pdp_packet_bitmap_info(packet);
+ if (!header) return -1;
+
+ bitmap->encoding = PDP_BITMAP_RGBA;
+ bitmap->width = w;
+ bitmap->height = h;
+ header->desc = pdp_packet_bitmap_get_description(packet);
+ header->theclass = bitmap_class;
+
+ return packet;
+}
+
+int pdp_packet_new_bitmap(int type, u32 w, u32 h)
+{
+ switch(type){
+ case PDP_BITMAP_GREY: return pdp_packet_new_bitmap_grey(w,h);
+ case PDP_BITMAP_RGB: return pdp_packet_new_bitmap_rgb(w,h);
+ case PDP_BITMAP_RGBA: return pdp_packet_new_bitmap_rgba(w,h);
+ default: return -1;
+ }
+}
+
+
+/* some utility methods */
+void pdp_llconv_flip_top_bottom(char *data, int width, int height, int pixelsize);
+
+/* flip top & bottom */
+void pdp_packet_bitmap_flip_top_bottom(int packet)
+{
+ t_bitmap *b = (t_bitmap *)pdp_packet_subheader(packet);
+ char *d = (char *)pdp_packet_data(packet);
+ int w,h;
+ if (!pdp_packet_bitmap_isvalid(packet)) return;
+ if (!b) return;
+ w = b->width;
+ h = b->height;
+
+ switch(b->encoding){
+ case PDP_BITMAP_GREY: pdp_llconv_flip_top_bottom(d,w,h,1); break;
+ case PDP_BITMAP_RGB: pdp_llconv_flip_top_bottom(d,w,h,3); break;
+ case PDP_BITMAP_RGBA: pdp_llconv_flip_top_bottom(d,w,h,4); break;
+ default: break;
+ }
+
+}
+
+
+
+/* conversion methods */
+// image/grey/* -> bitmap/grey/*
+static int _pdp_packet_bitmap_convert_grey_to_grey8(int packet, t_pdp_symbol *dest_template)
+{
+ t_pdp *header = pdp_packet_header(packet);
+ t_image *image = pdp_packet_image_info(packet);
+ s16 *data = (s16 *)pdp_packet_data(packet);
+ u8 *new_data;
+ u32 w,h;
+ int new_p;
+
+ if (!pdp_packet_image_isvalid(packet)) return -1;
+ w = image->width;
+ h = image->height;
+
+ if (!((image->encoding == PDP_IMAGE_GREY) ||
+ (image->encoding == PDP_IMAGE_YV12))) return -1;
+
+ new_p = pdp_packet_new_bitmap_grey(w,h);
+ if (-1 == new_p) return -1;
+ new_data = (u8 *)pdp_packet_data(new_p);
+
+ /* convert image to greyscale 8 bit */
+ pdp_llconv(data,RIF_GREY______S16, new_data, RIF_GREY______U8, w, h);
+
+ return new_p;
+}
+
+static int _pdp_packet_bitmap_convert_YCrCb_to_rgb8(int packet, t_pdp_symbol *dest_template)
+{
+ t_pdp *header = pdp_packet_header(packet);
+ t_image *image = pdp_packet_image_info(packet);
+ s16 *data = (s16 *)pdp_packet_data(packet);
+ u8 *new_data;
+ u32 w,h;
+ int new_p;
+
+ if (!pdp_packet_image_isvalid(packet)) return -1;
+ w = image->width;
+ h = image->height;
+
+ if (!((image->encoding == PDP_IMAGE_YV12))) return -1;
+
+ new_p = pdp_packet_new_bitmap_rgb(w,h);
+ if (-1 == new_p) return -1;
+ new_data = (u8 *)pdp_packet_data(new_p);
+
+ /* convert image to greyscale 8 bit */
+ pdp_llconv(data,RIF_YVU__P411_S16, new_data, RIF_RGB__P____U8, w, h);
+
+ return new_p;
+}
+
+static int _pdp_packet_bitmap_convert_image_to_yv12(int packet, t_pdp_symbol *dest_template)
+{
+ t_pdp *header = pdp_packet_header(packet);
+ t_image *image = pdp_packet_image_info(packet);
+ s16 *data = (s16 *)pdp_packet_data(packet);
+ u8 *new_data;
+ u32 w,h, nbpixels;
+ int new_p;
+ int encoding = image->encoding;
+
+ if (!pdp_packet_image_isvalid(packet)) return -1;
+ w = image->width;
+ h = image->height;
+ nbpixels = w*h;
+
+ new_p = pdp_packet_new_bitmap_yv12(w,h);
+ if (-1 == new_p) return -1;
+ new_data = (u8 *)pdp_packet_data(new_p);
+
+ switch (encoding){
+ case PDP_IMAGE_YV12:
+ pdp_llconv(data, RIF_YVU__P411_S16, new_data, RIF_YVU__P411_U8, w, h);
+ break;
+ case PDP_IMAGE_GREY:
+ pdp_llconv(data, RIF_GREY______S16, new_data, RIF_GREY______U8, w, h);
+ memset(new_data + nbpixels, 0x80, nbpixels>>1);
+ break;
+ default:
+ /* not supported, $$$TODO add more */
+ pdp_packet_mark_unused(new_p);
+ new_p = -1;
+ break;
+ }
+
+ return new_p;
+
+}
+
+static int _pdp_packet_bitmap_convert_rgb8_to_YCrCb(int packet, t_pdp_symbol *dest_template)
+{
+ t_pdp *header = pdp_packet_header(packet);
+ t_bitmap *bitmap = pdp_packet_bitmap_info(packet);
+ u8 *data = (u8 *)pdp_packet_data(packet);
+ s16 *new_data;
+ u32 w,h;
+ int new_p;
+
+ w = bitmap->width;
+ h = bitmap->height;
+ new_p = pdp_packet_new_image_YCrCb(w,h);
+ if (-1 == new_p) return -1;
+ new_data = (s16 *)pdp_packet_data(new_p);
+
+ /* convert image to greyscale 8 bit */
+ pdp_llconv(data, RIF_RGB__P____U8, new_data, RIF_YVU__P411_S16, w, h);
+
+ return new_p;
+}
+
+static int _pdp_packet_bitmap_convert_rgb8_to_bitmap_YCrCb(int packet, t_pdp_symbol *dest_template)
+{
+ t_pdp *header = pdp_packet_header(packet);
+ t_bitmap *bitmap = pdp_packet_bitmap_info(packet);
+ u8 *data = (u8 *)pdp_packet_data(packet);
+ u8 *new_data;
+ u32 w,h;
+ int new_p;
+
+ w = bitmap->width;
+ h = bitmap->height;
+ new_p = pdp_packet_new_bitmap_yv12(w,h);
+ if (-1 == new_p) return -1;
+ new_data = (u8 *)pdp_packet_data(new_p);
+
+ /* convert image to greyscale 8 bit */
+ pdp_llconv(data, RIF_RGB__P____U8, new_data, RIF_YVU__P411_U8, w, h);
+
+ return new_p;
+}
+
+static int _pdp_packet_bitmap_convert_grey8_to_grey(int packet, t_pdp_symbol *dest_template)
+{
+ t_pdp *header = pdp_packet_header(packet);
+ t_bitmap *bitmap = pdp_packet_bitmap_info(packet);
+ s16 *data = (s16 *)pdp_packet_data(packet);
+ u8 *new_data;
+ u32 w,h;
+ int new_p;
+
+ w = bitmap->width;
+ h = bitmap->height;
+ new_p = pdp_packet_new_image_grey(w,h);
+ if (-1 == new_p) return -1;
+ new_data = (u8 *)pdp_packet_data(new_p);
+
+ /* convert image to greyscale 8 bit */
+ pdp_llconv(data, RIF_GREY______U8, new_data, RIF_GREY______S16, w, h);
+
+ return new_p;
+}
+static int _pdp_packet_bitmap_convert_rgb8_to_rgba8(int packet, t_pdp_symbol *dest_template)
+{
+ t_pdp *header = pdp_packet_header(packet);
+ t_bitmap *bitmap = pdp_packet_bitmap_info(packet);
+ u8 *data = (u8 *)pdp_packet_data(packet);
+ u8 *new_data;
+ int w,h, new_p, i;
+
+ w = bitmap->width;
+ h = bitmap->height;
+ new_p = pdp_packet_new_bitmap_rgba(w,h);
+ if (-1 == new_p) return -1;
+ new_data = (u8 *)pdp_packet_data(new_p);
+
+ for(i=0; i<w*h; i++){
+ new_data[4*i+0] = data[3*i + 0];
+ new_data[4*i+1] = data[3*i + 1];
+ new_data[4*i+2] = data[3*i + 2];
+ new_data[4*i+3] = 0;
+ }
+
+ return new_p;
+}
+static int _pdp_packet_bitmap_convert_rgba8_to_rgb8(int packet, t_pdp_symbol *dest_template)
+{
+ t_pdp *header = pdp_packet_header(packet);
+ t_bitmap *bitmap = pdp_packet_bitmap_info(packet);
+ u8 *data = (u8 *)pdp_packet_data(packet);
+ u8 *new_data;
+ int w,h, new_p, i;
+
+ w = bitmap->width;
+ h = bitmap->height;
+ new_p = pdp_packet_new_bitmap_rgb(w,h);
+ if (-1 == new_p) return -1;
+ new_data = (u8 *)pdp_packet_data(new_p);
+
+ for(i=0; i<w*h; i++){
+ new_data[3*i+0] = data[4*i + 0];
+ new_data[3*i+1] = data[4*i + 1];
+ new_data[3*i+2] = data[4*i + 2];
+ }
+
+ return new_p;
+}
+static int _pdp_packet_bitmap_convert_rgb8_to_mchp(int packet, t_pdp_symbol *dest_template)
+{
+ t_pdp *header = pdp_packet_header(packet);
+ t_bitmap *bitmap = pdp_packet_bitmap_info(packet);
+ u8 *data = (u8 *)pdp_packet_data(packet);
+ s16 *new_data;
+ int w,h;
+ int new_p, i, plane;
+
+ w = bitmap->width;
+ h = bitmap->height;
+ plane = w*h;
+ new_p = pdp_packet_new_image_multi(w,h,3);
+ if (-1 == new_p) return -1;
+ new_data = (s16 *)pdp_packet_data(new_p);
+
+ for(i=0; i<w*h; i++){
+ new_data[i] = ((u32)data[3*i + 0]) << 7;
+ new_data[i+plane] = ((u32)data[3*i + 1]) << 7;
+ new_data[i+plane*2] = ((u32)data[3*i + 2]) << 7;
+ }
+
+ return new_p;
+}
+
+static int _pdp_packet_bitmap_convert_yv12_to_image(int packet, t_pdp_symbol *dest_template)
+{
+ t_pdp *header = pdp_packet_header(packet);
+ t_bitmap *bitmap = pdp_packet_bitmap_info(packet);
+ u8 *data = (u8 *)pdp_packet_data(packet);
+ s16 *new_data;
+ int w,h;
+ int new_p;
+
+ w = bitmap->width;
+ h = bitmap->height;
+ new_p = pdp_packet_new_image_YCrCb(w,h);
+ new_data = pdp_packet_data(new_p);
+ if (-1 == new_p || !new_data) return -1;
+ pdp_llconv(data, RIF_YVU__P411_U8, new_data, RIF_YVU__P411_S16, w, h);
+
+ return new_p;
+}
+
+static int _pdp_packet_bitmap_convert_mchp_to_rgb8(int packet, t_pdp_symbol *dest_template)
+{
+ t_pdp *header = pdp_packet_header(packet);
+ t_image *image = (t_image *)pdp_packet_subheader(packet);
+ s16 *data = (s16 *)pdp_packet_data(packet);
+ u8 *new_data;
+ int w = image->width;
+ int h = image->height;
+ int plane = w*h;
+ int nb_channels = image->depth;
+ int new_p, i;
+
+ static inline u8 _map(s32 pixel){
+ s32 mask = ~(pixel>>16);
+ return ((pixel >> 7) & mask);
+ }
+
+ switch(nb_channels){
+ default: return -1;
+ case 1:
+ if (-1 == (new_p = pdp_packet_new_bitmap_grey(w,h))) return -1;
+ new_data = (u8*)pdp_packet_data(new_p);
+ for(i=0; i<plane; i++) new_data[i] = _map(data[i]);
+ break;
+ case 3:
+ if (-1 == (new_p = pdp_packet_new_bitmap_rgb(w,h))) return -1;
+ new_data = (u8*)pdp_packet_data(new_p);
+ for(i=0; i<plane; i++){
+ new_data[3*i+0] = _map(data[i]);
+ new_data[3*i+1] = _map(data[i+plane]);
+ new_data[3*i+2] = _map(data[i+plane*2]);
+ }
+ break;
+ case 4:
+ if (-1 == (new_p = pdp_packet_new_bitmap_rgba(w,h))) return -1;
+ new_data = (u8*)pdp_packet_data(new_p);
+ for(i=0; i<plane; i++){
+ new_data[4*i+0] = _map(data[i]);
+ new_data[4*i+1] = _map(data[i+plane]);
+ new_data[4*i+2] = _map(data[i+plane*2]);
+ new_data[4*i+3] = _map(data[i+plane*3]);
+ }
+ break;
+
+
+ }
+
+ return new_p;
+
+}
+
+static int _pdp_packet_bitmap_convert_fallback(int packet, t_pdp_symbol *dest_template)
+{
+ post("can't convert image type %s to %s",
+ pdp_packet_get_description(packet)->s_name, dest_template->s_name);
+
+ return -1;
+}
+
+static int pdp_bitmap_factory(t_pdp_symbol *type)
+{
+ return -1;
+}
+
+void pdp_bitmap_setup(void)
+{
+ t_pdp_conversion_program *program;
+
+ /* setup class object */
+ bitmap_class = pdp_class_new(pdp_gensym("bitmap/*/*"), pdp_bitmap_factory);
+
+
+ /* setup conversion programs */
+ program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_grey_to_grey8, 0);
+ pdp_type_register_conversion(pdp_gensym("image/grey/*"), pdp_gensym("bitmap/grey/*"), program);
+
+ program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_grey8_to_grey, 0);
+ pdp_type_register_conversion(pdp_gensym("bitmap/grey/*"), pdp_gensym("image/grey/*"), program);
+
+ program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_YCrCb_to_rgb8, 0);
+ pdp_type_register_conversion(pdp_gensym("image/YCrCb/*"), pdp_gensym("bitmap/rgb/*"), program);
+
+ program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_image_to_yv12, 0);
+ pdp_type_register_conversion(pdp_gensym("image/YCrCb/*"), pdp_gensym("bitmap/yv12/*"), program);
+ pdp_type_register_conversion(pdp_gensym("image/grey/*"), pdp_gensym("bitmap/yv12/*"), program);
+
+ program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_yv12_to_image, 0);
+ pdp_type_register_conversion(pdp_gensym("bitmap/yv12/*"), pdp_gensym("image/YCrCb/*"), program);
+
+ /* rgb->YCrCb converts the colour space */
+ program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_rgb8_to_YCrCb, 0);
+ pdp_type_register_conversion(pdp_gensym("bitmap/rgb/*"), pdp_gensym("image/YCrCb/*"), program);
+
+
+ /* rgb <-> multi does not convert the colour space */
+ program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_rgb8_to_mchp, 0);
+ pdp_type_register_conversion(pdp_gensym("bitmap/rgb/*"), pdp_gensym("image/multi/*"), program);
+
+ program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_mchp_to_rgb8, 0);
+ pdp_type_register_conversion(pdp_gensym("image/multi/*"), pdp_gensym("bitmap/*/*"), program);
+
+
+ /* rgb <-> rgba */
+ program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_rgb8_to_rgba8, 0);
+ pdp_type_register_conversion(pdp_gensym("bitmap/rgb/*"), pdp_gensym("bitmap/rgba/*"), program);
+ program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_rgba8_to_rgb8, 0);
+ pdp_type_register_conversion(pdp_gensym("bitmap/rgba/*"), pdp_gensym("bitmap/rgb/*"), program);
+
+
+ /* fallback rgb convertor */
+ program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_rgb8_to_YCrCb, 0);
+ pdp_type_register_conversion(pdp_gensym("bitmap/rgb/*"), pdp_gensym("image/*/*"), program);
+
+ program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_rgb8_to_bitmap_YCrCb, 0);
+ pdp_type_register_conversion(pdp_gensym("bitmap/rgb/*"), pdp_gensym("bitmap/yv12/*"), program);
+
+
+ /* fallbacks */
+ program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_fallback, 0);
+ pdp_type_register_conversion(pdp_gensym("image/*/*"), pdp_gensym("bitmap/*/*"), program);
+ pdp_type_register_conversion(pdp_gensym("bitmap/*/*"), pdp_gensym("image/*/*"), program);
+ pdp_type_register_conversion(pdp_gensym("bitmap/*/*"), pdp_gensym("bitmap/*/*"), program);
+
+}