initial check-in

This commit is contained in:
Paul Fitzpatrick
2018-04-27 17:34:35 -04:00
parent ba7dbcb02e
commit d713f8e069
36 changed files with 5599 additions and 0 deletions

6
.dockerignore Normal file
View File

@@ -0,0 +1,6 @@
*~
build
stash
old
templates
Dockerfile

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
build

12
CMakeLists.txt Normal file
View File

@@ -0,0 +1,12 @@
cmake_minimum_required(VERSION 2.6)
PROJECT(makesweet)
SET(BUILD_SHARED_LIBS ON)
# Find YARP. Point the YARP_DIR environment variable at your build.
FIND_PACKAGE(YARP)
INCLUDE_DIRECTORIES(${YARP_INCLUDE_DIRS})
LINK_LIBRARIES(${YARP_LIBRARIES})
ADD_SUBDIRECTORY(src)

35
Dockerfile Normal file
View File

@@ -0,0 +1,35 @@
FROM ubuntu:14.04
RUN \
apt-get update; \
apt-get install -y build-essential
RUN \
cd tmp; \
apt-get update; \
apt-get install -y cmake3 wget; \
wget https://github.com/robotology/yarp/archive/v2.3.72.tar.gz; \
tar xzvf v2.3.72.tar.gz; \
mkdir yarp; \
cd yarp; \
cmake -DSKIP_ACE=TRUE ../yarp-*; \
make
RUN \
apt-get update; \
apt-get install -y libgd2-noxpm-dev libzzip-dev
COPY . /makesweet/
RUN \
cd /makesweet; \
mkdir build; \
cd build; \
cmake -DYARP_DIR=/tmp/yarp ..; \
make
RUN \
echo "#!/bin/bash" > /reanimator; \
echo "cd /share" >> /reanimator; \
echo "/makesweet/build/bin/reanimator \"\$@\"" >> /reanimator; \
chmod u+x /reanimator

0
README
View File

9
README.md Normal file
View File

@@ -0,0 +1,9 @@
Putting pictures in animated templates.
```
docker pull paulfitz/makesweet
docker run -v $PWD:/share paulfitz/makesweet /reanimator \
--zip templates/billboard-cityscape.zip \
--in templates/frog.jpg \
--gif animation.gif
```

15
src/CMakeLists.txt Normal file
View File

@@ -0,0 +1,15 @@
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
ADD_LIBRARY(msmap msmap.h msmap.c)
ADD_LIBRARY(filer Filer.cpp Filer.h)
TARGET_LINK_LIBRARIES(filer gd zzip)
ADD_EXECUTABLE(reanimator reanimator.cpp Prop.h Prop.cpp Pixer.h
Mapping.h Repository.h Repository.cpp Render.h Render.cpp
Input.h Input.cpp Inputs.h Renders.h Renders.cpp
GifAnim.h GifAnim.cpp
gd_topal.c)
TARGET_LINK_LIBRARIES(reanimator filer)

7
src/Dbg.h Normal file
View File

@@ -0,0 +1,7 @@
#ifndef MS_DBG_INC
#define MS_DBG_INC
extern int __ms_verbose;
#define dbg_printf if (__ms_verbose) printf
#endif

604
src/Filer.cpp Normal file
View File

@@ -0,0 +1,604 @@
#define USE_ZIP
#include "Filer.h"
#include "Dbg.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gd.h>
#include <string>
#ifdef USE_ZIP
#include <zzip/zzip.h>
#endif
#define R gdTrueColorGetRed
#define G gdTrueColorGetGreen
#define B gdTrueColorGetBlue
#define A gdTrueColorGetAlpha
using namespace std;
using namespace yarp::sig;
using namespace yarp::sig::file;
using namespace yarp::sig::draw;
typedef struct dpIOCtx
{
gdIOCtx ctx;
FILE *f;
}
fileIOCtx;
gdIOCtx *newFileCtx (FILE * f);
static int fileGetbuf (gdIOCtx *, void *, int);
static int filePutbuf (gdIOCtx *, const void *, int);
static void filePutchar (gdIOCtx *, int);
static int fileGetchar (gdIOCtx * ctx);
static int fileSeek (struct gdIOCtx *, const int);
static long fileTell (struct gdIOCtx *);
static void gdFreeFileCtx (gdIOCtx * ctx);
gdIOCtx *myNewFileCtx (FILE * f) {
fileIOCtx *ctx;
ctx = (fileIOCtx *) new fileIOCtx;
if (ctx == NULL)
{
return NULL;
}
ctx->f = f;
ctx->ctx.getC = fileGetchar;
ctx->ctx.putC = filePutchar;
ctx->ctx.getBuf = fileGetbuf;
ctx->ctx.putBuf = filePutbuf;
ctx->ctx.tell = fileTell;
ctx->ctx.seek = fileSeek;
ctx->ctx.gd_free = gdFreeFileCtx;
return (gdIOCtx *) ctx;
}
static void
gdFreeFileCtx (gdIOCtx * ctx)
{
delete ctx;
}
static int
filePutbuf (gdIOCtx * ctx, const void *buf, int size)
{
fileIOCtx *fctx;
fctx = (fileIOCtx *) ctx;
return fwrite (buf, 1, size, fctx->f);
}
static int
fileGetbuf (gdIOCtx * ctx, void *buf, int size)
{
fileIOCtx *fctx;
fctx = (fileIOCtx *) ctx;
return (fread (buf, 1, size, fctx->f));
}
static void
filePutchar (gdIOCtx * ctx, int a)
{
unsigned char b;
fileIOCtx *fctx;
fctx = (fileIOCtx *) ctx;
b = a;
putc (b, fctx->f);
}
static int
fileGetchar (gdIOCtx * ctx)
{
fileIOCtx *fctx;
fctx = (fileIOCtx *) ctx;
return getc (fctx->f);
}
static int
fileSeek (struct gdIOCtx *ctx, const int pos)
{
fileIOCtx *fctx;
fctx = (fileIOCtx *) ctx;
return (fseek (fctx->f, pos, SEEK_SET) == 0);
}
static long
fileTell (struct gdIOCtx *ctx)
{
fileIOCtx *fctx;
fctx = (fileIOCtx *) ctx;
return ftell (fctx->f);
}
#ifdef USE_ZIP
#include <zzip/zzip.h>
typedef struct dpZipIOCtx
{
gdIOCtx ctx;
ZZIP_FILE *f;
}
zipIOCtx;
gdIOCtx *newZipCtx (ZZIP_FILE * f);
static int zipGetbuf (gdIOCtx *, void *, int);
static int zipPutbuf (gdIOCtx *, const void *, int);
static void zipPutchar (gdIOCtx *, int);
static int zipGetchar (gdIOCtx * ctx);
static int zipSeek (struct gdIOCtx *, const int);
static long zipTell (struct gdIOCtx *);
static void gdFreeZipCtx (gdIOCtx * ctx);
gdIOCtx *myNewZipCtx (ZZIP_FILE * f) {
zipIOCtx *ctx;
ctx = (zipIOCtx *) new zipIOCtx;
if (ctx == NULL)
{
return NULL;
}
ctx->f = f;
ctx->ctx.getC = zipGetchar;
ctx->ctx.putC = zipPutchar;
ctx->ctx.getBuf = zipGetbuf;
ctx->ctx.putBuf = zipPutbuf;
ctx->ctx.tell = zipTell;
ctx->ctx.seek = zipSeek;
ctx->ctx.gd_free = gdFreeZipCtx;
return (gdIOCtx *) ctx;
}
static void
gdFreeZipCtx (gdIOCtx * ctx)
{
delete ctx;
}
static int
zipPutbuf (gdIOCtx * ctx, const void *buf, int size)
{
zipIOCtx *fctx;
fctx = (zipIOCtx *) ctx;
fprintf(stderr,"CANNOT WRITE TO ZIP\n");
exit(1);
return -1;
}
static int
zipGetbuf (gdIOCtx * ctx, void *buf, int size)
{
zipIOCtx *fctx;
fctx = (zipIOCtx *) ctx;
return (zzip_fread (buf, 1, size, fctx->f));
}
static void
zipPutchar (gdIOCtx * ctx, int a)
{
fprintf(stderr,"CANNOT WRITE TO ZIP\n");
exit(1);
}
static int
zipGetchar (gdIOCtx * ctx)
{
zipIOCtx *fctx;
fctx = (zipIOCtx *) ctx;
char buf;
int r = (zzip_fread (&buf, 1, 1, fctx->f));
if (r<0) return -1;
return buf;
}
static int
zipSeek (struct gdIOCtx *ctx, const int pos)
{
zipIOCtx *fctx;
fctx = (zipIOCtx *) ctx;
return (zzip_seek (fctx->f, pos, SEEK_SET) == 0);
}
static long
zipTell (struct gdIOCtx *ctx)
{
zipIOCtx *fctx;
fctx = (zipIOCtx *) ctx;
return zzip_tell (fctx->f);
}
#endif
/*
static const char * ispng(const char * name, int & result) {
FILE * png = fopen(name, "rb");
char buf[32];
if (!png) {
return "ispng: Failure in fopen";
}
if (8 != fread(buf, 1, 8, png)) {
fclose(png);
return "ispng: couldn't read magic number";
}
result = !memcmp(buf, "\x89PNG\x0D\x0A\x1A\x0A", 8);
fclose(png);
return 0;
}
static const char * isgif(const char * name, int & result) {
FILE * gif = fopen(name, "rb");
char buf[32];
if (!gif) {
return "isgif: Failure in fopen";
}
if (6 != fread(buf, 1, 6, gif)) {
fclose(gif);
return "isgif: couldn't read magic number";
}
result = !memcmp(buf, "GIF89a", 6);
fclose(gif);
return 0;
}
static const char * isjpg(const char * name, int & result) {
FILE * jpg = fopen(name, "rb");
char buf[32];
if (!jpg) {
return "isjpg: Failure in fopen";
}
if (2 != fread(buf, 1, 2, jpg)) {
fclose(jpg);
return "isjpg: couldn't read magic number";
}
result = !memcmp(buf, "\xFF\xD8", 2);
fclose(jpg);
return 0;
}
*/
static const char * ispng(gdIOCtx * ctx, int & result) {
char buf[32];
ctx->seek(ctx,0);
if (8 != ctx->getBuf(ctx, buf, 8)) {
return "ispng: couldn't read magic number";
}
result = !memcmp(buf, "\x89PNG\x0D\x0A\x1A\x0A", 8);
return 0;
}
static const char * isgif(gdIOCtx * ctx, int & result) {
char buf[32];
ctx->seek(ctx,0);
if (6 != ctx->getBuf(ctx, buf, 6)) {
return "isgif: couldn't read magic number";
}
result = !memcmp(buf, "GIF89a", 6);
return 0;
}
static const char * isjpg(gdIOCtx * ctx, int & result) {
char buf[32];
ctx->seek(ctx,0);
if (2 != ctx->getBuf(ctx, buf, 2)) {
return "isjpg: couldn't read magic number";
}
result = !memcmp(buf, "\xFF\xD8", 2);
return 0;
}
std::string Filer::load_text(const char *fname) {
gdImagePtr img = NULL;
gdIOCtx *ctx = NULL;
FILE *fd = NULL;
#ifdef USE_ZIP
ZZIP_DIR *zip = (ZZIP_DIR *)src_zip;
ZZIP_FILE *zd = NULL;
if (zip) {
zd = zzip_file_open(zip,fname,ZZIP_CASELESS);
if (!zd) {
dbg_printf("Cannot open %s in zip\n", fname);
return "";
} else {
dbg_printf("Got %s from zip\n", fname);
}
ctx = myNewZipCtx(zd);
}
#endif
if (!ctx) {
fd = fopen(fname,"r");
if (fd==NULL) {
fprintf(stderr,"Cannot open %s\n", fname);
return "";
}
ctx = myNewFileCtx(fd);
}
std::string result;
if (ctx) {
ctx->seek(ctx,0);
char buf[1024];
int r = 0;
do {
r = ctx->getBuf(ctx,buf,sizeof(buf));
if (r>0) {
result.append(buf,r);
}
} while (r>0);
ctx->gd_free(ctx);
}
if (fd) {
fclose(fd);
}
#ifdef USE_ZIP
if (zd) {
zzip_file_close(zd);
}
#endif
return result;
}
static gdImagePtr gd_load(const char *fname, void *src_zip) {
gdImagePtr img = NULL;
gdIOCtx *ctx = NULL;
FILE *fd = NULL;
#ifdef USE_ZIP
ZZIP_DIR *zip = (ZZIP_DIR *)src_zip;
ZZIP_FILE *zd = NULL;
if (zip) {
zd = zzip_file_open(zip,fname,ZZIP_CASELESS);
if (!zd) {
fprintf(stderr,"Cannot open %s in zip\n", fname);
exit(1);
} else {
dbg_printf("Got %s from zip\n", fname);
}
ctx = myNewZipCtx(zd);
}
#endif
if (!ctx) {
fd = fopen(fname,"r");
if (fd==NULL) {
fprintf(stderr,"Cannot open %s\n", fname);
return NULL;
}
ctx = myNewFileCtx(fd);
}
if (ctx) {
int png = 0;
int jpg = 0;
int gif = 0;
ispng(ctx,png);
if (!png) {
isjpg(ctx,jpg);
if (!jpg) {
isgif(ctx,gif);
}
}
if (!(png||jpg||gif)) {
fprintf(stderr,"Cannot process %s\n", fname);
return NULL;
}
ctx->seek(ctx,0);
if (png) {
img = gdImageCreateFromPngCtx(ctx);
} else if (jpg) {
img = gdImageCreateFromJpegCtx(ctx);
} else if (gif) {
img = gdImageCreateFromGifCtx(ctx);
}
ctx->gd_free(ctx);
}
bool found = false;
if (img!=NULL) {
found = true;
gdImageSaveAlpha(img, 1);
gdImageAlphaBlending(img, 0);
}
if (fd) {
fclose(fd);
}
#ifdef USE_ZIP
if (zd) {
zzip_file_close(zd);
}
#endif
if (img) {
dbg_printf(" loaded image of size %dx%d\n", img->sx, img->sy);
}
return img;
}
template <class T>
static bool yarp_load(const char *fname,
yarp::sig::ImageOf<T>& src, void *src_zip) {
bool found = false;
gdImagePtr img = gd_load(fname,src_zip);
if (img!=NULL) {
found = true;
src.resize(img->sx,img->sy);
IMGFOR(src,x,y) {
int pi = gdImageGetPixel(img,x,y);
int r = R(pi);
int g = G(pi);
int b = B(pi);
int a = A(pi);
a *= 2;
if (a>253) a = 255;
src(x,y) = T(r,g,b,255-a);
}
gdFree(img);
}
return found;
}
bool Filer::load(const char *fname,
yarp::sig::ImageOf<yarp::sig::PixelRgba>& src) {
return yarp_load(fname,src,src_zip);
}
bool Filer::load(const char *fname,
yarp::sig::ImageOf<yarp::sig::PixelBgra>& src) {
return yarp_load(fname,src,src_zip);
}
template <class T>
static bool yarp_save(const char *fname,
yarp::sig::ImageOf<T>& src) {
string n = fname;
bool is_png = false;
bool is_jpg = false;
if (n.rfind(".png")==n.length()-4) {
is_png = true;
}
if (n.rfind(".jpg")==n.length()-4) {
is_jpg = true;
}
gdImageStruct access;
ImageOf<PixelBgra> idest;
gdImagePtr im2;
im2 = gdImageCreateTrueColor(src.width(),src.height());
access = *im2;
gdImageDestroy(im2);
gdImageSaveAlpha(&access, 1);
gdImageAlphaBlending(&access, 0);
idest.copy(src);
IMGFOR(idest,x,y) {
PixelBgra& pix = idest(x,y);
pix.a = 255-pix.a;
pix.a /= 2;
}
access.tpixels = (int**)idest.getRowArray();
access.sx = idest.width();
access.sy = idest.height();
FILE *test = fopen(fname,"wb");
if (is_png) {
gdImagePng(&access,test);
} else if (is_jpg) {
gdImageJpeg(&access,test,95);
} else {
fprintf(stderr,"unknown image format\n");
exit(1);
}
fclose(test);
return true;
}
bool Filer::save(const char *fname,
yarp::sig::ImageOf<yarp::sig::PixelRgba>& src) {
return yarp_save(fname,src);
}
bool Filer::save(const char *fname,
yarp::sig::ImageOf<yarp::sig::PixelBgra>& src) {
return yarp_save(fname,src);
}
bool Filer::load_zip(const char *fname) {
#ifdef USE_ZIP
dbg_printf("Loading zip %s\n", fname);
src_zip = zzip_opendir(fname);
if (!src_zip) {
fprintf(stderr, "failed to load zip %s\n", fname);
exit(1);
}
return true;
#else
return false;
#endif
}
bool Filer::unload_zip() {
#ifdef USE_ZIP
ZZIP_DIR *zip = (ZZIP_DIR *)src_zip;
if (zip) {
zzip_closedir(zip);
src_zip = NULL;
}
#endif
return true;
}

