Update of /cvsroot/pure-data/externals/pdp/modules/image_special In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6756/modules/image_special
Added Files: Makefile README pdp_array.c pdp_chrot.c pdp_cog.c pdp_grey2mask.c pdp_histo.c pdp_scale.c pdp_scan.c pdp_scanxy.c pdp_scope.c Log Message: checking in pdp 0.12.4 from http://zwizwa.fartit.com/pd/pdp/pdp-0.12.4.tar.gz
--- NEW FILE: pdp_histo.c --- /* * Pure Data Packet module. * Copyright (c) 2003 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_base.h" #include <math.h>
struct _pdp_histo; typedef void (*t_histo_proc)(struct _pdp_histo *);
typedef struct _pdp_histo { t_object x_obj; t_int x_logN; t_symbol *x_array_sym; t_float x_scale; t_int x_debug; t_int x_sample_size; /* pointcloud size */ t_histo_proc x_process_method; /* what to do with the histogram */ t_outlet *x_outlet0; int x_matrix_output;
/* the packet */ int x_packet0;
/* packet data */ short int *x_data; int x_width; int x_height; int x_nb_pixels;
/* histo data for processor: these are stored on the stack */ int *x_histo;
} t_pdp_histo;
static int round_up_2log(int i) { int l = 0; i--; while (i) { i >>= 1; l++; } //post("log is %d, 2^n is %d", l, 1 << l);
l = (l < 16) ? l : 15; return l; }
static void dump_to_array(t_pdp_histo *x) { float *vec; int nbpoints; t_garray *a; int i; int *histo = x->x_histo; int N = 1 << (x->x_logN); float scale = 1.0f / (float)(x->x_nb_pixels);
/* dump to array if possible */ if (!x->x_array_sym){ }
/* check if array is valid */ else if (!(a = (t_garray *)pd_findbyclass(x->x_array_sym, garray_class))){ post("pdp_histo: %s: no such array", x->x_array_sym->s_name); } /* get data */ else if (!garray_getfloatarray(a, &nbpoints, &vec)){ post("pdp_histo: %s: bad template", x->x_array_sym->s_name); } /* scale and dump in array */ else{
N = (nbpoints < N) ? nbpoints : N; for (i=0; i<N; i++) vec[i] = (float)(histo[i]) * scale * x->x_scale; //garray_redraw(a); }
}
static void get_sampleset(t_pdp_histo *x, int log_tmp_size, int threshold) { int N = 1 << log_tmp_size; int mask = N-1; int index, nbpoints, i; t_atom a[2]; double scalex = 1.0f / (double)(x->x_width); double scaley = 1.0f / (double)(x->x_height); t_symbol *s = gensym("list"); int matrix_packet; double *mat_data;
/* store the offsets of the points in a in an oversized array the oversizing is to eliminate a division and to limit the searching for a free location after a random index is generated */
int offset[N];
/* reset the array */ memset(offset, -1, N * sizeof(int));
/* get the coordinates of the tempsize brightest points and store them in a random location in the hash */ for (i=0; i<x->x_nb_pixels; i++){ if (x->x_data[i] >= threshold){ /* get a random index */ int ri = random(); //int ri = 0; /* find an empty spot to store it */ while (-1 != offset[ri & mask]) ri++; offset[ri & mask] = i; } }
/* repack the array to get the requested sample size at the start */ index = 0; nbpoints = 0; while (nbpoints < x->x_sample_size){ while (-1 == offset[index]) index++; // ffwd to next nonepty slot offset[nbpoints++] = offset[index++]; // move slot }
/* MATRIX OUTPUT */ if (x->x_matrix_output){
matrix_packet = pdp_packet_new_matrix(x->x_sample_size, 2, PDP_MATRIX_TYPE_RDOUBLE); mat_data = pdp_packet_data(matrix_packet); if (mat_data){ /* build the cluster data struct */ for (i=0; i<x->x_sample_size; i++){ mat_data[2*i] = ((double)(offset[i] % x->x_width)) * scalex; mat_data[2*i+1] = ((double)(offset[i] / x->x_width)) * scaley; }
pdp_pass_if_valid(x->x_outlet0, &matrix_packet); pdp_packet_mark_unused(x->x_packet0); x->x_packet0 = -1; } }
/* IMAGE OUTPUT */ else {
/* get rw copy */ pdp_packet_replace_with_writable(&x->x_packet0); x->x_data = pdp_packet_data(x->x_packet0);
/* mark output packet samples */ if (x->x_data){ memset(x->x_data, 0, 2*x->x_nb_pixels); for (i=0; i<x->x_sample_size; i++){ x->x_data[offset[i]] = 0x7fff; } }
/* send packet to left outlet */ pdp_pass_if_valid(x->x_outlet0, &x->x_packet0); }
}
static void get_brightest(t_pdp_histo *x) { int i; int *histo = x->x_histo; int N = 1 << (x->x_logN);
int index, nsamps;
/* check requested size */ if (x->x_sample_size > x->x_nb_pixels){ post("WARNING: more samples requested than pixels in image"); x->x_sample_size = x->x_nb_pixels; }
/* find limiting index */ index = N; nsamps = 0; while (nsamps < x->x_sample_size){ index--; nsamps += histo[index]; }
/* status report */ if (x->x_debug){ post("found %d samples between h[%d] and h[%d]", nsamps, index, N-1); }
/* get a representative set from the candidates the tempbuf is the rounded log of the nb of samples + 1 so it is at least 50% sparse */ get_sampleset(x, round_up_2log(nsamps) + 1, index << (15-x->x_logN));
}
static void _pdp_histo_perform(t_pdp_histo *x) { short int *pp; int N = 1 << x->x_logN; int nbpixels = x->x_width * x->x_height, i;
int histo[N];
/* init */ for (i=0; i<N; i++) histo[i] = 0;
/* build histo */ for (i=0; i<nbpixels; i++){ int index = x->x_data[i] >> (15 - x->x_logN); if (index < 0) index = 0; /* negative -> zero */ histo[index]++; }
/* save the histo stack location */ x->x_histo = histo;
/* print it */ if (x->x_debug){ post("histogram:"); for (i=0; i<N; i++){ fprintf(stderr, "%d\t", histo[i]); if (!(i % 10)) post(""); } post(""); }
/* call the processor */ x->x_process_method(x);
}
// packet is an image/*/* packet or invalid */ static void pdp_histo_perform(t_pdp_histo *x) { t_pdp *header0 = pdp_packet_header(x->x_packet0); void *data0 = pdp_packet_data(x->x_packet0); if (!header0 || !data0) return;
x->x_width = header0->info.image.width; x->x_height = header0->info.image.height; x->x_nb_pixels = x->x_width * x->x_height; x->x_data = data0;
_pdp_histo_perform(x); }
static void pdp_histo_input_0(t_pdp_histo *x, t_symbol *s, t_floatarg f) { int packet = (int)f;
/* register */ if (s == gensym("register_rw")){ /* replace if not compatible or we are not interpolating */ pdp_packet_mark_unused(x->x_packet0); x->x_packet0 = pdp_packet_convert_ro(packet, pdp_gensym("image/grey/*")); }
if (s == gensym("process")){ pdp_histo_perform(x); }
}
static void pdp_histo_samplesize(t_pdp_histo *x, t_floatarg f) { int i = (int)f; if (i > 0) x->x_sample_size = i; }
static void pdp_histo_scale(t_pdp_histo *x, t_floatarg f){x->x_scale = f;}
static void pdp_histo_size(t_pdp_histo *x, t_floatarg f) { int i = (int)f; if (i < 1) return; x->x_logN = round_up_2log(i); }
static void pdp_histo_array(t_pdp_histo *x, t_symbol *s) { //post("setting symbol %x", s); x->x_array_sym = s; }
static void pdp_histo_free(t_pdp_histo *x) { pdp_packet_mark_unused(x->x_packet0); }
t_class *pdp_histo_class;
void *pdp_histo_new(t_floatarg f) {
t_pdp_histo *x = (t_pdp_histo *)pd_new(pdp_histo_class); if (f == 0.0f) f = 64; pdp_histo_size(x, f); x->x_packet0 = -1; x->x_debug = 0; x->x_sample_size = 16; return (void *)x; }
void *pdp_histo_array_new(t_symbol *s, t_float f, t_float f2) { t_pdp_histo *x = (t_pdp_histo *)pdp_histo_new(f); if (f2 == 0.0f) f2 = 1.0f; pdp_histo_scale(x, f2); pdp_histo_array(x, s); x->x_process_method = dump_to_array; return (void *)x; }
void *pdp_histo_sample_new(t_float nbsamples, t_float histosize) { t_pdp_histo *x; if (histosize == 0.0f) histosize = 256.0f; x = (t_pdp_histo *)pdp_histo_new(histosize); if (nbsamples == 0.0f) nbsamples = 16.0f; pdp_histo_samplesize(x, nbsamples); x->x_process_method = get_brightest; x->x_outlet0 = outlet_new(&x->x_obj, gensym("anything")); x->x_matrix_output = 0;
inlet_new((t_object *)x, (t_pd *)&x->x_obj, gensym("float"), gensym("nbpoints"));
return (void *)x; }
void *pdp_histo_sample_matrix_new(t_float nbsamples, t_float histosize) { t_pdp_histo *x = pdp_histo_sample_new(nbsamples, histosize); if (x) x->x_matrix_output = 1; return (void *)x; }
#ifdef __cplusplus extern "C" { #endif
void pdp_histo_setup(void) {
pdp_histo_class = class_new(gensym("pdp_histo"), (t_newmethod)pdp_histo_array_new, (t_method)pdp_histo_free, sizeof(t_pdp_histo), 0, A_DEFSYMBOL, A_DEFFLOAT, A_DEFFLOAT, A_NULL);
class_addcreator((t_newmethod)pdp_histo_sample_new, gensym("pdp_pointcloud"), A_DEFFLOAT, A_DEFFLOAT, A_NULL); class_addcreator((t_newmethod)pdp_histo_sample_matrix_new, gensym("pdp_pointcloud_matrix"), A_DEFFLOAT, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_histo_class, (t_method)pdp_histo_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_histo_class, (t_method)pdp_histo_size, gensym("size"), A_FLOAT, A_NULL); class_addmethod(pdp_histo_class, (t_method)pdp_histo_size, gensym("scale"), A_FLOAT, A_NULL); class_addmethod(pdp_histo_class, (t_method)pdp_histo_array, gensym("array"), A_SYMBOL, A_NULL); class_addmethod(pdp_histo_class, (t_method)pdp_histo_samplesize, gensym("nbpoints"), A_FLOAT, A_NULL); }
#ifdef __cplusplus } #endif
--- NEW FILE: pdp_scale.c --- /* * Pure Data Packet module. * 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_resample.h"
typedef struct pdp_scale_struct { t_object x_obj; t_float x_f;
t_outlet *x_outlet0;
int x_packet0; int x_packet1; int x_dropped; int x_queue_id;
unsigned int x_width; unsigned int x_height; int x_quality;
} t_pdp_scale;
static void pdp_scale_process_yv12(t_pdp_scale *x) { t_pdp *header0 = pdp_packet_header(x->x_packet0); t_pdp *header1 = pdp_packet_header(x->x_packet1); void *data0 = pdp_packet_data (x->x_packet0); void *data1 = pdp_packet_data (x->x_packet1);
unsigned int src_w = header0->info.image.width; unsigned int src_h = header0->info.image.height;
unsigned int dst_w = header1->info.image.width; unsigned int dst_h = header1->info.image.height;
short int *src_image = (short int *)data0; short int *dst_image = (short int *)data1;
unsigned int src_size = src_w*src_h; unsigned int src_voffset = src_size; unsigned int src_uoffset = src_size + (src_size>>2);
unsigned int dst_size = dst_w*dst_h; unsigned int dst_voffset = dst_size; unsigned int dst_uoffset = dst_size + (dst_size>>2);
if (x->x_quality){ pdp_resample_scale_bilin(src_image, dst_image, src_w, src_h, dst_w, dst_h); pdp_resample_scale_bilin(src_image+src_voffset, dst_image+dst_voffset, src_w>>1, src_h>>1, dst_w>>1, dst_h>>1); pdp_resample_scale_bilin(src_image+src_uoffset, dst_image+dst_uoffset, src_w>>1, src_h>>1, dst_w>>1, dst_h>>1); } else{ pdp_resample_scale_nn(src_image, dst_image, src_w, src_h, dst_w, dst_h); pdp_resample_scale_nn(src_image+src_voffset, dst_image+dst_voffset, src_w>>1, src_h>>1, dst_w>>1, dst_h>>1); pdp_resample_scale_nn(src_image+src_uoffset, dst_image+dst_uoffset, src_w>>1, src_h>>1, dst_w>>1, dst_h>>1); }
return; }
static void pdp_scale_process_grey(t_pdp_scale *x) {
t_pdp *header0 = pdp_packet_header(x->x_packet0); t_pdp *header1 = pdp_packet_header(x->x_packet1); void *data0 = pdp_packet_data (x->x_packet0); void *data1 = pdp_packet_data (x->x_packet1);
unsigned int src_w = header0->info.image.width; unsigned int src_h = header0->info.image.height;
unsigned int dst_w = header1->info.image.width; unsigned int dst_h = header1->info.image.height;
short int *src_image = (short int *)data0; short int *dst_image = (short int *)data1;
if (x->x_quality) pdp_resample_scale_bilin(src_image, dst_image, src_w, src_h, dst_w, dst_h); else pdp_resample_scale_nn(src_image, dst_image, src_w, src_h, dst_w, dst_h);
return;
}
static void pdp_scale_sendpacket(t_pdp_scale *x) { /* delete source packet */ pdp_packet_mark_unused(x->x_packet0); x->x_packet0 = -1;
/* unregister and propagate if valid dest packet */ pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1); }
static void pdp_scale_process(t_pdp_scale *x) { t_pdp_procqueue *q = pdp_queue_get_queue(); t_pdp *header0 = pdp_packet_header(x->x_packet0);
/* check data packets */
if ((header0) && (PDP_IMAGE == header0->type)){
/* if dims are equal, just send the packet */ if ((header0->info.image.width == x->x_width) && (header0->info.image.height == x->x_height)){ x->x_packet1 = x->x_packet0; x->x_packet0 = -1; pdp_scale_sendpacket(x); return; }
/* type hub */ switch(header0->info.image.encoding){
case PDP_IMAGE_YV12: x->x_packet1 = pdp_packet_new_image_YCrCb(x->x_width, x->x_height); if(x->x_packet1 == -1){ post("pdp_scale: can't allocate packet"); return; } pdp_procqueue_add(q, x, pdp_scale_process_yv12, pdp_scale_sendpacket, &x->x_queue_id); break;
case PDP_IMAGE_GREY: x->x_packet1 = pdp_packet_new_image_grey(x->x_width, x->x_height); if(x->x_packet1 == -1){ post("pdp_scale: can't allocate packet"); return; } pdp_procqueue_add(q, x, pdp_scale_process_grey, pdp_scale_sendpacket, &x->x_queue_id); break;
default: break; /* don't know the type, so dont process */ } }
}
static void pdp_scale_input_0(t_pdp_scale *x, t_symbol *s, t_floatarg f) {
int p = (int)f; int passes, i;
if (s== gensym("register_rw")) x->x_dropped = pdp_packet_copy_ro_or_drop(&x->x_packet0, p);
if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)){
/* add the process method and callback to the process queue */ pdp_scale_process(x);
}
}
static void pdp_scale_width(t_pdp_scale *x, t_floatarg f) { int i = (int)f; if (i < 32) i = 32; x->x_width = i; }
static void pdp_scale_height(t_pdp_scale *x, t_floatarg f) { int i = (int)f; if (i < 32) i = 32; x->x_height = i; }
static void pdp_scale_dim(t_pdp_scale *x, t_floatarg w, t_floatarg h) { pdp_scale_width(x, w); pdp_scale_height(x, h); }
static void pdp_scale_quality(t_pdp_scale *x, t_floatarg f) { if (f==0) x->x_quality = 0; if (f==1) x->x_quality = 1; }
t_class *pdp_scale_class;
void pdp_scale_free(t_pdp_scale *x) { t_pdp_procqueue *q = pdp_queue_get_queue(); pdp_procqueue_finish(q, x->x_queue_id); pdp_packet_mark_unused(x->x_packet0); pdp_packet_mark_unused(x->x_packet1); }
void *pdp_scale_new(t_floatarg fw, t_floatarg fh) { t_pdp_scale *x = (t_pdp_scale *)pd_new(pdp_scale_class);
x->x_outlet0 = outlet_new(&x->x_obj, &s_anything);
x->x_packet0 = -1; x->x_packet1 = -1; x->x_queue_id = -1;
if ((fw != 0.0f) && (fh != 0.0f)) pdp_scale_dim(x, fw, fh); else pdp_scale_dim(x, 320, 240);
pdp_scale_quality(x, 1);
return (void *)x; }
#ifdef __cplusplus extern "C" { #endif
void pdp_scale_setup(void) {
pdp_scale_class = class_new(gensym("pdp_scale"), (t_newmethod)pdp_scale_new, (t_method)pdp_scale_free, sizeof(t_pdp_scale), 0, A_DEFFLOAT, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_scale_class, (t_method)pdp_scale_quality, gensym("quality"), A_FLOAT, A_NULL); class_addmethod(pdp_scale_class, (t_method)pdp_scale_width, gensym("width"), A_FLOAT, A_NULL); class_addmethod(pdp_scale_class, (t_method)pdp_scale_height, gensym("height"), A_FLOAT, A_NULL); class_addmethod(pdp_scale_class, (t_method)pdp_scale_dim, gensym("dim"), A_FLOAT, A_FLOAT, A_NULL); class_addmethod(pdp_scale_class, (t_method)pdp_scale_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
}
#ifdef __cplusplus } #endif
--- NEW FILE: pdp_scanxy.c --- /* * Pure Data Packet module. * 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 <math.h>
typedef struct pdp_scanxy_struct { t_object x_obj; t_float x_f;
t_outlet *x_outlet0; t_outlet *x_outlet1;
int x_packet0; int x_packet1;
int x_interpolate;
} t_pdp_scanxy;
static t_int *pdp_scanxy_perform(t_int *w) {
t_pdp_scanxy *x = (t_pdp_scanxy *)(w[1]); t_int n = (t_int)(w[2]); t_float *inx = (float *)(w[3]); t_float *iny = (float *)(w[4]); t_float *out = (float *)(w[5]);
/* check if valid image */ if (-1 == x->x_packet0){ while (n--) *out++ = 0; return (w+6); } else{
t_pdp *header0 = pdp_packet_header(x->x_packet0); short int *data0 = (short int *)pdp_packet_data (x->x_packet0); short int *data1 = (short int *)pdp_packet_data (x->x_packet1); int width = (float)header0->info.image.width; int height = (float)header0->info.image.height; int i;
float scale = 1.0f / 32767.0f; float scalein = 0x10000;
if (x->x_interpolate && (-1 != x->x_packet1)){ float a_old = 1.0f; float a_new = 0.0f; float a_inc = 1.0f / (float)n; float old, new;
while(n--){ int xxx = ((((int)(scalein * *inx++)) & 0xffff) * width) >> 16; int yyy = ((((int)(scalein * *iny++)) & 0xffff) * height) >> 16; int offset = yyy*width+xxx; new = ((float)(data0[offset])) * scale; old = ((float)(data1[offset])) * scale; *out++ = a_old * old + a_new * new; a_new += a_inc; a_old -= a_inc; }
pdp_packet_mark_unused(x->x_packet1); x->x_packet1 = -1; } else{ while(n--){ int xxx = ((((int)(scalein * *inx++)) & 0xffff) * width) >> 16; int yyy = ((((int)(scalein * *iny++)) & 0xffff) * height) >> 16; int offset = yyy*width+xxx; *out++ = ((float)(data0[offset])) * scale; } }
return (w+6);
} }
static void pdp_scanxy_input_0(t_pdp_scanxy *x, t_symbol *s, t_floatarg f) { int packet = (int)f;
/* register */ if (s== gensym("register_ro")){ t_pdp *header = pdp_packet_header(packet); if (!header) return; if (PDP_IMAGE != header->type) return; if ((header->info.image.encoding != PDP_IMAGE_YV12) && (header->info.image.encoding != PDP_IMAGE_GREY)) return;
/* replace if not compatible or we are not interpolating */ if (!x->x_interpolate || (!pdp_packet_image_compat(x->x_packet0, packet))){ pdp_packet_mark_unused(x->x_packet0); x->x_packet0 = pdp_packet_copy_ro(packet); } /* otherwize keep the old one */ else{ pdp_packet_mark_unused(x->x_packet1); x->x_packet1 = x->x_packet0; x->x_packet0 = pdp_packet_copy_ro(packet); } }
/* pass packet */ if (s== gensym("process")){ //if (-1 != x->x_packet0) outlet_pdp (x->x_outlet0, x->x_packet0); }
}
static void pdp_scanxy_dsp (t_pdp_scanxy *x, t_signal **sp) { dsp_add(pdp_scanxy_perform, 5, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec);
}
static void pdp_scanxy_interpolate(t_pdp_scanxy *x, t_floatarg f) { if (0.0 == f){ x->x_interpolate = 0; pdp_packet_mark_unused(x->x_packet1); } if (1.0 == f) x->x_interpolate = 1; }
static void pdp_scanxy_free(t_pdp_scanxy *x) { pdp_packet_mark_unused(x->x_packet0); }
t_class *pdp_scanxy_class;
void *pdp_scanxy_new(void) { t_pdp_scanxy *x = (t_pdp_scanxy *)pd_new(pdp_scanxy_class);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal")); x->x_outlet1 = outlet_new(&x->x_obj, &s_signal); x->x_packet0 = -1; x->x_packet1 = -1;
pdp_scanxy_interpolate(x, 0);
return (void *)x; }
#ifdef __cplusplus extern "C" { #endif
void pdp_scanxy_setup(void) {
pdp_scanxy_class = class_new(gensym("pdp_scanxy~"), (t_newmethod)pdp_scanxy_new, (t_method)pdp_scanxy_free, sizeof(t_pdp_scanxy), 0, A_NULL);
CLASS_MAINSIGNALIN(pdp_scanxy_class, t_pdp_scanxy, x_f);
class_addmethod(pdp_scanxy_class, (t_method)pdp_scanxy_interpolate, gensym("interpolate"), A_FLOAT, A_NULL); class_addmethod(pdp_scanxy_class, (t_method)pdp_scanxy_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); class_addmethod(pdp_scanxy_class, (t_method)pdp_scanxy_dsp, gensym("dsp"), A_NULL);
}
#ifdef __cplusplus } #endif
--- NEW FILE: pdp_grey2mask.c --- /* * Pure Data Packet module. * 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. * */
/* this module converts a greyscale image or the luma channel of a colour image to a colour image intensity mask, usable for multiplication */
#include "pdp.h" #include "pdp_resample.h"
typedef struct pdp_grey2mask_struct { t_object x_obj; t_float x_f;
t_outlet *x_outlet0;
int x_packet0; int x_dropped; int x_queue_id;
} t_pdp_grey2mask;
static void pdp_grey2mask_process_grey(t_pdp_grey2mask *x) { t_pdp *header = pdp_packet_header(x->x_packet0); short int *data = (short int *)pdp_packet_data (x->x_packet0); t_pdp *newheader = 0; short int *newdata = 0; int newpacket = -1;
unsigned int w = header->info.image.width; unsigned int h = header->info.image.height;
unsigned int size = w*h; unsigned int totalnbpixels = size; unsigned int u_offset = size; unsigned int v_offset = size + (size>>2);
unsigned int row, col;
newpacket = pdp_packet_new_image_YCrCb(w, h); newheader = pdp_packet_header(newpacket); newdata = (short int *)pdp_packet_data(newpacket);
/* copy luma channel */ memcpy(newdata, data, size * sizeof(s16));
/* subsample luma -> chroma channel */ pdp_resample_halve(data, newdata+u_offset, w, h);
/* copy this to the other chroma channel */ memcpy(newdata+v_offset, newdata+u_offset, (size>>2)*sizeof(s16));
/* delete source packet and replace with new packet */ pdp_packet_mark_unused(x->x_packet0); x->x_packet0 = newpacket; return; }
static void pdp_grey2mask_process_yv12(t_pdp_grey2mask *x) { /* process only the luminance channel */ pdp_grey2mask_process_grey(x); }
static void pdp_grey2mask_process(t_pdp_grey2mask *x) { int encoding; t_pdp *header = 0;
/* check if image data packets are compatible */ if ( (header = pdp_packet_header(x->x_packet0)) && (PDP_IMAGE == header->type)){
/* pdp_grey2mask_process inputs and write into active inlet */ switch(pdp_packet_header(x->x_packet0)->info.image.encoding){
case PDP_IMAGE_YV12: pdp_grey2mask_process_yv12(x); break;
case PDP_IMAGE_GREY: pdp_grey2mask_process_grey(x); break;
default: /* don't know the type, so dont pdp_grey2mask_process */ break; } } }
static void pdp_grey2mask_sendpacket(t_pdp_grey2mask *x) { /* unregister and propagate if valid packet */ pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet0); }
static void pdp_grey2mask_input_0(t_pdp_grey2mask *x, t_symbol *s, t_floatarg f) {
int p = (int)f;
if (s== gensym("register_ro")) x->x_dropped = pdp_packet_copy_ro_or_drop(&x->x_packet0, p);
if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)){
/* add the process method and callback to the process queue */
//pdp_queue_add(x, pdp_grey2mask_process, pdp_grey2mask_sendpacket, &x->x_queue_id); // since the process method creates a packet, this is not processed in the thread // $$$TODO: fix this pdp_grey2mask_process(x); pdp_grey2mask_sendpacket(x); }
}
static void pdp_grey2mask_free(t_pdp_grey2mask *x) { t_pdp_procqueue *q = pdp_queue_get_queue(); pdp_procqueue_finish(q, x->x_queue_id); pdp_packet_mark_unused(x->x_packet0);
}
t_class *pdp_grey2mask_class;
void *pdp_grey2mask_new(void) { int i;
t_pdp_grey2mask *x = (t_pdp_grey2mask *)pd_new(pdp_grey2mask_class);
x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); x->x_packet0 = -1; x->x_queue_id = -1;
return (void *)x; }
#ifdef __cplusplus extern "C" { #endif
void pdp_grey2mask_setup(void) {
pdp_grey2mask_class = class_new(gensym("pdp_grey2mask"), (t_newmethod)pdp_grey2mask_new, (t_method)pdp_grey2mask_free, sizeof(t_pdp_grey2mask), 0, A_NULL);
class_addmethod(pdp_grey2mask_class, (t_method)pdp_grey2mask_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
}
#ifdef __cplusplus } #endif
--- NEW FILE: pdp_scan.c --- /* * Pure Data Packet module. * 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_mmx.h" #include <math.h>
#define PDP_SCAN_COSTABLE_SIZE 1024 static float pdp_cos[PDP_SCAN_COSTABLE_SIZE];
typedef struct pdp_scan_struct { t_object x_obj; t_float x_f;
t_outlet *x_outlet0; t_outlet *x_outlet1;
float x_centerx; float x_centery; float x_sizeh; float x_sizev;
int x_packet0; int x_packet1;
int x_interpolate;
} t_pdp_scan;
static t_int *pdp_scan_perform(t_int *w) {
t_pdp_scan *x = (t_pdp_scan *)(w[1]); t_int n = (t_int)(w[2]); t_float *in = (float *)(w[3]); t_float *out = (float *)(w[4]);
/* check if valid image */ if (-1 == x->x_packet0){ while (n--) *out++ = 0; return (w+5); } else{
t_pdp *header0 = pdp_packet_header(x->x_packet0); short int *data0 = (short int *)pdp_packet_data (x->x_packet0); short int *data1 = (short int *)pdp_packet_data (x->x_packet1); int width = (float)header0->info.image.width; float widthm1 = (float)header0->info.image.width - 1; float heightm1 = (float)header0->info.image.height - 1; int i;
float scale = 1.0f / 32767.0f;
if (x->x_interpolate && (-1 != x->x_packet1)){ float a_old = 1.0f; float a_new = 0.0f; float a_inc = 1.0f / (float)n; float old, new;
while(n--){ float phase = *in++; int iphase = (int)(phase * PDP_SCAN_COSTABLE_SIZE); float c = pdp_cos[iphase & (PDP_SCAN_COSTABLE_SIZE - 1)]; float s = pdp_cos[(iphase - (PDP_SCAN_COSTABLE_SIZE>>1)) & (PDP_SCAN_COSTABLE_SIZE - 1)]; int xxx = (int)((x->x_centerx + x->x_sizeh * c) * widthm1); int yyy = (int)((x->x_centery + x->x_sizev * c) * heightm1); int offset = yyy*width+xxx; new = ((float)(data0[offset])) * scale; old = ((float)(data1[offset])) * scale; *out++ = a_old * old + a_new * new; a_new += a_inc; a_old -= a_inc; }
pdp_packet_mark_unused(x->x_packet1); x->x_packet1 = -1; } else{ while(n--){ float phase = *in++; int iphase = (int)(phase * PDP_SCAN_COSTABLE_SIZE); float c = pdp_cos[iphase & (PDP_SCAN_COSTABLE_SIZE - 1)]; float s = pdp_cos[(iphase - (PDP_SCAN_COSTABLE_SIZE>>1)) & (PDP_SCAN_COSTABLE_SIZE - 1)]; int xxx = (int)((x->x_centerx + x->x_sizeh * c) * widthm1); int yyy = (int)((x->x_centery + x->x_sizev * c) * heightm1); *out++ = ((float)(data0[yyy*width+xxx])) * scale; } }
return (w+5);
} }
static void pdp_scan_input_0(t_pdp_scan *x, t_symbol *s, t_floatarg f) { int packet = (int)f;
/* register */ if (s== gensym("register_ro")){ t_pdp *header = pdp_packet_header(packet); if (!header) return; if (PDP_IMAGE != header->type) return; if ((header->info.image.encoding != PDP_IMAGE_YV12) && (header->info.image.encoding != PDP_IMAGE_GREY)) return;
/* replace if not compatible or we are not interpolating */ if (!x->x_interpolate || (!pdp_packet_image_compat(x->x_packet0, packet))){ pdp_packet_mark_unused(x->x_packet0); x->x_packet0 = pdp_packet_copy_ro(packet); } /* otherwize keep the old one */ else{ pdp_packet_mark_unused(x->x_packet1); x->x_packet1 = x->x_packet0; x->x_packet0 = pdp_packet_copy_ro(packet); } }
/* pass packet */ if (s== gensym("process")){ //if (-1 != x->x_packet0) outlet_pdp (x->x_outlet0, x->x_packet0); }
}
static void pdp_scan_dsp (t_pdp_scan *x, t_signal **sp) { dsp_add(pdp_scan_perform, 4, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
}
static void pdp_scan_interpolate(t_pdp_scan *x, t_floatarg f) { if (0.0 == f){ x->x_interpolate = 0; pdp_packet_mark_unused(x->x_packet1); } if (1.0 == f) x->x_interpolate = 1; }
static void pdp_scan_free(t_pdp_scan *x) { pdp_packet_mark_unused(x->x_packet0); }
t_class *pdp_scan_class;
void *pdp_scan_new(void) { t_pdp_scan *x = (t_pdp_scan *)pd_new(pdp_scan_class);
//x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); x->x_outlet1 = outlet_new(&x->x_obj, &s_signal); x->x_packet0 = -1; x->x_packet1 = -1;
x->x_centerx = 0.5f; x->x_centery = 0.5f; x->x_sizeh = 0.3; x->x_sizev = 0.3;
pdp_scan_interpolate(x, 0);
return (void *)x; }
#ifdef __cplusplus extern "C" { #endif
void pdp_scan_setup(void) { int i; for (i=0; i<PDP_SCAN_COSTABLE_SIZE; i++) pdp_cos[i] = cos((double)(i) * 2 * M_PI / PDP_SCAN_COSTABLE_SIZE);
pdp_scan_class = class_new(gensym("pdp_scan~"), (t_newmethod)pdp_scan_new, (t_method)pdp_scan_free, sizeof(t_pdp_scan), 0, A_NULL);
CLASS_MAINSIGNALIN(pdp_scan_class, t_pdp_scan, x_f);
class_addmethod(pdp_scan_class, (t_method)pdp_scan_interpolate, gensym("interpolate"), A_FLOAT, A_NULL); class_addmethod(pdp_scan_class, (t_method)pdp_scan_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); class_addmethod(pdp_scan_class, (t_method)pdp_scan_dsp, gensym("dsp"), A_NULL);
}
#ifdef __cplusplus } #endif
--- NEW FILE: Makefile --- current: all_modules
include ../../Makefile.config
PDP_MOD = pdp_chrot.o pdp_grey2mask.o pdp_scale.o pdp_scan.o \ pdp_scanxy.o pdp_scope.o \ pdp_cog.o pdp_array.o $(PDP_IMAGE_SPECIAL)
# build special case image (and sound) processing modules all_modules: $(PDP_MOD)
clean: rm -f *~ rm -f *.o
--- NEW FILE: pdp_cog.c --- /* * Pure Data Packet module. * Copyright (c) 2003 by Johannes Taelman johannes.taelman@rug.ac.be * API updates 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_base.h" #include <math.h>
typedef struct pdp_cog_struct { t_object x_obj; t_float x_f;
t_outlet *x_outlet0; t_outlet *x_outlet1; t_outlet *x_outlet2; t_outlet *x_outlet3; t_outlet *x_outlet4;
int x_packet0; int x_threshold; int x_do_thresholding; } t_pdp_cog;
static void _pdp_cog_perform(t_pdp_cog *x, int width, int height, short int *data0) { short int *pp; int nbpixels;
int y; int h,v; int rowsums[width]; int columnsums[height];
float vsum,vvar,vcog,vstd; float hsum,hvar,hcog,hstd;
pp=data0;
nbpixels=width*height;
for (h=0;h<width;h++) columnsums[h]=0;
/* create column & row sums from thresholded data */ if (x->x_do_thresholding){ for (v=0;v<height;v++){ int rs=0; for (h=0;h<width;h++){ int d=*pp++; d=(d>x->x_threshold) ? d : ((d<-x->x_threshold)?(-d):0); columnsums[h]+= d; rs+=d; } rowsums[v]=rs; } }
/* don't perform thresholding */ else{ for (v=0;v<height;v++){ int rs=0; for (h=0;h<width;h++){ int d=*pp++; columnsums[h]+= d; rs+=d; } rowsums[v]=rs; } }
/* compute vertical mean and standard dev */ vsum=1; vvar=height*height/4; vcog=height/2; for (v=0;v<height;v++){ float d=rowsums[v]; vsum+=d; vcog+=d*v; } vcog/=vsum; for (v=0;v<height;v++){ float d=rowsums[v]; float f=v-vcog; vvar+=d*f*f; } vstd=sqrt(vvar/vsum)/height;
/* compute horizontal meaan and standard dev */ hsum=1; hvar=width*width/4; hcog=width/2; for (h=0;h<width;h++){ float d=columnsums[h]; hsum+=d; hcog+=d*h; } hcog/=hsum; for (h=0;h<width;h++){ float d=columnsums[h]; float f=h-hcog; hvar+=d*f*f; } hstd=sqrt(hvar/hsum)/width;
/* pass it on */ outlet_float(x->x_outlet4,vstd); outlet_float(x->x_outlet3,hstd); outlet_float(x->x_outlet2,vcog/height); outlet_float(x->x_outlet1,hcog/width); outlet_float(x->x_outlet0,(1.0f / (float)(0x7fff)) * hsum/(height*width)); }
// packet is an image/*/* packet or invalid */ static void pdp_cog_perform(t_pdp_cog *x) { t_pdp *header0 = pdp_packet_header(x->x_packet0); void *data0 = pdp_packet_data(x->x_packet0); if (!header0 || !data0) return;
_pdp_cog_perform(x, header0->info.image.width, header0->info.image.height, data0); }
static void pdp_cog_input_0(t_pdp_cog *x, t_symbol *s, t_floatarg f) { int packet = (int)f;
/* register */ if (s == gensym("register_ro")){ /* replace if not compatible or we are not interpolating */ pdp_packet_mark_unused(x->x_packet0); x->x_packet0 = pdp_packet_convert_ro(packet, pdp_gensym("image/*/*")); }
if (s == gensym("process")){ pdp_cog_perform(x); }
}
static void pdp_cog_threshold(t_pdp_cog *x, t_floatarg f) { x->x_threshold=(int) (f * ((float) 0x7fff)); }
static void pdp_cog_free(t_pdp_cog *x) { pdp_packet_mark_unused(x->x_packet0); }
t_class *pdp_cog_class;
void *pdp_cog_new(void) {
t_pdp_cog *x = (t_pdp_cog *)pd_new(pdp_cog_class);
x->x_outlet0 = outlet_new(&x->x_obj, &s_float); x->x_outlet1 = outlet_new(&x->x_obj, &s_float); x->x_outlet2 = outlet_new(&x->x_obj, &s_float); x->x_outlet3 = outlet_new(&x->x_obj, &s_float); x->x_outlet4 = outlet_new(&x->x_obj, &s_float);
x->x_packet0 = -1; x->x_do_thresholding = 0;
return (void *)x; }
void *pdp_cog_abs_thresh_new(t_floatarg f) { t_pdp_cog *x = (t_pdp_cog *)pdp_cog_new(); inlet_new((void *)x, &x->x_obj.ob_pd, gensym("float"),gensym("threshold")); pdp_cog_threshold(x, f); x->x_do_thresholding = 1; return (void *)x; }
#ifdef __cplusplus extern "C" { #endif
void pdp_cog_setup(void) {
pdp_cog_class = class_new(gensym("pdp_cog"), (t_newmethod)pdp_cog_new, (t_method)pdp_cog_free, sizeof(t_pdp_cog), 0,A_NULL);
class_addcreator((t_newmethod)pdp_cog_abs_thresh_new, gensym("pdp_cog_abs_thresh"), A_DEFFLOAT, A_NULL);
class_addmethod(pdp_cog_class, (t_method)pdp_cog_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_cog_class, (t_method)pdp_cog_threshold, gensym("threshold"),A_DEFFLOAT, A_NULL); }
#ifdef __cplusplus } #endif
--- NEW FILE: README --- This directory contains image processors that don't fit into the basic and io categories.
--- NEW FILE: pdp_array.c --- /* * Pure Data Packet module. * Copyright (c) 2003 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 <math.h>
#include "pdp.h" #include "pdp_base.h"
typedef struct _pdp_array { t_object x_obj; t_symbol *x_array_sym; t_outlet *x_outlet; // for array->pdp t_int x_rows;
/* the packet */ int x_packet0;
} t_pdp_array;
static void pdp_array_bang(t_pdp_array *x) { post("not implemented"); }
static void pdp_array_input_0(t_pdp_array *x, t_symbol *s, t_floatarg f) { int packet = (int)f;
/* register */ if (s == gensym("register_ro")){ /* replace if not compatible or we are not interpolating */ pdp_packet_mark_unused(x->x_packet0); x->x_packet0 = pdp_packet_convert_ro(packet, pdp_gensym("image/grey/*")); }
/* process */ if (s == gensym("process")){ float *vec; int nbpoints; t_garray *a; t_pdp *header = pdp_packet_header(x->x_packet0); short int *data = pdp_packet_data(x->x_packet0); if (!header || !data) return;
/* dump to array if possible */ if (!x->x_array_sym){ }
/* check if array is valid */ else if (!(a = (t_garray *)pd_findbyclass(x->x_array_sym, garray_class))){ post("pdp_array: %s: no such array", x->x_array_sym->s_name); } /* get data */ else if (!garray_getfloatarray(a, &nbpoints, &vec)){ post("pdp_array: %s: bad template", x->x_array_sym->s_name); } /* scale and dump in array */ else{ int i; int w = header->info.image.width; int h = header->info.image.height; int N = w*h; N = (nbpoints < N) ? nbpoints : N;
/* scan rows */ if (x->x_rows){ for (i=0; i<N; i++) vec[i] = (float)data[i] * (1.0f / (float)0x8000); } /* scan columns */ else{ for (i=0; i<N; i++) { int x = i / h; int y = i % h; vec[i] = (float)data[x+(h-y-1)*w] * (1.0f / (float)0x8000); } } //garray_redraw(a); }
} }
static void pdp_array_array(t_pdp_array *x, t_symbol *s) { //post("setting symbol %x", s); x->x_array_sym = s; x->x_packet0 = -1; }
static void pdp_array_free(t_pdp_array *x) { pdp_packet_mark_unused(x->x_packet0); }
t_class *pdp_array2grey_class; t_class *pdp_grey2array_class;
void *pdp_array2grey_new(t_symbol *s, t_symbol *r) { t_pdp_array *x = (t_pdp_array *)pd_new(pdp_array2grey_class); pdp_array_array(x, s); return (void *)x; }
void *pdp_grey2array_new(t_symbol *s, t_symbol *r) { t_pdp_array *x = (t_pdp_array *)pd_new(pdp_grey2array_class); pdp_array_array(x, s); if (r == gensym("rows")){ x->x_rows = 1; post("pdp_grey2array: scanning rows"); } else { x->x_rows = 0; post("pdp_grey2array: scanning columns"); } return (void *)x; }
#ifdef __cplusplus extern "C" { #endif
void pdp_array_setup(void) {
pdp_array2grey_class = class_new(gensym("pdp_array2grey"), (t_newmethod)pdp_array2grey_new, (t_method)pdp_array_free, sizeof(t_pdp_array), 0, A_DEFSYMBOL, A_DEFSYMBOL, A_NULL);
pdp_grey2array_class = class_new(gensym("pdp_grey2array"), (t_newmethod)pdp_grey2array_new, (t_method)pdp_array_free, sizeof(t_pdp_array), 0, A_DEFSYMBOL, A_DEFSYMBOL, A_NULL);
/* packet input */ class_addmethod(pdp_grey2array_class, (t_method)pdp_array_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
/* bang method */ class_addmethod(pdp_array2grey_class, (t_method)pdp_array_bang, gensym("bang"), A_NULL);
/* bookkeeping */ class_addmethod(pdp_array2grey_class, (t_method)pdp_array_array, gensym("array"), A_SYMBOL, A_NULL); class_addmethod(pdp_grey2array_class, (t_method)pdp_array_array, gensym("array"), A_SYMBOL, A_NULL);
}
#ifdef __cplusplus } #endif
--- NEW FILE: pdp_scope.c --- /* * Pure Data Packet module. * 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 <string.h>
#define BUFSIZE 2048
typedef struct pdp_scope_data { short int random_seed[4];
}t_pdp_scope_data;
typedef struct pdp_scope_struct { t_object x_obj; t_float x_f;
t_outlet *x_outlet0;
t_pdp_scope_data *x_data; int x_packet0; int x_queue_id;
int x_pdp_image_type;
unsigned int x_width; unsigned int x_height;
float *x_buffer; int x_needle;
} t_pdp_scope;
void pdp_scope_type(t_pdp_scope *x, t_symbol *s) { if (gensym("yv12") == s) {x->x_pdp_image_type = PDP_IMAGE_YV12; return;} if (gensym("grey") == s) {x->x_pdp_image_type = PDP_IMAGE_GREY; return;}
x->x_pdp_image_type = -1;
}
static void pdp_scope_createpacket_yv12(t_pdp_scope *x) { t_pdp *header;
unsigned int w = x->x_width; unsigned int h = x->x_height;
unsigned int size = w*h; unsigned int totalnbpixels = size + (size >> 1); unsigned int packet_size = totalnbpixels << 1;
x->x_packet0 = pdp_packet_new_image_YCrCb(w, h); if(x->x_packet0 == -1){ post("pdp_scope: can't allocate packet"); return; } header = pdp_packet_header(x->x_packet0); memset(pdp_packet_data(x->x_packet0), 0, packet_size);
}
static void pdp_scope_generate_yv12(t_pdp_scope *x) { unsigned int w = x->x_width; unsigned int h = x->x_height; unsigned int size = w*h; unsigned int totalnbpixels = size + (size >> 1); short int *data = (short int *) pdp_packet_data(x->x_packet0);
unsigned int i; int offset = x->x_needle; int val; unsigned int y; float fh2 = (float)(h/2);
if (!data) return;
for (i=0; i<w; i++){ y = (h/2) + (int)(fh2 * -x->x_buffer[(offset - w + i) & (BUFSIZE - 1)]); if (y>=h) y = h-1;
data[i + y*w] = 0x7fff; }
return;
}
static void pdp_scope_createpacket_grey(t_pdp_scope *x) { t_pdp *header; short int *data;
unsigned int w = x->x_width; unsigned int h = x->x_height;
unsigned int size = w*h; unsigned int totalnbpixels = size; unsigned int packet_size = totalnbpixels << 1;
/* create new packet */ x->x_packet0 = pdp_packet_new_image_grey(w,h); if(x->x_packet0 == -1){ post("pdp_scope: can't allocate packet"); return; }
header = pdp_packet_header(x->x_packet0); data = (short int *) pdp_packet_data(x->x_packet0);
memset(pdp_packet_data(x->x_packet0), 0, packet_size);
}
static void pdp_scope_generate_grey(t_pdp_scope *x) { unsigned int w = x->x_width; unsigned int h = x->x_height; unsigned int totalnbpixels = x->x_width * x->x_height; short int *data = (short int *) pdp_packet_data(x->x_packet0);
unsigned int i; int offset = x->x_needle; int val; unsigned int y; float fh2 = (float)(h/2);
if (!data) return;
for (i=0; i<w; i++){ y = (h/2) + (int)(fh2 * -x->x_buffer[(offset - w + i) & (BUFSIZE - 1)]); if (y>=h) y = h-1;
data[i + y*w] = 0x7fff; }
return; }
static void pdp_scope_sendpacket(t_pdp_scope *x) { /* propagate if valid */ pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet0); }
static void pdp_scope_bang(t_pdp_scope *x) {
int encoding;
/* if we have an active packet, don't do anything */ if (-1 != x->x_packet0) return;
switch(x->x_pdp_image_type){
case PDP_IMAGE_YV12: pdp_scope_createpacket_yv12(x); // don't create inside thread!!! pdp_scope_generate_yv12(x); pdp_scope_sendpacket(x); //pdp_queue_add(x, pdp_scope_generate_yv12, pdp_scope_sendpacket, &x->x_queue_id); break;
case PDP_IMAGE_GREY: pdp_scope_createpacket_grey(x); // don't create inside thread!!! pdp_scope_generate_grey(x); pdp_scope_sendpacket(x); //pdp_queue_add(x, pdp_scope_generate_grey, pdp_scope_sendpacket, &x->x_queue_id); break;
default: break; }
/* release the packet */
}
static void pdp_scope_dim(t_pdp_scope *x, t_floatarg w, t_floatarg h) { if (w<32.0f) w = 32.0f; if (h<32.0f) h = 32.0f;
x->x_width = (unsigned int)w; x->x_height = (unsigned int)h; }
static void pdp_scope_free(t_pdp_scope *x) {
/* remove callback from process queue */ t_pdp_procqueue *q = pdp_queue_get_queue(); pdp_procqueue_finish(q, x->x_queue_id);
/* tidy up */ pdp_packet_mark_unused(x->x_packet0); pdp_dealloc(x->x_data);
} static t_int *pdp_scope_perform(t_int *w) {
t_float *in = (float *)(w[3]); t_pdp_scope *x = (t_pdp_scope *)(w[1]); t_int n = (t_int)(w[2]); t_int i;
t_int offset = x->x_needle;
for (i=0; i<n; i++) x->x_buffer[(offset+i)&(BUFSIZE-1)] = in[i];
x->x_needle = (offset + n ) & (BUFSIZE - 1);
return (w+4);
} static void pdp_scope_dsp(t_pdp_scope *x, t_signal **sp) { dsp_add(pdp_scope_perform, 3, x, sp[0]->s_n, sp[0]->s_vec);
}
t_class *pdp_scope_class;
void *pdp_scope_new(void) { int i;
t_pdp_scope *x = (t_pdp_scope *)pd_new(pdp_scope_class);
x->x_outlet0 = outlet_new(&x->x_obj, &s_anything);
x->x_packet0 = -1; x->x_queue_id = -1; x->x_width = 320; x->x_height = 240; x->x_f = 0.0;
x->x_data = (t_pdp_scope_data *)pdp_alloc(sizeof(t_pdp_scope_data));
pdp_scope_type(x, gensym("yv12"));
x->x_buffer = (float *)pdp_alloc(sizeof(float) * BUFSIZE); x->x_needle = 0;
return (void *)x; }
#ifdef __cplusplus extern "C" { #endif
void pdp_scope_setup(void) {
pdp_scope_class = class_new(gensym("pdp_scope~"), (t_newmethod)pdp_scope_new, (t_method)pdp_scope_free, sizeof(t_pdp_scope), 0, A_NULL);
CLASS_MAINSIGNALIN(pdp_scope_class, t_pdp_scope, x_f);
class_addmethod(pdp_scope_class, (t_method)pdp_scope_type, gensym("type"), A_SYMBOL, A_NULL); class_addmethod(pdp_scope_class, (t_method)pdp_scope_dim, gensym("dim"), A_FLOAT, A_FLOAT, A_NULL); class_addmethod(pdp_scope_class, (t_method)pdp_scope_bang, gensym("bang"), A_NULL); class_addmethod(pdp_scope_class, (t_method)pdp_scope_dsp, gensym("dsp"), 0); }
#ifdef __cplusplus } #endif
--- NEW FILE: pdp_chrot.c --- /* * Pure Data Packet module. * 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_base.h" #include <math.h>
typedef struct pdp_chrot_struct { t_pdp_base x_base;
float x_matrix[4]; void *x_crot2d;
} t_pdp_chrot;
static void pdp_chrot_process(t_pdp_chrot *x) { int packet; t_pdp *header; void *data; unsigned int w,h,size,v_offset; short int *idata;
/* get packet & info */ packet = pdp_base_get_packet(x, 0); header = pdp_packet_header(packet); data = pdp_packet_data (packet);
/* only process if we have a vlid yv12 image */ if ((header) && (PDP_IMAGE == header->type) && (PDP_IMAGE_YV12 == header->info.image.encoding)){
w = header->info.image.width; h = header->info.image.height;
size = w*h; v_offset = size; idata = (short int *)data;
/* color rotation for 2 colour planes */ pdp_imageproc_crot2d_process(x->x_crot2d, idata + v_offset, w>>1, h>>1);
} return; }
static void pdp_chrot_setelement(t_pdp_chrot *x, int element, float f) { x->x_matrix[element] = f; }
static void pdp_chrot_angle_radians(t_pdp_chrot *x, t_floatarg angle) { float c = cos(angle); float s = sin(angle);
pdp_chrot_setelement(x, 0, c); pdp_chrot_setelement(x, 1, s); pdp_chrot_setelement(x, 2, -s); pdp_chrot_setelement(x, 3, c);
pdp_imageproc_crot2d_setmatrix(x->x_crot2d, x->x_matrix); }
static void pdp_chrot_angle_degrees(t_pdp_chrot *x, t_floatarg angle) { pdp_chrot_angle_radians(x, (angle * (M_PI / 180.f)));
}
static void pdp_chrot_free(t_pdp_chrot *x) { pdp_base_free(x); pdp_imageproc_crot2d_delete(x->x_crot2d); }
t_class *pdp_chrot_class;
void *pdp_chrot_new(t_floatarg f) { t_pdp_chrot *x = (t_pdp_chrot *)pd_new(pdp_chrot_class);
pdp_base_init(x); pdp_base_add_gen_inlet(x, gensym("float"), gensym("angle")); pdp_base_add_pdp_outlet(x); pdp_base_set_process_method(x, (t_pdp_method)pdp_chrot_process);
x->x_crot2d = pdp_imageproc_crot2d_new(); pdp_chrot_angle_radians(x, 0.0f);
return (void *)x; }
#ifdef __cplusplus extern "C" { #endif
void pdp_chrot_setup(void) {
pdp_chrot_class = class_new(gensym("pdp_chrot"), (t_newmethod)pdp_chrot_new, (t_method)pdp_chrot_free, sizeof(t_pdp_chrot), 0, A_DEFFLOAT, A_NULL);
pdp_base_setup(pdp_chrot_class); class_addmethod(pdp_chrot_class, (t_method)pdp_chrot_angle_degrees, gensym("angle"), A_DEFFLOAT, A_NULL);
}
#ifdef __cplusplus } #endif