This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/blenkernel/intern/verse_bitmap_node.c
Chris Want 5d0a207ecb Patch from GSR that a) fixes a whole bunch of GPL/BL license
blocks that were previously missed; and b) greatly increase my
ohloh stats!
2008-04-16 22:40:48 +00:00

449 lines
13 KiB
C

/**
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Contributor(s): Jiri Hnidek.
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifdef WITH_VERSE
#include <string.h>
#include "MEM_guardedalloc.h"
#include "DNA_listBase.h"
#include "BLI_dynamiclist.h"
#include "BLI_blenlib.h"
#include "BIF_verse.h"
#include "BKE_verse.h"
#include "verse.h"
/* function prototypes of static functions */
static void cb_b_dimension_set(void *user_data, VNodeID node_id, uint16 width, uint16 height, uint16 depth);
static void cb_b_layer_create(void *user_data, VNodeID node_id, VLayerID layer_id, const char *name, VNBLayerType type);
static void cb_b_layer_destroy(void *user_data, VNodeID node_id, VLayerID layer_id);
static void cb_b_tile_set(void *user_data, VNodeID node_id, VLayerID layer_id, uint16 tile_x, uint16 tile_y, uint16 z, VNBLayerType type, const VNBTile *tile);
static void change_layer_dimension(
VBitmapLayer *vblayer,
unsigned int old_width,
unsigned int old_height,
unsigned int t_old_width,
unsigned int t_old_height);
static void *alloc_verse_bitmap_layer_data(struct VBitmapLayer *vblayer);
/*
* resize/crop verse bitmap layer
*/
static void change_layer_dimension(
VBitmapLayer *vblayer,
unsigned int old_width,
unsigned int old_height,
unsigned int t_old_width,
unsigned int t_old_height)
{
struct VNode *vnode = vblayer->vnode;
unsigned int t_width = ((VBitmapData*)(vnode->data))->t_width;
unsigned int width = ((VBitmapData*)(vnode->data))->width;
unsigned int height = ((VBitmapData*)(vnode->data))->height;
unsigned int x, y, i, j;
i = j = 0;
/* "copy" old data to new data */
if(vblayer->type==VN_B_LAYER_UINT8) {
unsigned char *data = (unsigned char*)vblayer->data;
/* allocate new verse bitmap layer data */
unsigned char *new_data = (unsigned char*)alloc_verse_bitmap_layer_data(vblayer);
for(y=0; y<old_height && y<height; y++, i=y*t_width, j=y*t_old_width) {
for(x=0; x<old_width && y<width; x++, i++, j++) {
new_data[i] = data[j];
}
}
MEM_freeN(vblayer->data);
vblayer->data = new_data;
}
}
/*
* free data stored in verse bitmap layer
*/
void free_bitmap_layer_data(VBitmapLayer *vblayer)
{
struct VerseSession *session = vblayer->vnode->session;
/* free name of bitmap layer */
MEM_freeN(vblayer->name);
/* unsubscribe from verse bitmap layer */
if(session->flag & VERSE_CONNECTED)
verse_send_b_layer_unsubscribe(vblayer->vnode->id, vblayer->id);
/* free image data of bitmap layer */
if(vblayer->data) MEM_freeN(vblayer->data);
}
/*
* allocate data of verse bitmap layer
*/
static void *alloc_verse_bitmap_layer_data(VBitmapLayer *vblayer)
{
struct VNode *vnode = vblayer->vnode;
unsigned int t_width = ((VBitmapData*)(vnode->data))->t_width;
unsigned int t_height = ((VBitmapData*)(vnode->data))->t_height;
unsigned int size;
void *data;
size = t_width*t_height;
/* allocation of own data stored in verse bitmap layer */
switch (vblayer->type) {
case VN_B_LAYER_UINT1:
data = (void*)MEM_mallocN(sizeof(unsigned char)*size, "VBLayer data uint1");
break;
case VN_B_LAYER_UINT8:
data = (void*)MEM_mallocN(sizeof(unsigned char)*size, "VBLayer data uint8");
break;
case VN_B_LAYER_UINT16:
data = (void*)MEM_mallocN(sizeof(unsigned int)*size, "VBLayer data uint16");
break;
case VN_B_LAYER_REAL32:
data = (void*)MEM_mallocN(sizeof(float)*size, "VBLayer data float16");
break;
case VN_B_LAYER_REAL64:
data = (void*)MEM_mallocN(sizeof(double)*size, "VBLayer data float32");
break;
default:
data = NULL;
break;
}
return data;
}
/*
* create verse bitmap layer
*/
VBitmapLayer *create_bitmap_layer(
VNode *vnode,
VLayerID layer_id,
const char *name,
VNBLayerType type)
{
struct VBitmapLayer *vblayer;
unsigned int width = ((VBitmapData*)(vnode->data))->width;
unsigned int height = ((VBitmapData*)(vnode->data))->height;
/* allocate memory for own verse bitmap layer */
vblayer = (VBitmapLayer*)MEM_mallocN(sizeof(VBitmapLayer), "Verse Bitmap Layer");
/* verse bitmap layer will include pointer at parent verse node and own id */
vblayer->vnode = vnode;
vblayer->id = layer_id;
/* name of verse layer */
vblayer->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "Verse Bitmap Layer name");
vblayer->name[0] = '\0';
strcpy(vblayer->name, name);
/* type of data stored in verse bitmap layer */
vblayer->type = type;
/* we can allocate memory for layer data, when we know dimmension of layers; when
* we don't know it, then we will allocate this data when we will receive dimmension */
if(width==0 || height==0)
vblayer->data = NULL;
else
vblayer->data = alloc_verse_bitmap_layer_data(vblayer);
vblayer->flag = 0;
return vblayer;
}
/*
* free data of bitmap node
*/
void free_bitmap_node_data(VNode *vnode)
{
if(vnode->data) {
struct VBitmapLayer *vblayer = (VBitmapLayer*)((VBitmapData*)(vnode->data))->layers.lb.first;
/* free all VerseLayer data */
while(vblayer) {
free_bitmap_layer_data(vblayer);
vblayer = vblayer->next;
}
/* free all VerseLayers */
BLI_dlist_destroy(&(((VGeomData*)vnode->data)->layers));
}
}
/*
* create data of bitmap node
*/
VBitmapData *create_bitmap_data()
{
struct VBitmapData *vbitmap;
vbitmap = (VBitmapData*)MEM_mallocN(sizeof(VBitmapData), "Verse Bitmap Data");
BLI_dlist_init(&(vbitmap->layers));
vbitmap->queue.first = vbitmap->queue.last = NULL;
vbitmap->width = 0;
vbitmap->height = 0;
vbitmap->depth = 0;
vbitmap->image = NULL;
vbitmap->post_bitmap_dimension_set = post_bitmap_dimension_set;
vbitmap->post_bitmap_layer_create = post_bitmap_layer_create;
vbitmap->post_bitmap_layer_destroy = post_bitmap_layer_destroy;
vbitmap->post_bitmap_tile_set = post_bitmap_tile_set;
return vbitmap;
}
/*
* callback function, dimension of image was changed, it is neccessary to
* crop all layers
*/
static void cb_b_dimension_set(
void *user_data,
VNodeID node_id,
uint16 width,
uint16 height,
uint16 depth)
{
struct VerseSession *session = (VerseSession*)current_verse_session();
struct VNode *vnode;
struct VBitmapLayer *vblayer;
unsigned int old_width, old_height, t_old_width, t_old_height;
if(!session) return;
vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
if(!vnode) return;
#ifdef VERSE_DEBUG_PRINT
printf("\t cb_b_dimension_set()\n");
#endif
/* backup old width and height */
old_width = ((VBitmapData*)(vnode->data))->width;
old_height = ((VBitmapData*)(vnode->data))->height;
t_old_width = ((VBitmapData*)(vnode->data))->t_width;
t_old_height = ((VBitmapData*)(vnode->data))->t_height;
/* set up new dimension of layers */
((VBitmapData*)(vnode->data))->width = width;
((VBitmapData*)(vnode->data))->height = height;
((VBitmapData*)(vnode->data))->depth = depth;
/* we cache t_width because tiles aren't one pixel width */
if((width % VN_B_TILE_SIZE)!=0)
((VBitmapData*)(vnode->data))->t_width = (width/VN_B_TILE_SIZE + 1)*VN_B_TILE_SIZE;
else
((VBitmapData*)(vnode->data))->t_width = width;
/* we cache t_height because tiles aren't one pixel height */
if((height % VN_B_TILE_SIZE)!=0)
((VBitmapData*)(vnode->data))->t_height = (height/VN_B_TILE_SIZE + 1)*VN_B_TILE_SIZE;
else
((VBitmapData*)(vnode->data))->t_height = height;
/* crop resize all layers */
vblayer = ((VBitmapData*)vnode->data)->layers.lb.first;
while(vblayer) {
/* when this callback function received after cb_b_layer_create,
* then we have to allocate memory for verse bitmap layer data */
if(!vblayer->data) vblayer->data = alloc_verse_bitmap_layer_data(vblayer);
/* crop/resize all verse bitmap layers */
else change_layer_dimension(vblayer, old_width, old_height, t_old_width, t_old_height);
vblayer = vblayer->next;
}
/* post callback function */
((VBitmapData*)(vnode->data))->post_bitmap_dimension_set(vnode);
}
/*
* callback function, new layer channel of image was created
*/
static void cb_b_layer_create(
void *user_data,
VNodeID node_id,
VLayerID layer_id,
const char *name,
VNBLayerType type)
{
struct VerseSession *session = (VerseSession*)current_verse_session();
struct VNode *vnode;
struct VBitmapLayer *vblayer;
if(!session) return;
vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
if(!vnode) return;
#ifdef VERSE_DEBUG_PRINT
printf("\t cb_b_layer_create()\n");
#endif
/* when no layer exists, then new layer will be created */
vblayer = create_bitmap_layer(vnode, layer_id, name, type);
/* add verse bitmap layer to list of layers */
BLI_dlist_add_item_index(&((VBitmapData*)vnode->data)->layers, vblayer, layer_id);
/* post callback function */
((VBitmapData*)(vnode->data))->post_bitmap_layer_create(vblayer);
}
/*
* callback function, existing layer of image was destroyed
*/
static void cb_b_layer_destroy(
void *user_data,
VNodeID node_id,
VLayerID layer_id)
{
struct VerseSession *session = (VerseSession*)current_verse_session();
struct VNode *vnode;
struct VBitmapLayer *vblayer;
if(!session) return;
/* find node of this layer*/
vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
if(!vnode) return;
vblayer = (VBitmapLayer*)BLI_dlist_find_link(&(((VBitmapData*)vnode->data)->layers), layer_id);
if(!vblayer) return;
#ifdef VERSE_DEBUG_PRINT
printf("\t cb_b_layer_destroy()\n");
#endif
/* remove verse bitmap layer from list of layers */
BLI_dlist_rem_item(&(((VBitmapData*)vnode->data)->layers), layer_id);
/* post callback function */
((VBitmapData*)(vnode->data))->post_bitmap_layer_destroy(vblayer);
/* free data of verse bitmap layer */
free_bitmap_layer_data(vblayer);
/* free verse bitmap layer */
MEM_freeN(vblayer);
}
/*
* callback function, small part (8x8 pixels) was changed
*/
static void cb_b_tile_set(
void *user_data,
VNodeID node_id,
VLayerID layer_id,
uint16 tile_x,
uint16 tile_y,
uint16 z,
VNBLayerType type,
const VNBTile *tile)
{
struct VerseSession *session = (VerseSession*)current_verse_session();
struct VNode *vnode;
struct VBitmapLayer *vblayer;
unsigned int x, y, xs, ys, width, height, t_height, t_width, i, j;
if(!session) return;
/* try to find verse node in dynamic list nodes */
vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
if(!vnode) return;
/* try to find verse bitmap layer in list of layers */
vblayer = (VBitmapLayer*)BLI_dlist_find_link(&(((VBitmapData*)vnode->data)->layers), layer_id);
if(!vblayer) return;
/* we have to have allocated memory for bitmap layer */
if(!vblayer->data) return;
width = ((VBitmapData*)vnode->data)->width;
height = ((VBitmapData*)vnode->data)->height;
/* width of verse image including all tiles */
t_height = ((VBitmapData*)vnode->data)->t_height;
/* height of verse image including all tiles */
t_width = ((VBitmapData*)vnode->data)->t_width;
#ifdef VERSE_DEBUG_PRINT
printf("\t cb_b_tile_set()\n");
#endif
xs = tile_x*VN_B_TILE_SIZE;
ys = tile_y*VN_B_TILE_SIZE;
/* initial position in one dimension vblayer->data (y_start*width + x_start) */
i = ys*t_width + xs;
/* intial position in one dimension tile array */
j = 0;
if(type==VN_B_LAYER_UINT8) {
unsigned char *data = (unsigned char*)vblayer->data;
for(y=ys; y<ys+VN_B_TILE_SIZE && y<height; y++, i=y*t_width+xs)
for(x=xs; x<xs+VN_B_TILE_SIZE && x<width; x++, i++, j++)
data[i] = (unsigned char)tile->vuint8[j];
}
/* post callback function */
((VBitmapData*)(vnode->data))->post_bitmap_tile_set(vblayer, xs, ys);
}
/*
* set up all callbacks functions for image nodes
*/
void set_bitmap_callbacks(void)
{
/* dimension (size) of bitmap was set up or changes (image will be croped) */
verse_callback_set(verse_send_b_dimensions_set, cb_b_dimension_set, NULL);
/* new layer (chanell) of image was added or created */
verse_callback_set(verse_send_b_layer_create, cb_b_layer_create, NULL);
/* existing layer was destroyed */
verse_callback_set(verse_send_b_layer_destroy, cb_b_layer_destroy, NULL);
/* some tile (small part 8x8 pixels of image was changed) */
verse_callback_set(verse_send_b_tile_set, cb_b_tile_set, NULL);
}
#endif