41
src/Filer.h Normal file
View File

@@ -0,0 +1,41 @@
#ifndef FILER_INC
#define FILER_INC
#include <string>
#include <yarp/sig/all.h>
class Filer {
private:
void *src_zip;
public:
Filer() {
src_zip = NULL;
}
~Filer() {
if (src_zip) unload_zip();
}
bool load_zip(const char *fname);
bool unload_zip();
bool load(const char *fname,
yarp::sig::ImageOf<yarp::sig::PixelRgba>& src);
bool save(const char *fname,
yarp::sig::ImageOf<yarp::sig::PixelRgba>& src);
// GD compatible, apart from alpha channel
bool load(const char *fname,
yarp::sig::ImageOf<yarp::sig::PixelBgra>& src);
bool save(const char *fname,
yarp::sig::ImageOf<yarp::sig::PixelBgra>& src);
std::string load_text(const char *fname);
};
#endif

236
src/GifAnim.cpp Normal file
View File

@@ -0,0 +1,236 @@
#include "GifAnim.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gd.h>
#include "gd_mod.h"
#include <yarp/sig/Image.h>
using namespace yarp::sig;
using namespace yarp::os;
#include "Dbg.h"
static int raw_dither[16][16] = { {0, 192, 48, 240, 12, 204, 60, 252, 3, 195, 51, 243, 15, 207, 63, 255}, {128, 64, 176, 112, 140, 76, 188, 124, 131, 67, 179, 115, 143, 79, 191, 127}, {32, 224, 16, 208, 44, 236, 28, 220, 35, 227, 19, 211, 47, 239, 31, 223}, {160, 96, 144, 80, 172, 108, 156, 92, 163, 99, 147, 83, 175, 111, 159, 95}, {8, 200, 56, 248, 4, 196, 52, 244, 11, 203, 59, 251, 7, 199, 55, 247}, {136, 72, 184, 120, 132, 68, 180, 116, 139, 75, 187, 123, 135, 71, 183, 119}, {40, 232, 24, 216, 36, 228, 20, 212, 43, 235, 27, 219, 39, 231, 23, 215}, {168, 104, 152, 88, 164, 100, 148, 84, 171, 107, 155, 91, 167, 103, 151, 87}, {2, 194, 50, 242, 14, 206, 62, 254, 1, 193, 49, 241, 13, 205, 61, 253}, {130, 66, 178, 114, 142, 78, 190, 126, 129, 65, 177, 113, 141, 77, 189, 125}, {34, 226, 18, 210, 46, 238, 30, 222, 33, 225, 17, 209, 45, 237, 29, 221}, {162, 98, 146, 82, 174, 110, 158, 94, 161, 97, 145, 81, 173, 109, 157, 93}, {10, 202, 58, 250, 6, 198, 54, 246, 9, 201, 57, 249, 5, 197, 53, 245}, {138, 74, 186, 122, 134, 70, 182, 118, 137, 73, 185, 121, 133, 69, 181, 117}, {42, 234, 26, 218, 38, 230, 22, 214, 41, 233, 25, 217, 37, 229, 21, 213}, {170, 106, 154, 90, 166, 102, 150, 86, 169, 105, 153, 89, 165, 101, 149, 85} };
static int raw_dither_dim = 16;
GifAnim::~GifAnim() {
for (int i=0; i<(int)blocks.size(); i++) {
gdFree(blocks[i].get());
}
blocks.clear();
}
void GifAnim::check() {
if (!renders) {
fprintf(stderr,"No renders for GifAnim!\n");
exit(1);
}
}
static void sync_palette(gdImagePtr from, gdImagePtr to) {
for (int i = 0; i<gdMaxColors; i++) {
to->red[i] = from->red[i];
to->blue[i] = from->blue[i];
to->green[i] = from->green[i];
to->alpha[i] = from->alpha[i];
to->open[i] = from->open[i];
}
to->colorsTotal = from->colorsTotal;
}
inline int crop(int x) {
if (x>255) return 255;
return x;
}
void GifAnim::apply() {
bool local_color = false;
int loops = 0;
bool have_prev = false;
bool dither = true;
int step = int(period*100+0.5);
int last_step = int(hold*100+0.5);
dbg_printf("Step is %d (from %g)\n", step, period);
check();
int pals = (int)palette_frames.size();
int pal_index = -1;
if (pals<1) {
fprintf(stderr,"No palette frames\n");
exit(1);
}
ImageOf<PixelBgra> pal_image;
ImageOf<PixelBgra> *p_pal_image = &pal_image;
for (int i=0; i<pals; i++) {
int idx = palette_frames[i];
Render *r = renders->get_render(idx);
renders->remove_mapping(idx);
if (pals==1) {
p_pal_image = &r->get_mod();
pal_index = idx;
} else {
const ImageOf<PixelBgra>& img = r->get();
pal_image.resize(img);
int w = pal_image.width();
int h = pal_image.height();
for (int k=i; k<w*h; k+=pals) {
int xx = k%w;
int yy = k/w;
pal_image(xx,yy) = img(xx,yy);
}
}
}
int ww = p_pal_image->width();
int hh = p_pal_image->height();
gdImageStruct gd_wrap;
gdImagePtr im_tmp;
im_tmp = gdImageCreateTrueColor(ww,hh);
gd_wrap = *im_tmp;
gdImageDestroy(im_tmp);
gdImageSaveAlpha(&gd_wrap, 1);
gdImageAlphaBlending(&gd_wrap, 0);
gdImagePtr gd_palette = gdImageCreate(ww,hh);
gd_wrap.tpixels = (int**)p_pal_image->getRowArray();
double tot = 0;
IMGFOR(*p_pal_image,ww,hh) {
PixelBgra pix = p_pal_image->pixel(ww,hh);
tot += pix.r;
}
void *quantizer = pf_gdQuantizeInit(&gd_wrap,gd_palette);
pf_gdQuantizeApply(quantizer,&gd_wrap,1,gd_palette);
gdImagePtr gd_prev = gdImageCreate(ww,hh);
gdImagePtr gd_curr = gdImageCreate(ww,hh);
gdImagePtr gd_pre_prev = gdImageCreate(ww,hh);
sync_palette(gd_palette,gd_prev);
sync_palette(gd_palette,gd_curr);
sync_palette(gd_palette,gd_pre_prev);
int frames = renders->length();
int sz = 0;
void *mem = gdImageGifAnimBeginPtr(gd_palette,&sz,
1,
loops);
blocks.push_back(Bytes((char*)mem,(size_t)sz));
int accum_delay = 0;
// bool have_r = false;
//Render *r_prev = NULL;
//Render *r_pre_prev = NULL;
int emit_ct = 0;
int step_pending = 0;
for (int i=0; i<frames; i++) {
step_pending += step;
dbg_printf("Working on frame %d\n", i);
if (i!=pal_index) {
Render *r = renders->get_render(i);
renders->remove_mapping(i);
ImageOf<PixelBgra>& img = r->get_mod();
gd_wrap.tpixels = (int**)img.getRowArray();
pf_gdQuantizeApply(quantizer,&gd_wrap,1,gd_curr);
} else {
dbg_printf("Substitute in palette frame\n");
gdImagePtr tmp = gd_palette;
gd_palette = gd_curr;
gd_curr = tmp;
}
renders->remove_render(i);
bool change = false;
if (i>0) {
for (int x=0; x<ww && !change; x++) {
for (int y=0; y<hh; y++) {
int p0 = gd_prev->pixels[y][x];
int p1 = gd_curr->pixels[y][x];
if (p0!=p1) {
change = true;
break;
}
}
}
}
if (change) {
mem = gdImageGifAnimAddPtr(gd_prev,&sz,
local_color?1:0,
0,0,
step_pending,1,
(emit_ct>=1)?gd_pre_prev:NULL);
dbg_printf(" Generated frame, %d ticks\n", step_pending);
step_pending = 0;
emit_ct++;
blocks.push_back(Bytes((char*)mem,(size_t)sz));
}
if (change) {
//r_pre_prev = r_prev;
gdImagePtr tmp = gd_pre_prev;
gd_pre_prev = gd_prev;
gd_prev = gd_curr;
gd_curr = tmp;
} else {
gdImagePtr tmp = gd_prev;
gd_prev = gd_curr;
gd_curr = tmp;
}
//r_prev = r;
// ...
//renders->remove_render(i);
//renders->remove_mapping(i);
}
step_pending += step;
step_pending += last_step;
if (frames) {
mem = gdImageGifAnimAddPtr(gd_prev,&sz,
local_color?1:0,
0,0,
step_pending,1,
(emit_ct>=1)?gd_pre_prev:NULL);
emit_ct++;
blocks.push_back(Bytes((char*)mem,(size_t)sz));
dbg_printf(" Generated final frame, %d ticks\n",
step_pending);
}
pf_gdQuantizeFini(quantizer);
quantizer = NULL;
gdImageDestroy(gd_curr);
gdImageDestroy(gd_prev);
gdImageDestroy(gd_pre_prev);
gdImageDestroy(gd_palette);
mem = gdImageGifAnimEndPtr(&sz);
blocks.push_back(Bytes((char*)mem,(size_t)sz));
}
void GifAnim::save(const char *fname) {
FILE *fout = fopen(fname,"wb");
if (!fout) {
fprintf(stderr,"Cannot write GIF\n");
exit(1);
}
for (int i=0; i<(int)blocks.size(); i++) {
Bytes& b = blocks[i];
fwrite(b.get(),1,b.length(),fout);
}
fclose(fout);
}

55
src/GifAnim.h Normal file
View File

@@ -0,0 +1,55 @@
#ifndef GIFANIM_INC
#define GIFANIM_INC
#include "Renders.h"
#include <vector>
#include <yarp/os/Bytes.h>
class GifAnim {
private:
Renders *renders;
std::vector<int> palette_frames;
std::vector<yarp::os::Bytes> blocks;
double period;
double hold;
bool early_release;
public:
GifAnim() {
renders = 0 /*NULL*/;
period = 0.1;
hold = 5;
early_release = true;
}
~GifAnim();
void attach_renders(Renders *renders) {
this->renders = renders;
}
void check();
void set_palette(int index) {
palette_frames.clear();
palette_frames.push_back(index);
}
void set_palette(const std::vector<int>& palette) {
palette_frames = palette;
}
void apply();
void save(const char *fname);
void set_timing(double period, double hold) {
this->period = period;
this->hold = hold;
}
};
#endif

30
src/Input.cpp Normal file
View File

@@ -0,0 +1,30 @@
#include "Input.h"
#include "Dbg.h"
#include <stdio.h>
#include <stdlib.h>
using namespace std;
using namespace yarp::os;
bool Input::load(const char *fname) {
Filer filer;
dbg_printf("Loading %s\n", fname);
if (!filer.load(fname,src)) {
fprintf(stderr, "Failed to load %s\n", fname);
exit(1);
}
src.safePixel(-1,-1).a = 0;
in_scale = src.width();
in_x0 = 0;
in_y0 = 0;
if (src.height()>src.width()) {
in_scale = src.height();
in_x0 = -(-src.width()+src.height())/2;
} else {
in_y0 = -(src.width()-src.height())/2;
}
xa = cos(theta);
ya = sin(theta);
return true;
}

50
src/Input.h Normal file
View File

@@ -0,0 +1,50 @@
#ifndef INPUT_INC
#define INPUT_INC
#include <math.h>
#include <yarp/sig/Image.h>
#include "Filer.h"
class Input {
private:
yarp::sig::ImageOf<yarp::sig::PixelBgra> src;
double theta;
public:
const yarp::sig::ImageOf<yarp::sig::PixelBgra>& get() const { return src; }
// scale, angle, and offset in source coordinates
double xs;
double ys;
double xo;
double yo;
int layer;
int in_scale;
double in_x0;
double in_y0;
double xa;
double ya;
Input() {
xs = ys = 1;
theta = 0;
xo = yo = 0;
layer = 1;
in_scale = 0;
in_x0 = in_y0 = 0;
xa = 1;
ya = 0;
}
bool load(const char *fname);
};
#endif

27
src/Inputs.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef INPUTS_INC
#define INPUTS_INC
#include "Input.h"
#include <vector>
class Inputs {
private:
std::vector<Input> data;
public:
Input& add() {
data.push_back(Input());
return data.back();
}
const std::vector<Input>& get() const {
return data;
}
std::vector<Input>& get_mod() {
return data;
}
};
#endif

20
src/Mapping.h Normal file
View File

@@ -0,0 +1,20 @@
#ifndef MAPPING_INC
#define MAPPING_INC
#include <yarp/sig/Image.h>
#include <string>
class Mapping {
public:
yarp::sig::ImageOf<yarp::sig::PixelBgra> map1, map2, light, dark, neutral;
std::string map1_name, map2_name, light_name, dark_name, neutral_name;
// scale factor for interpreting map
int scale;
Mapping() {
scale = 1;
}
};
#endif

59
src/Pixer.h Normal file
View File

@@ -0,0 +1,59 @@
#ifndef PIXER_INC
#define PIXER_INC
#include <yarp/sig/Image.h>
class Pixer {
public:
double r;
double g;
double b;
double a;
Pixer operator+(const Pixer& alt) {
Pixer p;
p.r = r+alt.r;
p.g = g+alt.g;
p.b = b+alt.b;
p.a = a+alt.a;
return p;
}
void operator+=(const yarp::sig::PixelBgra& pix) {
r += pix.r;
g += pix.g;
b += pix.b;
a += pix.a;
}
Pixer operator*(double v) {
Pixer p;
p.r = r*v;
p.g = g*v;
p.b = b*v;
p.a = a*v;
return p;
}
Pixer operator/(double v) {
Pixer p;
p.r = r/v;
p.g = g/v;
p.b = b/v;
p.a = a/v;
return p;
}
};
inline Pixer sampleLinear(const yarp::sig::ImageOf<yarp::sig::PixelBgra>& src,
double x, double y) {
const yarp::sig::PixelBgra& p = src.safePixel(x,y);
Pixer v;
v.r = p.r;
v.g = p.g;
v.b = p.b;
v.a = p.a;
return v;
}
#endif

82
src/Prop.cpp Normal file
View File

@@ -0,0 +1,82 @@
#include "Prop.h"
using namespace yarp::os;
using namespace std;
void Prop::scan_hx(const std::string& txt, yarp::os::Property& data) {
data.clear();
string line;
for (int i=0; i<(int)txt.size(); i++) {
char ch = txt[i];
if (ch=='\r'||ch=='\n') {
line = "";
continue;
}
if (ch=='[') {
line += '(';
continue;
}
if (ch==']') {
line += ')';
continue;
}
if (ch==',') {
line += ' ';
continue;
}
if (ch!=';') {
line += ch;
continue;
}
Bottle b(line.c_str());
string var = "dud";
for (int j=1; j<b.size(); j++) {
if (b.get(j-1).asString()=="var") {
var = b.get(j).asString();
continue;
}
if (b.get(j-1).asString()=="=") {
Value v = b.get(j);
ConstString s = v.asString();
if (s=="true") {
data.put(var.c_str(),1);
} else if (s=="false") {
data.put(var.c_str(),0);
} else {
data.put(var.c_str(),v);
}
}
}
}
}
void Prop::scan_xml(const std::string& txt, yarp::os::Property& data) {
data.clear();
string line;
for (int i=0; i<(int)txt.size(); i++) {
char ch = txt[i];
if (ch=='\"') {
line += " ";
continue;
}
if (ch!='\r'&&ch!='\n') {
line += ch;
continue;
}
Bottle b(line.c_str());
string var = "dud";
for (int j=1; j<b.size(); j++) {
if (b.get(j-1).asString()=="id=") {
var = b.get(j).asString();
continue;
}
if (b.get(j-1).asString()=="import=") {
data.put(var.c_str(),b.get(j));
}
}
}
}

14
src/Prop.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef PROP_INC
#define PROP_INC
#include <string>
#include <yarp/os/Property.h>
class Prop {
public:
static void scan_hx(const std::string& txt, yarp::os::Property& data);
static void scan_xml(const std::string& txt, yarp::os::Property& data);
};
#endif

463
src/Render.cpp Normal file
View File

@@ -0,0 +1,463 @@
#include "Render.h"
#include "Pixer.h"
#include <stdio.h>
#include <stdlib.h>
#include <gd.h>
#include "Dbg.h"
#include <yarp/sig/ImageFile.h>
using namespace yarp::sig::file;
using namespace yarp::sig;
#define RR (4096/2)
static int render_count = 0;
static double distance(double x1, double y1,
double x2, double y2) {
return sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
}
int Render::render_count() {
return ::render_count;
}
void Render::check() {
if (!mapping) {
fprintf(stderr,"No mapping!\n");
exit(1);
}
}
void Render::add(const Input& in) {
check();
double active_scale = in.in_scale;
active_scale /= 2; //mapping->scale;
int w = mapping->light.width();
int h = mapping->light.height();
if (mapping->map1.width()<w) {
return;
}
int off = (mapping->map2.height()-mapping->light.height())/2;
if (mapping->map1.width()!=mapping->neutral.width()) return;
if (mapping->map2.width()!=mapping->neutral.width()) return;
IMGFOR(out,x,y) {
PixelBgra& pix = out(x,y);
const PixelBgra& lightPixel = mapping->light(x,y);
const PixelBgra& darkPixel = mapping->dark(x,y);
const PixelBgra& mapPixel = mapping->map1(x,y+off);
const PixelBgra& selPixel = mapping->map2(x,y+off);
bool d = (selPixel.r==in.layer);
if (!d) continue;
int act = mapPixel.a;
if (act<=25) continue;
int mod = mapPixel.b;
int ymod = mod/16;
int xmod = mod%16;
double x1 = mapPixel.r + 256*xmod - RR;
double y1 = mapPixel.g + 256*ymod - RR;
PixelBgra m;
double x12 = x1;
double y12 = y1;
double x13 = x1;
double y13 = y1;
if (x<w-1&&y<h-1) {
const PixelBgra& mdx = mapping->map1(x+1,y+off);
const PixelBgra& mdy = mapping->map1(x,y+1+off);
if (mdx.a>127 && mdy.a>127) {
const PixelBgra& idx2 = mapping->map2(x+1,y+off);
const PixelBgra& idx3 = mapping->map2(x,y+1+off);
if (idx2.r==in.layer && idx3.r==in.layer) {
int mod2 = mdx.b;
int ymod2 = mod2/16;
int xmod2 = mod2%16;
x12 = mdx.r + 256*xmod2 - RR;
y12 = mdx.g + 256*ymod2 - RR;
int mod3 = mdy.b;
int ymod3 = mod3/16;
int xmod3 = mod3%16;
x13 = mdy.r + 256*xmod3 - RR;
y13 = mdy.g + 256*ymod3 - RR;
//printf("WORKING %g %g / %g %g\n", x12-x1, y12-y1,
//x13-x1, y13-y1);
}
double da = distance(x1,y1,x12,y12);
double db = distance(x1,y1,x13,y13);
if (da>400.0||db>400.0) {
x12 = x1;
y12 = y1;
x13 = x1;
y13 = y1;
}
}
}
x1 *= in.xs;
y1 *= in.ys;
double xx = in.xa*x1 + in.ya*y1;
double yy = -in.ya*x1 + in.xa*y1;
xx += RR + in.xo;
yy += RR + in.yo;
xx = in.in_x0 + active_scale*xx/RR;
yy = in.in_y0 + active_scale*yy/RR;
x12 *= in.xs;
y12 *= in.ys;
double xxa = in.xa*x12 + in.ya*y12;
double yya = -in.ya*x12 + in.xa*y12;
xxa += RR + in.xo;
yya += RR + in.yo;
xxa = in.in_x0 + active_scale*xxa/RR;
yya = in.in_y0 + active_scale*yya/RR;
x13 *= in.xs;
y13 *= in.ys;
double xxb = in.xa*x13 + in.ya*y13;
double yyb = -in.ya*x13 + in.xa*y13;
xxb += RR + in.xo;
yyb += RR + in.yo;
xxb = in.in_x0 + active_scale*xxb/RR;
yyb = in.in_y0 + active_scale*yyb/RR;
xxa -= xx;
yya -= yy;
xxb -= xx;
yyb -= yy;
Pixer mo = sampleLinear(in.get(),xx,yy);
Pixer m2 = sampleLinear(in.get(),xx+xxa/2.0,yy+yya/2.0);
Pixer m3 = sampleLinear(in.get(),xx-xxa/2.0,yy-yya/2.0);
Pixer m4 = sampleLinear(in.get(),xx+xxb/2.0,yy+yyb/2.0);
Pixer m5 = sampleLinear(in.get(),xx-xxb/2.0,yy-yyb/2.0);
Pixer m2b = sampleLinear(in.get(),xx+(xxa+xxb)/2.0,yy+(yya+yyb)/2.0);
Pixer m3b = sampleLinear(in.get(),xx+(xxa-xxb)/2.0,yy+(yya-yyb)/2.0);
Pixer m4b = sampleLinear(in.get(),xx-(xxa+xxb)/2.0,yy-(yya+yyb)/2.0);
Pixer m5b = sampleLinear(in.get(),xx-(xxa-xxb)/2.0,yy-(yya-yyb)/2.0);
mo = (mo*4.0 + (m2+m3+m4+m5)*2.0 + (m2b+m3b+m4b+m5b))/16.0;
m.r = mo.r;
m.g = mo.g;
m.b = mo.b;
m.a = mo.a;
//} else {
//m = in.get().safePixel((int)xx,(int)yy);
//}
//const PixelBgra& m = in.get().safePixel((int)xx,(int)yy);
PixelBgra result;
if (d && act>25) {
result.r = darkPixel.r + ((lightPixel.r-darkPixel.r)*m.r)/255;
result.g = darkPixel.g + ((lightPixel.g-darkPixel.g)*m.g)/255;
result.b = darkPixel.b + ((lightPixel.b-darkPixel.b)*m.b)/255;
result.a = m.a;
if (darkPixel.a<result.a) {
result.a = darkPixel.a;
}
if (result.a>0) {
PixelBgra& outPixel = out.pixel(x,y);
if (result.a>250) {
outPixel = result;
} else {
outPixel.r += ((result.r-outPixel.r)*result.a)/255;
outPixel.g += ((result.g-outPixel.g)*result.a)/255;
outPixel.b += ((result.b-outPixel.b)*result.a)/255;
}
}
}
}
}
void Render::add_simple(const Input& in) {
check();
double active_scale = in.in_scale;
active_scale /= 2; //mapping->scale;
int off = (mapping->map2.height()-mapping->light.height())/2;
if (mapping->map1.width()<mapping->light.width()) {
return;
}
IMGFOR(out,x,y) {
PixelBgra& pix = out(x,y);
const PixelBgra& lightPixel = mapping->light(x,y);
const PixelBgra& darkPixel = mapping->dark(x,y);
const PixelBgra& mapPixel = mapping->map1(x,y+off);
const PixelBgra& selPixel = mapping->map2(x,y+off);
int mod = mapPixel.b;
int ymod = mod/16;
int xmod = mod%16;
int act = mapPixel.a;
double x1 = mapPixel.r + 256*xmod - RR;
double y1 = mapPixel.g + 256*ymod - RR;
x1 *= in.xs;
y1 *= in.ys;
double xx = in.xa*x1 + in.ya*y1;
double yy = -in.ya*x1 + in.xa*y1;
xx += RR + in.xo;
yy += RR + in.yo;
xx = in.in_x0 + active_scale*xx/RR;
yy = in.in_y0 + active_scale*yy/RR;
const PixelBgra& m = in.get().safePixel((int)xx,(int)yy);
PixelBgra result;
bool d = (selPixel.r==in.layer);
if (d && act>25) {
result.r = darkPixel.r + ((lightPixel.r-darkPixel.r)*m.r)/255;
result.g = darkPixel.g + ((lightPixel.g-darkPixel.g)*m.g)/255;
result.b = darkPixel.b + ((lightPixel.b-darkPixel.b)*m.b)/255;
result.a = m.a;
if (darkPixel.a<result.a) {
result.a = darkPixel.a;
}
if (result.a>0) {
PixelBgra& outPixel = out.pixel(x,y);
if (result.a>250) {
outPixel = result;
} else {
outPixel.r += ((result.r-outPixel.r)*result.a)/255;
outPixel.g += ((result.g-outPixel.g)*result.a)/255;
outPixel.b += ((result.b-outPixel.b)*result.a)/255;
}
}
}
}
}
void Render::post() {
::render_count++;
check();
ImageOf<PixelBgra> pre = out;
int w = out.width();
int h = out.height();
if (mapping->map1.width()<mapping->light.width()) {
return;
}
if (mapping->map1.width()!=mapping->neutral.width()) return;
if (mapping->map2.width()!=mapping->neutral.width()) return;
IMGFOR(out,x,y) {
PixelBgra& pix = out(x,y);
const PixelBgra& selPixel = mapping->map2(x,y);
if (selPixel.b>0) {
/*
pix.r = 0;
pix.g = 0;
pix.b = 0;
*/
if (x>0 && y>0 && x<w-1 && y<h-1) {
PixelBgra back1 = pre(x-1,y);
PixelBgra idx1 = mapping->map2(x-1,y);
PixelBgra back2 = pre(x+1,y);
PixelBgra idx2 = mapping->map2(x+1,y);
PixelBgra back3 = pre(x,y-1);
PixelBgra idx3 = mapping->map2(x,y-1);
PixelBgra back4 = pre(x,y+1);
PixelBgra idx4 = mapping->map2(x,y+1);
Pixer total = {0,0,0,0};
double ct = 0;
if (idx1.b<127) {
total += back1;
ct++;
}
if (idx2.b<127) {
total += back2;
ct++;
}
if (idx3.b<127) {
total += back3;
ct++;
}
if (idx4.b<127) {
total += back4;
ct++;
}
if (ct>0.5) {
total = total/ct;
pix.r = total.r;
pix.g = total.g;
pix.b = total.b;
}
}
}
}
}
bool Render::auto_zoom(Input& in) {
check();
double active_scale = in.in_scale;
active_scale /= 2; //mapping->scale;
int off = (mapping->map2.height()-mapping->light.height())/2;
if (mapping->map1.width()<mapping->light.width()) {
return false;
}
double x_min = in.get().width();
double x_max = 0;
double y_min = in.get().height();
double y_max = 0;
IMGFOR(mapping->light,x,y) {
const PixelBgra& lightPixel = mapping->light(x,y);
const PixelBgra& darkPixel = mapping->dark(x,y);
const PixelBgra& mapPixel = mapping->map1(x,y+off);
const PixelBgra& selPixel = mapping->map2(x,y+off);
int mod = mapPixel.b;
int ymod = mod/16;
int xmod = mod%16;
int act = mapPixel.a;
double x1 = mapPixel.r + 256*xmod - RR;
double y1 = mapPixel.g + 256*ymod - RR;
x1 *= in.xs;
y1 *= in.ys;
double xx = in.xa*x1 + in.ya*y1;
double yy = -in.ya*x1 + in.xa*y1;
xx += RR + in.xo;
yy += RR + in.yo;
xx = in.in_x0 + active_scale*xx/RR;
yy = in.in_y0 + active_scale*yy/RR;
const PixelBgra& m = in.get().safePixel((int)xx,(int)yy);
PixelBgra result;
bool d = (selPixel.r==1);
if (d && act>25) {
if (xx<x_min) x_min = xx;
if (xx>x_max) x_max = xx;
if (yy<y_min) y_min = yy;
if (yy>y_max) y_max = yy;
}
}
double ww = in.get().width();
double hh = in.get().height();
dbg_printf("zoom %g %g %g %g (%g %g)\n", x_min, y_min, x_max, y_max, ww, hh);
if (y_max-y_min<hh*0.75) {
in.xs *= 2;
in.ys *= 2;
return true;
}
return false;
}
void Render::apply_scaled(const Inputs& ins, int w, int h) {
pre();
const std::vector<Input>& data = ins.get();
for (std::vector<Input>::const_iterator it = data.begin();
it != data.end(); it++) {
add(*it);
}
post();
if (w>0&&h>0 && (w!=out.width()||h!=out.height())) {
int wi = out.width();
int hi = out.height();
// we have wi,hi - want to present it in w,h
// pad with whitespace if needed to preserve aspect ratio
double fi = (double)wi/hi;
double f = (double)w/h;
int xo = 0;
int yo = 0;
int wo = w;
int ho = h;
out_scaled.resize(w,h);
if (fi>f+0.001) {
// input is wider than output
// pad top, bottom
wo = w;
ho = (int)(wo/fi);
yo = (h-ho)/2;
} else if (fi<f-0.001) {
// input is thinner than output (or same)
// pad left, right
ho = h;
wo = (int)(h*fi);
xo = (w-wo)/2;
}
if (xo!=0||yo!=0) {
IMGFOR(out_scaled,x,y) {
out_scaled(x,y) = PixelBgra(255,255,255,0);
}
}
gdImageStruct src;
src.trueColor = true;
src.sx = out.width();
src.sy = out.height();
src.cx1 = src.cy1 = 0;
src.cx2 = src.sx-1;
src.cy2 = src.sy-1;
src.trueColor = true;
src.tpixels = (int**)out.getRowArray();
gdImageStruct dest;
dest.trueColor = true;
dest.sx = out_scaled.width();
dest.sy = out_scaled.height();
dest.cx1 = dest.cy1 = 0;
dest.cx2 = dest.sx-1;
dest.cy2 = dest.sy-1;
dest.trueColor = true;
dest.tpixels = (int**)out_scaled.getRowArray();
dest.saveAlphaFlag = 1;
dest.alphaBlendingFlag = 0;
gdImageCopyResampled(&dest,&src,xo,yo,0,0,wo,ho,
src.sx,src.sy);
IMGFOR(out_scaled,x,y) {
out_scaled(x,y).a = 255;
}
out.resize(1,1);
}
}
bool Render::auto_zoom(Inputs& ins) {
std::vector<Input>& data = ins.get_mod();
bool changed = false;
for (std::vector<Input>::iterator it = data.begin();
it != data.end(); it++) {
changed = changed || auto_zoom(*it);
}
return changed;
}

73
src/Render.h Normal file
View File

@@ -0,0 +1,73 @@
#ifndef RENDER_INC
#define RENDER_INC
#include "Mapping.h"
#include "Filer.h"
#include "Input.h"
#include "Inputs.h"
class Render {
private:
const Mapping *mapping;
yarp::sig::ImageOf<yarp::sig::PixelBgra> out;
yarp::sig::ImageOf<yarp::sig::PixelBgra> out_scaled;
// active variables
public:
Render() {
mapping = 0 /*NULL*/;
}
void check();
void attach_mapping(const Mapping *mapping) {
if (!mapping) return;
this->mapping = mapping;
}
void pre() {
check();
out.setQuantum(1);
out.copy(this->mapping->neutral);
}
void add_simple(const Input& in);
void add(const Input& in);
void apply(const Inputs& ins) {
apply_scaled(ins,-1,-1);
}
void apply_scaled(const Inputs& ins, int w, int h);
bool auto_zoom(Inputs& ins);
bool auto_zoom(Input& in);
void post();
bool save(const char *fname) {
Filer filer;
filer.save(fname,get_mod());
return true;
}
const yarp::sig::ImageOf<yarp::sig::PixelBgra>& get() {
return get_mod();
}
yarp::sig::ImageOf<yarp::sig::PixelBgra>& get_mod() {
if (out_scaled.width()>0) {
return out_scaled;
}
return out;
}
static int render_count();
};
#endif

48
src/Renders.cpp Normal file
View File

@@ -0,0 +1,48 @@
#include "Renders.h"
#include <stdio.h>
#include <stdlib.h>
using namespace std;
void Renders::check() {
if (!repo) {
fprintf(stderr,"No repository!\n");
exit(1);
}
if (!inputs) {
fprintf(stderr,"No inputs!\n");
exit(1);
}
}
Render *Renders::get_render(int index) {
check();
map<int,Render>::iterator it = renders.find(index);
if (it == renders.end()) {
Render& render = renders[index] = Render();
render.attach_mapping(repo->get_mapping(index));
render.apply_scaled(*inputs,w,h);
int rct = (int)renders.size();
if (rct>peak_cache_count) peak_cache_count = rct;
return &render;
}
return &(it->second);
}
void Renders::remove_render(int index) {
map<int,Render>::iterator it = renders.find(index);
if (it!=renders.end()) {
renders.erase(it);
}
}
bool Renders::auto_zoom() {
check();
Render render;
render.attach_mapping(repo->get_mapping(0));
return render.auto_zoom(*inputs);
}

58
src/Renders.h Normal file
View File

@@ -0,0 +1,58 @@
#ifndef RENDERS_INC
#define RENDERS_INC
#include "Inputs.h"
#include "Repository.h"
#include "Render.h"
class Renders {
private:
Inputs *inputs;
Repository *repo;
std::map<int,Render> renders;
int w, h;
int peak_cache_count;
public:
Renders() {
inputs = 0 /*NULL*/;
repo = 0 /*NULL*/;
w = h = -1;
peak_cache_count = 0;
}
void check();
void set_size(int w, int h) {
this->w = w;
this->h = h;
}
void attach_repository(Repository *repo) {
this->repo = repo;
}
void attach_inputs(Inputs *inputs) {
this->inputs = inputs;
}
bool auto_zoom();
Render *get_render(int index = 0);
void remove_render(int index);
void remove_mapping(int index) {
repo->remove_mapping(index);
}
int length() {
return repo->length();
}
int peak() {
return peak_cache_count;
}
};
#endif

185
src/Repository.cpp Normal file
View File

@@ -0,0 +1,185 @@
#include "Repository.h"
#include "Prop.h"
#include "Dbg.h"
#include <stdio.h>
#include <stdlib.h>
using namespace std;
using namespace yarp::os;
void Repository::load_part(const char *postfix, int idx) {
string base = "Disp";
if (idx==-2) base = "Thumb";
string dark = base + "DarkData";
string light = base + "LightData";
string neutral = base + "TransparentData";
string map1 = base + "MapData";
string map2 = base + "SelData";
if (postfix[0]!='\0') {
dark += postfix;
light += postfix;
neutral += postfix;
map1 += postfix;
map2 += postfix;
}
if (mappings.find(idx)==mappings.end()) {
mappings[idx] = Mapping();
}
Mapping& s = mappings[idx];
bool ok = inventory.check(dark.c_str()) &&
inventory.check(light.c_str()) &&
inventory.check(map1.c_str()) &&
inventory.check(map2.c_str());
if (!ok) {
fprintf(stderr,"Missing some map data (%s/%s/%s/%s)\n",
dark.c_str(), light.c_str(), map1.c_str(), map2.c_str());
return;
}
bool have_neutral = inventory.check(neutral.c_str());
ConstString light_name = inventory.find(light.c_str()).asString();
ConstString dark_name = inventory.find(dark.c_str()).asString();
ConstString neutral_name = inventory.find(neutral.c_str()).asString();
ConstString map1_name = inventory.find(map1.c_str()).asString();
ConstString map2_name = inventory.find(map2.c_str()).asString();
dbg_printf("Loading light %s\n", light_name.c_str());
if (!filer.load(light_name.c_str(),s.light)) exit(1);
s.light_name = light_name;
dbg_printf("Loading dark\n");
if (!filer.load(dark_name.c_str(),s.dark)) exit(1);
s.dark_name = dark_name;
dbg_printf("Loading map1\n");
if (!filer.load(map1_name.c_str(),s.map1)) exit(1);
s.map1_name = map1_name;
dbg_printf("Loading map2\n");
if (!filer.load(map2_name.c_str(),s.map2)) exit(1);
s.map2_name = map2_name;
if (have_neutral) {
dbg_printf("Loading neutral\n");
if (!filer.load(neutral_name.c_str(),s.neutral)) exit(1);
s.neutral_name = neutral_name;
} else {
s.neutral = s.light;
s.neutral_name = light_name;
}
s.scale = 1;
}
void Repository::load(const char *fname) {
bool ok = filer.load_zip(fname);
if (!ok) {
fprintf(stderr,"Cannot load zip %s\n", fname);
exit(1);
}
Prop prop;
std::string txt = filer.load_text("MakeSweetConfig.hx");
if (txt=="") {
dbg_printf("No config file\n");
}
prop.scan_hx(txt,config);
txt = filer.load_text("inventory.xml");
if (txt=="") {
fprintf(stderr, "No inventory file\n");
exit(1);
}
prop.scan_xml(txt,inventory);
dbg_printf("Props: %s\n", config.toString().c_str());
dbg_printf("Inventory: %s\n", inventory.toString().c_str());
flag_animation = false;
if (config.check("animation",Value(0)).asInt()) {
flag_animation = true;
} else {
flag_animation = false;
}
frames = 1;
if (flag_animation) {
frames = config.check("frames",Value(1)).asInt();
}
dbg_printf("Loaded all files / animation %d\n", flag_animation);
}
Mapping *Repository::get_mapping(int index) {
if (index<0) {
map<int,Mapping>::iterator it = mappings.find(index);
if (it == mappings.end()) {
load_part("",index);
it = mappings.find(index);
}
return &(it->second);
}
if (!flag_animation) {
map<int,Mapping>::iterator it = mappings.find(0);
if (it == mappings.end()) {
load_part("",0);
it = mappings.find(0);
int rct = (int)mappings.size();
if (rct>peak_cache_count) peak_cache_count = rct;
}
return &(it->second);
}
map<int,Mapping>::iterator it = mappings.find(index);
if (it == mappings.end()) {
char buf[256];
sprintf(buf,"%d", index);
load_part(buf,index);
it = mappings.find(index);
int rct = (int)mappings.size();
if (rct>peak_cache_count) peak_cache_count = rct;
}
return &(it->second);
}
void Repository::remove_mapping(int index) {
map<int,Mapping>::iterator it = mappings.find(index);
if (it!=mappings.end()) {
mappings.erase(it);
}
}
std::vector<int> Repository::get_palette() {
vector<int> frames;
Bottle *lst = config.find("palette").asList();
if (!lst) {
int idx = config.find("palette").asInt();
frames.push_back(idx);
return frames;
}
for (int i=0; i<lst->size(); i++) {
frames.push_back(lst->get(i).asInt());
}
return frames;
}
double Repository::get_period() {
double period = config.check("delay",Value(1.0)).asDouble();
double speed = config.check("speed_step",Value(1.0)).asDouble();
return period*speed;
}
double Repository::get_hold() {
double hold = config.check("hold",Value(1.0)).asDouble();
return hold;
}
double Repository::get_zoom() {
double zoom = config.check("zoom",Value(1.0)).asDouble();
return zoom;
}

61
src/Repository.h Normal file
View File

@@ -0,0 +1,61 @@
#ifndef REPOSITORY_INC
#define REPOSITORY_INC
#include <yarp/os/Property.h>
#include "Mapping.h"
#include "Filer.h"
#include <map>
#include <vector>
class Repository {
private:
yarp::os::Property inventory;
yarp::os::Property config;
std::map<int,Mapping> mappings;
Filer filer;
bool flag_animation;
int frames;
int peak_cache_count;
public:
Repository() {
flag_animation = false;
frames = 0;
peak_cache_count = 0;
}
void load_part(const char *postfix, int idx);
void load(const char *fname);
Mapping *get_mapping(int index = 0);
Mapping *get_thumb_mapping() {
return get_mapping(-2);
}
void remove_mapping(int index);
bool is_animation() {
return flag_animation;
}
int length() {
return frames;
}
std::vector<int> get_palette();
double get_period();
double get_hold();
double get_zoom();
int peak() {
return peak_cache_count;
}
};
#endif

129
src/anim_thumb.cpp Normal file
View File

@@ -0,0 +1,129 @@
#include <stdio.h>
#include <stdlib.h>
#include "Filer.h"
using namespace yarp::sig;
int __ms_verbose = 0;
bool fetch_image(ImageOf<PixelRgba>& img,
const char *prefix,
const char *mode,
int index) {
Filer filer;
char buf[1000];
snprintf(buf,sizeof(buf),"%s%d_%s.png",prefix,index,mode);
bool ok = filer.load(buf,img);
if (!ok) {
printf("Failed to load %s\n", buf);
exit(1);
} else {
printf("Found %s\n", buf);
}
return ok;
}
bool save_image(ImageOf<PixelRgba>& img,
const char *prefix,
const char *mode) {
Filer filer;
char buf[1000];
snprintf(buf,sizeof(buf),"%sall_%s.png",prefix,mode);
bool ok = filer.save(buf,img);
if (!ok) {
printf("Failed to save %s\n", buf);
exit(1);
} else {
printf("Made %s\n", buf);
}
return ok;
}
void add(ImageOf<PixelRgba>& ilight,
ImageOf<PixelRgba>& olight,
int i,
int N) {
int iw = 0;
int ih = 0;
int ow = 0;
int oh = 0;
int tw = 0;
int th = 0;
float twe = 0;
float the = 0;
iw = ilight.width();
ih = ilight.height();
if (iw<=1) {
return;
}
tw = iw/8;
th = ih/8;
twe = iw/8.0;
the = ih/8.0;
ow = iw;
oh = th;
ImageOf<PixelRgba> tmp;
tmp.copy(ilight,tw,th);
for (int xx=0; xx<tw; xx++) {
for (int yy=0; yy<th; yy++) {
olight.safePixel(int(i*twe)+xx,yy) = tmp(xx,yy);
}
}
}
void process() {
const char *prefix = "/tmp/pack_makesweet/thumb_";
int N = 8;
int iw = 0;
int ih = 0;
int ow = 0;
int oh = 0;
int tw = 0;
int th = 0;
float twe = 0;
float the = 0;
ImageOf<PixelRgba> olight, odark, omap, osel;
for (int i=0; i<N; i++) {
ImageOf<PixelRgba> ilight, idark, imap, isel;
fetch_image(ilight,prefix,"light",i);
fetch_image(idark,prefix,"dark",i);
fetch_image(imap,prefix,"map",i);
fetch_image(isel,prefix,"sel",i);
if (iw==0) {
iw = ilight.width();
ih = ilight.height();
tw = iw/8;
th = ih/8;
twe = iw/8.0;
the = ih/8.0;
ow = iw;
oh = th;
olight.resize(ow,oh);
odark.resize(ow,oh);
omap.resize(ow,oh);
osel.resize(ow,oh);
olight.zero();
odark.zero();
omap.zero();
osel.zero();
}
add(ilight,olight,i,N);
add(idark,odark,i,N);
add(isel,osel,i,N);
add(imap,omap,i,N);
}
save_image(olight,prefix,"light");
save_image(odark,prefix,"dark");
save_image(omap,prefix,"map");
save_image(osel,prefix,"sel");
}
int main() {
printf("Animation thumbnail\n");
process();
return 0;
}

196
src/dither.cpp Normal file
View File

@@ -0,0 +1,196 @@
#include <stdio.h>
#include <yarp/sig/Image.h>
#include <yarp/sig/ImageFile.h>
#include <yarp/sig/ImageDraw.h>
using namespace yarp::sig;
using namespace yarp::sig::file;
typedef ImageOf<PixelMono> Matrix;
Matrix getDither2x2() {
Matrix m;
m.resize(2,2);
m(0,0) = 0;
m(1,0) = 2;
m(0,1) = 3;
m(1,1) = 1;
return m;
}
Matrix doubleDither(const Matrix& a) {
Matrix b;
int w = a.width();
b.resize(w*2,w*2);
for (int i=0; i<2; i++) {
for (int j=0; j<2; j++) {
for (int ii=0; ii<w; ii++) {
for (int jj=0; jj<w; jj++) {
b(ii+i*w,jj+j*w) = a(ii,jj)*4 + a(i*(w/2),j*(w/2));
}
}
}
}
return b;
}
/*
Matrix directDither(int c) {
int w = 1;
for (int i=0; i<c; i++) {
w*=2;
}
Matrix m;
m.resize(w,w);
int r = w/2;
int rr = r;
m(0,0) = 0;
m(r,0) = 2;
m(0,r) = 3;
m(r,r) = 1;
for (int k=1; k<c; k++) {
for (int i=0; i<2; i++) {
for (int j=0; j<2; j++) {
for (int ii=0; ii<2; ii++) {
for (int jj=0; jj<2; jj++) {
if (ii+jj>0) {
m(ii*r/2+i*r,jj*r/2+j*r) =
m(ii*r,jj*r)*4 + a(i*(w/2),j*(w/2));
}
}
}
}
}
r /= 2;
}
}
*/
void codeDither(const Matrix& m) {
printf("static private var rawDither : Array<Int> = [ ");
for (int i=0; i<m.width(); i++) {
for (int j=0; j<m.height(); j++) {
int v = m(i,j);
v = int(((1.0+v)/(1.0+m.width()*m.width()))*256.0);
printf("%s0x%02x%02x%02x%02x",
(j>0||i>0)?", ":"",
255, v, v, v);
}
}
printf(" ];\n");
printf("static private var rawDitherDim : Int = %d;\n", m.width());
}
void codeDither2(const Matrix& m) {
printf("static int raw_dither[%d][%d] = { ", m.width(), m.height());
for (int i=0; i<m.width(); i++) {
if (i>0) printf(", ");
printf("{");
for (int j=0; j<m.height(); j++) {
int v = m(i,j);
v = int(((1.0+v)/(1.0+m.width()*m.width()))*256.0);
printf("%s%d",
(j>0)?", ":"",
v);
}
printf("}");
}
printf(" };\n");
printf("static int raw_dither_dim = %d;\n", m.width());
}
void showDither(const Matrix& m) {
for (int i=0; i<m.width(); i++) {
for (int j=0; j<m.height(); j++) {
printf("%d ", m(i,j));
}
printf("\n");
}
codeDither(m);
codeDither2(m);
}
void dithers() {
Matrix d2 = getDither2x2();
showDither(d2);
Matrix d4 = doubleDither(d2);
showDither(d4);
Matrix d8 = doubleDither(d4);
showDither(d8);
Matrix d16 = doubleDither(d8);
showDither(d16);
}
int c2p(int c,float tweak) {
int v = int(6*(c/256.0+tweak)+0.5);
if (v<0) return 0;
if (v>=6) return 5;
return v;
}
int p2c(int p) {
return 51*p;
}
int rgb2pal(const PixelRgb& pix,float tweak) {
int v = 36*c2p(pix.r,tweak) + 6*c2p(pix.g,tweak) + c2p(pix.b,tweak);
}
void pal2rgb(int pal, PixelRgb& pix) {
int bb = pal%6;
pal /= 6;
int gg = pal%6;
pal /= 6;
int rr = pal;
pix.r = p2c(rr);
pix.g = p2c(gg);
pix.b = p2c(bb);
}
void dither(ImageOf<PixelRgb>& src, ImageOf<PixelRgb>& dest) {
Matrix d = doubleDither(getDither2x2());
//Matrix d = doubleDither(doubleDither(getDither2x2()));
//Matrix d = doubleDither(doubleDither(doubleDither(getDither2x2())));
showDither(d);
write(d,"dither.ppm");
int dd = d.width();
dest.resize(src);
IMGFOR(src,x,y) {
int dx = x%dd;
int dy = y%dd;
int dith = d(dx,dy);
int pal = rgb2pal(src(x,y),(1.0+dith)/(1.0+dd*dd)-0.5);
pal2rgb(pal,dest(x,y));
//dest(x,y).r = x%256;
//dest(x,y).g = y%256;
//dest(x,y).b = (x+y)%256;
}
}
int main(int argc, char *argv[]) {
dithers();
return 1;
if (argc<2) {
printf("Need an in file, out file\n");
return 1;
}
char *input_name = argv[1];
char *output_name = argv[2];
printf("Loading %s\n", input_name);
ImageOf<PixelRgb> input, output;
bool ok = read(input,input_name);
if (!ok) {
printf("Failed to load\n");
return 1;
}
dither(input,output);
printf("Writing %s\n", output_name);
write(output,output_name);
return 0;
}

15
src/gd_mod.h Normal file
View File

@@ -0,0 +1,15 @@
#ifdef __cplusplus
extern "C" {
#endif
extern void *pf_gdQuantizeInit (gdImagePtr oim, gdImagePtr nim);
extern void pf_gdQuantizeApply (void *v, gdImagePtr oim, int dither, gdImagePtr nim);
extern void pf_gdQuantizeFini (void *v);
//#define pf_gdQuantizeInit gdQuantizeInit
//#define pf_gdQuantizeApply gdQuantizeApply
//#define pf_gdQuantizeFini gdQuantizeFini
#ifdef __cplusplus
}
#endif

2221
src/gd_topal.c Normal file

File diff suppressed because it is too large Load Diff

470
src/msmap.c Normal file
View File

@@ -0,0 +1,470 @@
#include "msmap.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define PAULFITZ_MAXWIDTH 4000
#define PAULFITZ_MAXHEIGHT 4000
#define PAULFITZ_MAXLAYER 2
//#define DBG
//#define DISABLE_ME
int paulfitz_px, paulfitz_py, paulfitz_active = 0;
int paulfitz_max_layer = 0;
float paulfitz_xx[PAULFITZ_MAXLAYER][PAULFITZ_MAXWIDTH][PAULFITZ_MAXHEIGHT];
float paulfitz_yy[PAULFITZ_MAXLAYER][PAULFITZ_MAXWIDTH][PAULFITZ_MAXHEIGHT];
//float paulfitz_xx2[PAULFITZ_MAXLAYER][PAULFITZ_MAXWIDTH][PAULFITZ_MAXHEIGHT];
//float paulfitz_yy2[PAULFITZ_MAXLAYER][PAULFITZ_MAXWIDTH][PAULFITZ_MAXHEIGHT];
int paulfitz_ct[PAULFITZ_MAXLAYER][PAULFITZ_MAXWIDTH][PAULFITZ_MAXHEIGHT];
char paulfitz_idx[PAULFITZ_MAXWIDTH][PAULFITZ_MAXHEIGHT];
char paulfitz_ray[PAULFITZ_MAXWIDTH][PAULFITZ_MAXHEIGHT];
int paulfitz_remap[256];
int paulfitz_remapping = 0;
int paulfitz_setup = 0;
int paulfitz_aux = 0;
int paulfitz_bounce = 0;
int paulfitz_frame = 0;
int paulfitz_make_map = 0;
// Use a tiny private function to output images in the trivial ppm format.
// This avoids adding a dependency on another library.
static int SavePPM(char *src, const char *filename, int w, int h) {
FILE *fp = fopen(filename, "wb");
if (!fp) {
printf("cannot open file %s for writing\n", filename);
return -1;
} else {
fprintf(fp, "P6\n%d %d\n%d\n", w, h, 255);
int i;
for (i = 0; i < h; i++) {
fwrite((void *) src, 1, (size_t) (w*3), fp);
src += w*3;
}
fclose(fp);
}
return 0;
}
void msmap_render(int w, int h) {
msmap_render_scaled(w,h,1);
}
void msmap_enable() {
paulfitz_make_map = 1;
}
void msmap_set_frame(int frame) {
paulfitz_frame = frame;
paulfitz_setup = 0;
}
int msmap_parse_name(char *name) {
if (name==NULL || (((long unsigned int) name)<256)) {
static int message_shown = 0;
if (!message_shown) {
printf("msmap_parse_name: dodgy name! (%lu)\n", (long int)name);
message_shown = 1;
}
return -1;
}
static const char *refname = "__makesweet_surface_n";
static int reflen = 21; //strlen(refname);
int idx = -1;
if (name[0]=='_') {
if (name[1]=='_') {
if (name[2]=='m') {
if (name[3]=='a') {
if (strlen(name)>reflen) {
idx = atoi(name+reflen);
}
}
}
}
}
if (idx == -1) {
static const char *refname = "mkswt_";
static int reflen = 6; //strlen(refname);
static char buf[256];
if (name[0]=='m') {
if (name[1]=='k') {
if (name[2]=='s') {
if (name[3]=='w') {
if (strlen(name)>reflen) {
int at = 0;
int i = 0;
for (i=0; i<strlen(name); i++) {
char ch = name[i];
if (ch=='@') break;
if (ch>='0'&&ch<='9') {
buf[at] = ch;
if (at<200) at++;
}
}
buf[at] = '\0';
//idx = atoi(name+reflen)-1;
printf("From %s got %s\n", name, buf);
idx = atoi(buf)-1;
printf("GOT INDEX %d\n",idx);
}
}
}
}
}
}
#ifdef DBG
printf("Parse %s as %d\n", name, idx);
#endif
return idx;
}
void msmap_set_bounce(int bounce) {
paulfitz_bounce = bounce;
}
void msmap_set_input(int idx, float fx, float fy) {
//printf("Set input %d %g %g\n", idx, fx, fy);
if (paulfitz_remapping) {
idx = paulfitz_remap[idx];
if (idx==-1) {
return;
}
}
if (idx>paulfitz_max_layer) {
paulfitz_max_layer = idx;
}
#ifdef DISABLE_ME
static int message_shown = 0;
if (!message_shown) {
printf("MSMAP invoked, but it is disabled so ignoring (msmap_set_input)\n");
message_shown = 1;
}
return;
#endif
#ifdef DBG
printf("Set input %d %g %g\n", idx, fx, fy);
#endif
static int env_checked = 0;
static int gave_warning = 0;
if (!env_checked) {
char *e = getenv("MAKESWEET_MAKE_MAP");
if (e!=NULL) {
paulfitz_make_map = (e[0]=='1')?1:0;
printf("MAKESWEET_MAKE_MAP variable is %d\n", paulfitz_make_map);
}
env_checked = 1;
}
if (!paulfitz_make_map) {
#ifdef DBG
printf("MAKESWEET_MAKE_MAP not set up, skipping\n");
#endif
return;
}
#ifdef DBG
printf("idx is %d\n", idx);
#endif
if (idx>=0) {
if (!paulfitz_active) {
if (gave_warning<10) {
printf("WARNING: IMAGEWRAPOSA without active\n");
} else if (gave_warning == 10) {
printf("WARNING: last warning about IMAGEWRAPOSA without active\n");
}
gave_warning++;
} else {
if (!paulfitz_setup) {
int i, j, k;
printf("paulfitz setting up\n");
for (i=0; i<PAULFITZ_MAXWIDTH; i++) {
for (j=0; j<PAULFITZ_MAXHEIGHT; j++) {
for (k=0; k<PAULFITZ_MAXLAYER; k++) {
paulfitz_xx[k][i][j] = 0;
paulfitz_yy[k][i][j] = 0;
//paulfitz_xx2[k][i][j] = 0;
//paulfitz_yy2[k][i][j] = 0;
paulfitz_ct[k][i][j] = 0;
}
paulfitz_idx[i][j] = 0;
paulfitz_ray[i][j] = 127;
}
}
printf("paulfitz set up\n");
paulfitz_setup = 1;
}
float dist = 0.0;
int ray = paulfitz_bounce;
if (paulfitz_px>=0 && paulfitz_py>=0 &&
paulfitz_px<PAULFITZ_MAXWIDTH &&
paulfitz_py<PAULFITZ_MAXHEIGHT &&
idx<PAULFITZ_MAXLAYER) {
if (ray<=paulfitz_ray[paulfitz_px][paulfitz_py]) {
if (ray<paulfitz_ray[paulfitz_px][paulfitz_py]) {
int k;
for (k=0; k<=paulfitz_max_layer; k++) {
paulfitz_xx[k][paulfitz_px][paulfitz_py] = 0;
paulfitz_yy[k][paulfitz_px][paulfitz_py] = 0;
paulfitz_ct[k][paulfitz_px][paulfitz_py] = 0;
}
paulfitz_ray[paulfitz_px][paulfitz_py] = ray;
}
paulfitz_xx[idx][paulfitz_px][paulfitz_py] += fx;
paulfitz_yy[idx][paulfitz_px][paulfitz_py] += fy;
//paulfitz_xx2[idx][paulfitz_px][paulfitz_py] += fx*fx;
//paulfitz_yy2[idx][paulfitz_px][paulfitz_py] += fy*fy;
paulfitz_ct[idx][paulfitz_px][paulfitz_py]++;
}
}
}
}
}
void msmap_set_output(int rx, int ry) {
#ifdef DBG
printf("Set output %d %d\n", rx, ry);
#endif
paulfitz_px = rx;
paulfitz_py = ry;
paulfitz_active = 1;
paulfitz_bounce = 0;
}
void msmap_unset_output() {
//paulfitz_px = 0;
//paulfitz_py = 0;
paulfitz_active = 0;
}
void msmap_set_aux(int aux) {
paulfitz_aux = aux;
}
void msmap_render_scaled(int w, int h, int factor) {
#ifdef DBG
printf("Makesweet Render %d %d\n", w, h);
#endif
if (factor!=1) {
printf("rescale is not implemented\n");
exit(1);
}
if (!paulfitz_setup) {
printf("MAKESWEET no output to write\n");
} else {
printf("MAKESWEET writing output %dx%d\n", w, h);
int i, j;
int ww = w/factor, hh = h/factor; // should be 4:3 aspect ratio
int ww2 = w, hh2 = h;
int dx = (ww2-ww)/2; // now always 0
int dy = (hh2-hh)/2; // now always 0
unsigned char *img = (unsigned char *) calloc(3,ww2*hh2);
unsigned char *img2 = (unsigned char *) calloc(3,ww2*hh2);
if (img!=NULL && img2!=NULL) {
memset(img,255,3*ww2*hh2);
memset(img2,255,3*ww2*hh2);
for (i=0; i<ww; i++) {
for (j=0; j<hh; j++) {
int d = 2;
if (!(i>=d&&j>=d&&i<ww-d&&j<hh-d)) {
d = 0;
}
int d2 = 1;
if (!(i>=d2&&j>=d2&&i<ww-d2&&j<hh-d2)) {
d2 = 0;
}
int max_ct = 0;
int tot_ct = 0;
//float best_sig = 1e9;
//float second_best_sig = 1e9;
//int winner_sig = -1;
int winner = -1;
int k, kx, ky;
/*
int cts[PAULFITZ_MAXLAYER];
//float txx[PAULFITZ_MAXLAYER];
//float txx2[PAULFITZ_MAXLAYER];
//float tyy[PAULFITZ_MAXLAYER];
//float tyy2[PAULFITZ_MAXLAYER];
//float sig2[PAULFITZ_MAXLAYER];
for (k=0; k<=paulfitz_max_layer; k++) {
cts[k] = 0;
}
for (kx=-d; kx<=d; kx++) {
for (ky=-d; ky<=d; ky++) {
for (k=0; k<=paulfitz_max_layer; k++) {
cts[k] += paulfitz_ct[k][i+kx][j+ky];
//txx[k] += paulfitz_xx[k][i+kx][j+ky];
//txx2[k] += paulfitz_xx2[k][i+kx][j+ky];
//tyy[k] += paulfitz_yy[k][i+kx][j+ky];
//tyy2[k] += paulfitz_yy2[k][i+kx][j+ky];
}
}
}
*/
for (k=0; k<=paulfitz_max_layer; k++) {
//int ct = cts[k];
int ct = paulfitz_ct[k][i][j];
//if (ct>0) {
//sig2[k] = txx2[k] - txx[k]*txx[k] + tyy2[k] - tyy[k]*tyy[k];
//}
//if (sig2[k]<best_sig) {
//second_best_sig = best_sig;
//best_sig = sig2[k];
//winner_sig = k;
//}
if (ct>max_ct) {
max_ct = ct;
winner = k;
}
tot_ct += ct;
}
//if (winner_sig>=0) {
//if (paulfitz_ct[winner_sig][i][j]>10) {
//winner = winner_sig;
//}
//}
float xx = 0;
float yy = 0;
int rct = 0;
if (tot_ct>0) {
if (max_ct>tot_ct*0.55) { // || best_sig<second_best_sig*0.8) {
paulfitz_idx[i][j] = winner+1;
/*
int c = 0;
int c2 = 0;
for (kx=-d2; kx<=d2; kx++) {
for (ky=-d2; ky<=d2; ky++) {
int lct = paulfitz_ct[winner][i+kx][j+ky];
c++;
if (lct<1) {
if (kx!=0||ky!=0) continue;
lct = 1;
}
c2++;
xx += paulfitz_xx[winner][i+kx][j+ky]/lct;
yy += paulfitz_yy[winner][i+kx][j+ky]/lct;
}
}
if (c!=c2) {
int lct = paulfitz_ct[winner][i][j];
if (lct<1) lct = 1;
xx = paulfitz_xx[winner][i][j]/lct;
yy = paulfitz_yy[winner][i][j]/lct;
} else {
xx /= c;
yy /= c;
}
*/
int lct = paulfitz_ct[winner][i][j];
if (lct<1) lct = 1;
xx = paulfitz_xx[winner][i][j]/lct;
yy = paulfitz_yy[winner][i][j]/lct;
rct = 1;
} else {
paulfitz_idx[i][j] = -1; // mixed-up
}
}
int q1 = 255;
int q2 = 255;
int q3 = 255;
if (rct) {
int x = (int)(xx*4096+4096+0.5);
int y = (int)(yy*4096+4096+0.5);
if (x>4095) x -= 4096;
if (y>4095) y -= 4096;
if (x>4095) x = 4095;
if (y>4095) y = 4095;
if (x<0) x = 0;
if (y<0) y = 0;
y = 4095-y;
int p1 = x%256;
int p2 = x/256;
int p3 = y%256;
int p4 = y/256;
q1 = p1;
q2 = p3;
q3 = p2 + 16*p4;
}
if (i<ww && j<hh) {
int at = ((hh2-1-(dy+j))*ww+dx+i)*3;
img[at] = (unsigned char) q1;
img[at+1] = (unsigned char) q2;
img[at+2] = (unsigned char) q3;
}
}
}
int maxn = paulfitz_max_layer + 1;
int tricky = 0;
for (i=0; i<ww; i++) {
for (j=0; j<hh; j++) {
int idx = paulfitz_idx[i][j];
int q1 = 255;
int q2 = 255;
int q3 = 255;
if (idx>0) {
q1 = idx;
q2 = idx*64;
q3 = 0;
} else if (idx==-1) {
tricky = 1;
}
int at = ((hh2-1-(dy+j))*ww+dx+i)*3;
img2[at] = (unsigned char) q1;
img2[at+1] = (unsigned char) q2;
img2[at+2] = (unsigned char) q3;
}
}
SavePPM((char *)img, "mapper.ppm", ww2, hh2);
SavePPM((char *)img2, "mapper2.ppm", ww2, hh2);
FILE *fout = fopen("mapper.txt","w");
if (fout==NULL) {
printf("cannot write to mapper.txt");
exit(1);
}
fprintf(fout,"maxn=%d\n", maxn);
fprintf(fout,"tricky=%d\n", tricky);
printf("PAULFITZ wrote mapper.ppm mapper2.ppm mapper.txt\n");
free(img);
free(img2);
img = NULL;
}
}
paulfitz_setup = 0;
}
int msmap_set_index(int external_index, int internal_index) {
int i;
if (!paulfitz_remapping) {
paulfitz_remapping = 1;
for (i=0; i<256; i++) {
paulfitz_remap[i] = -1;
}
}
paulfitz_remap[internal_index] = external_index;
return 0;
}

25
src/msmap.h Normal file
View File

@@ -0,0 +1,25 @@
#ifndef HAVE_MSMAP_H
#define HAVE_MSMAP_H
#ifdef __cplusplus
extern "C" {
#endif
void msmap_enable();
void msmap_set_frame(int frame);
void msmap_set_aux(int is_aux);
void msmap_set_output(int rx, int ry);
void msmap_unset_output();
void msmap_set_input(int index, float fx, float fy);
void msmap_set_bounce(int bounce);
int msmap_parse_name(char *name);
int msmap_set_index(int external_index, int internal_index);
void msmap_render(int w, int h);
void msmap_render_scaled(int w, int h, int factor);
#ifdef __cplusplus
}
#endif
#endif

132
src/nonblend.cpp Normal file
View File

@@ -0,0 +1,132 @@
#include <stdio.h>
#include <math.h>
#include <yarp/sig/Image.h>
#include <yarp/sig/ImageFile.h>
#include <yarp/sig/ImageDraw.h>
using namespace yarp::sig;
using namespace yarp::sig::file;
double punfix(int r) {
return (r/255.0)*2.0-1;
}
int pfix(double x) {
x = (x+1)/2;
int r = (int)(x*255.0+0.5);
if (r>255) r = 255;
if (r<0) r = 0;
return r;
}
void process2(ImageOf<PixelRgb>& dest,ImageOf<PixelRgb>& overlay) {
int w = 512;
dest.resize(w,w);
double maxerr = 0.0;
IMGFOR(dest,x,y) {
PixelRgb& pix = dest(x,y);
PixelRgb over;
double fx = x/((double)w);
double fy = y/((double)w);
// fx = [0:1)
// fy = [0:1)
double theta = fx*M_PI;
double phi = fy*M_PI*2;
double xx = sin(theta)*cos(phi);
double yy = sin(theta)*sin(phi);
double zz = cos(theta);
// xx, yy, zz: [-1:1]
int pr = pfix(xx);
int pg = pfix(yy);
int pb = pfix(zz);
pix.r = pr;
pix.g = pg;
pix.b = pb;
// inversion
double x2=punfix(pix.r);
double y2=punfix(pix.g);
double z2=punfix(pix.b);
double len = sqrt(x2*x2+y2*y2+z2*z2);
double phi2 = atan2(y2,x2);
double theta2 = acos(z2/len);
if (theta2<0) theta2 += M_PI;
if (phi2<0) phi2 += M_PI*2;
double theta3 = asin(sqrt(xx*xx+yy*yy));
if (theta3<0) theta3 += M_PI;
if (fabs(theta2-theta3)>=0.1) {
theta3 = M_PI-theta3;
}
if (fabs(theta2-theta3)<0.1) {
theta2 = (theta2+theta3)/2;
//printf("MATCH %g : %g\n", theta2, theta3);
} else {
printf("Mismatch %g : %g\n", theta2, theta3);
}
double ex = (theta2/(M_PI))*w;
double ey = (phi2/(M_PI*2.0))*w;
double err = sqrt((ex-x)*(ex-x)+(ey-y)*(ey-y));
if (x>5 && y>5 && x<w-6 && y<w-6) {
//if (err>10) {
//printf("err %g: %g %g / %d %d\n", err, ex, ey, x, y);
//}
if (err>8) {
printf("len %g err %g: %g %g / %d %d\n", len, err, ex, ey, x, y);
}
if (err>maxerr) maxerr = err;
}
}
printf("Maximum error is %g\n", maxerr);
}
void process(ImageOf<PixelRgb>& dest,ImageOf<PixelRgb>& overlay) {
int w = 512;
dest.resize(w,w);
IMGFOR(dest,x,y) {
PixelRgb& pix = dest(x,y);
PixelRgb over;
double fx = x/((double)w-1);
double fy = y/((double)w-1);
pix.r = int(fx*255+0.5);
pix.g = int(fy*255+0.5);
if (overlay.width()>0) {
pix.b = 255-overlay(x,y).r;
if (pix.b==0) {
pix.b = (pix.r%51==0||pix.g%51==0)?(((x+y)%2)?128:255):pix.b;
}
} else {
pix.b = (pix.r%51==0||pix.g%51==0)?255:0;
if (fabs(x-w/2.0)+fabs(y-w/2.0)<w/16) {
pix.b = (y<w/2)?255:((x<w/2)?128:64);
}
}
}
}
int main(int argc, char *argv[]) {
if (argc<2) {
printf("Need an out file\n");
return 1;
}
char *overlay_name = NULL;
if (argc>=3) {
overlay_name = argv[2];
}
char *output_name = argv[1];
ImageOf<PixelRgb> output, overlay;
if (overlay_name!=NULL) {
printf("template %s\n", overlay_name);
read(overlay,overlay_name);
}
process2(output,overlay);
printf("Writing %s\n", output_name);
write(output,output_name);
return 0;
}

149
src/reanimator.cpp Normal file
View File

@@ -0,0 +1,149 @@
#include <stdio.h>
#include <stdlib.h>
#include <yarp/sig/Image.h>
#include <yarp/sig/ImageFile.h>
#include <yarp/sig/ImageDraw.h>
#include <yarp/os/Network.h>
#include "Filer.h"
#include "Prop.h"
#include "Repository.h"
#include "Input.h"
#include "Render.h"
#include "Renders.h"
#include "GifAnim.h"
#include "Dbg.h"
using namespace std;
using namespace yarp::os;
using namespace yarp::sig;
using namespace yarp::sig::file;
int __ms_verbose = 0;
int main(int argc, char *argv[]) {
if (Network::getEnvironment("VERBOSE")=="1") {
__ms_verbose = 1;
}
Property options;
options.fromCommand(argc,argv);
Repository repo;
if (!options.check("zip")) {
fprintf(stderr, "reanimator --zip foo.zip --in img1.png img2.png\n");
fprintf(stderr, "reanimator ... --w 200 --h 150\n");
fprintf(stderr, "reanimator ... --first 2\n");
fprintf(stderr, "reanimator ... --last 4\n");
fprintf(stderr, "reanimator ... --single\n");
fprintf(stderr, "reanimator ... --auto_zoom\n");
fprintf(stderr, "reanimator ... --save \"frame_%%06d.jpg\"\n");
fprintf(stderr, "reanimator ... --gif example.gif\n");
fprintf(stderr, "reanimator ... --stats\n");
fprintf(stderr, "reanimator ... --files\n");
exit(1);
}
repo.load(options.find("zip").asString().c_str());
Inputs ins;
Bottle& lst = options.findGroup("in");
for (int i=1; i<lst.size(); i++) {
Input& in = ins.add();
in.load(lst.get(i).asString().c_str());
in.layer = i;
}
Renders renders;
renders.attach_repository(&repo);
renders.attach_inputs(&ins);
if (options.check("w")&&options.check("h")) {
renders.set_size(options.find("w").asInt(),options.find("h").asInt());
}
int first = options.check("first",Value(0)).asInt();
int last = options.check("last",Value(repo.length()-1)).asInt();
if (options.check("single")) {
first = last = 0;
}
if (options.check("auto_zoom")) {
renders.auto_zoom();
}
if (options.check("save")) {
for (int i=first; i<=last; i++) {
Render *r = renders.get_render(i);
if (!r) exit(1);
char buf[256];
sprintf(buf,options.check("save",Value("frame_%06d.jpg")).asString().c_str(),i);
r->save(buf);
dbg_printf("Wrote to %s\n", buf);
}
}
if (options.check("gif")) {
GifAnim anim;
anim.attach_renders(&renders);
anim.set_palette(repo.get_palette());
anim.set_timing(repo.get_period(),repo.get_hold());
anim.apply();
anim.save(options.find("gif").asString().c_str());
}
if (options.check("files")) {
printf("animation=%s\n", repo.is_animation()?"true":"false");
printf("length=%d\n", repo.length());
printf("period=%g\n", repo.get_period());
printf("hold=%g\n", repo.get_hold());
printf("zoom=%g\n", repo.get_zoom());
Mapping *mapping = repo.get_mapping();
if (mapping) {
printf("light=\"%s\"\n", mapping->light_name.c_str());
printf("dark=\"%s\"\n", mapping->dark_name.c_str());
printf("map1=\"%s\"\n", mapping->map1_name.c_str());
printf("map2=\"%s\"\n", mapping->map2_name.c_str());
printf("neutral=\"%s\"\n", mapping->neutral_name.c_str());
}
mapping = repo.get_thumb_mapping();
if (mapping) {
printf("thumb_light=\"%s\"\n", mapping->light_name.c_str());
printf("thumb_dark=\"%s\"\n", mapping->dark_name.c_str());
printf("thumb_map1=\"%s\"\n", mapping->map1_name.c_str());
printf("thumb_map2=\"%s\"\n", mapping->map2_name.c_str());
printf("thumb_neutral=\"%s\"\n", mapping->neutral_name.c_str());
}
if (repo.is_animation()) {
for (int i=0; i<repo.length(); i++) {
char prefix[256];
sprintf(prefix,"frame_%d_", i);
mapping = repo.get_mapping(i);
printf("%slight=\"%s\"\n", prefix, mapping->light_name.c_str());
printf("%sdark=\"%s\"\n", prefix, mapping->dark_name.c_str());
printf("%smap1=\"%s\"\n", prefix, mapping->map1_name.c_str());
printf("%smap2=\"%s\"\n", prefix, mapping->map2_name.c_str());
printf("%sneutral=\"%s\"\n", prefix, mapping->neutral_name.c_str());
}
}
}
if (options.check("stats")) {
fprintf(stderr,"Peak number of mappings cached: %d\n", repo.peak());
fprintf(stderr,"Peak number of renders cached: %d\n", renders.peak());
fprintf(stderr,"Total number of frames: %d\n", repo.length());
fprintf(stderr,"Total number of renders: %d\n",
Render::render_count());
fprintf(stderr,"Palette frame(s):");
vector<int> pals = repo.get_palette();
for (int i=0; i<(int)pals.size(); i++) {
fprintf(stderr," %d", pals[i]);
}
fprintf(stderr,"\n");
}
return 0;
}

71
src/reblend.cpp Normal file
View File

@@ -0,0 +1,71 @@
#include <stdio.h>
#include <yarp/sig/Image.h>
#include <yarp/sig/ImageFile.h>
#include <yarp/sig/ImageDraw.h>
#include "msmap.h"
using namespace yarp::sig;
using namespace yarp::sig::file;
int diff(PixelRgb& p1, PixelRgb& p2) {
return
(p1.r-p2.r)*(p1.r-p2.r)+
(p1.g-p2.g)*(p1.g-p2.g)+
(p1.b-p2.b)*(p1.b-p2.b);
}
void process(ImageOf<PixelRgb>& src, ImageOf<PixelRgb>& light, ImageOf<PixelRgb>& dark) {
printf("Size %d %d\n", src.width(), src.height());
msmap_enable();
msmap_set_frame(0);
int k = 2;
int d = 2;
IMGFOR(src,x,y) {
PixelRgb& pix = src(x,y);
if (pix.r>0||pix.g>0||pix.r>0) {
PixelRgb& li = light(x,y);
PixelRgb& da = dark(x,y);
if (diff(li,da)>10) {
msmap_set_output(x,src.height()-1-y);
double fx = pix.r/255.0;
double fy = pix.g/255.0;
msmap_set_input(0,fx,1-fy);
// smoothing
for (int kk=0; kk<k; kk++) {
for (int xx=-d; xx<=d; xx++) {
for (int yy=-d; yy<=d; yy++) {
if (x+xx>=0 && y+yy>=0 && x+xx<src.width() &&
y+yy<src.height()) {
msmap_set_aux(xx!=0||yy!=0);
msmap_set_output(x+xx,src.height()-1-y-yy);
msmap_set_input(0,fx,1-fy);
}
}
}
}
}
}
}
msmap_render(src.width(),src.height());
}
int main(int argc, char *argv[]) {
if (argc<4) {
printf("Need an input map file, a light file, a dark file\n");
return 1;
}
char *input_name = argv[1];
char *light_name = argv[2];
char *dark_name = argv[3];
ImageOf<PixelRgb> input, light, dark;
read(input,input_name);
read(light,light_name);
read(dark,dark_name);
process(input,light,dark);
return 0;
}

Binary file not shown.

BIN
templates/frog.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB