IdeaMonk

thoughts, ideas, code and other things...

Saturday, August 16, 2008

Paint Daubs effect through Allegro & C++

Went to automate some effect like this in allegro today, ended up unfinished with the paint daubs effect over bitmaps. It looks something like this -> ;)
What it basically does is draws filled circles by picking colours from original bitmap onto a copy of it. So, when many circles overlap each other they give a painting style effect. As if the image was made with short impressions of brush over and over again.
/*
Paint Daubs v.1 16 Aug 2008
An attempt at making image look like vintage art paintings.

This basic version takes a base image,
randomly creates filled circles on target image to get such effect.

Usage
------
$> paint_daubs <base.bmp> <tagert.bmp> [%blob_max] [depth] [s/c]

%blob_max is the % of size of image that a blob will size up to
depth is number of times the blobs are drawn
s/c - s for square fills, c for circles

-- Abhishek Mishra
ideamonk.blogspot.com
*/

#include <iostream>
#include <allegro.h>
using namespace std;

//Config parameters
float BASEBLOB_MAX = .02f;
float BASE_COUNT = 200.0f;


BITMAP *base, *target;
PALETTE base_pal, tar_pal;

void show_menu(char *fname){
cout << "Usage\n"
<< "------\n"
<< fname << " <base.bmp> <tagert.bmp> [%%blob_max] [depth] [s/c]\n";
}

bool init_bitmaps(char *fbase, char *ftarget){
cout << "\n[+] Loading bitmaps...\n";

// Load all three bitmaps
base = load_bitmap(fbase,base_pal);
if (!base) {
cout << " [-] Couldn't load "<<fbase <<"\n";
return false;
}

target = load_bitmap (fbase,tar_pal);
if (!target) {
cout << " [-] Couldn't create bitmap for target\n";
return false;
}

return true;
}

void process_base(char *s){
int min_dim = (base->w < base->h) ? base->w : base->h;
int bmax = (int) (BASEBLOB_MAX * min_dim);
int bmin = 2;
int times = (int) (BASE_COUNT * min_dim);
int width,color,px,py;

for (int i=0;i<times;){
width = bmin + rand() % (bmax-bmin);
px = rand() % base->w;
py = rand() % base->h;
color = getpixel(base,px,py);

if (color != makecol (255,0,255) ){
// Select fill type
if (*s=='s'){
rectfill (target,px-width/2,py-width/2,px+width/2,py+width/2, color);
} else {
circlefill(target,px,py,width/2,color);
}
i++;
}
}
}

int main (int argc, char *argv[]){
if (argc < 3){
show_menu(argv[0]);
} else {
//Allegro initialization routines
set_color_depth(32);
set_color_conversion(COLORCONV_EXPAND_HI_TO_TRUE);
allegro_init();

// Load the bitmaps
if (!init_bitmaps(argv[1],argv[2]))
return 0;

if (argc > 3)
BASEBLOB_MAX = atof(argv[3]);
if (argc > 4)
BASE_COUNT = atof(argv[4]);

cout << "[+] drwaing blobs\n";
process_base(argv[5]);

cout << "[+] saving "<< argv[2]<<"\n";
save_bitmap (argv[2],target,tar_pal);
//Debug
/*
set_gfx_mode(GFX_AUTODETECT_WINDOWED,1024,768,0,0);
blit (target,screen,0,0,0,0,800,600);
getchar();
*/
cout << "[+] done\n";

}
return 0;
}
END_OF_MAIN();

More samples (click to enlarge) =>
  • with square filter ON (s)
  • with default circlefill option and depth set to 400
To compile the source you will need Allegro working with your development environment. I use DevCPP with Allegro.devpak found at http://devpaks.org/
http://ideamonk.googlepages.com/ddl.gif
For linux & OSX, try installing Allegro and then compilling over g++ with -lalleg option.

Labels: , , ,

Sunday, August 03, 2008

Hints for SPOJ COINS

Trying out COINS(Bytelandian Gold Coins) at spoj.pl ? not getting it? Try giving life to these cryptic ideas from my scratchpad -
while they speak of recursion, to speed up try memoization technique from dynamic programming.

Labels: , ,

Recursive fractals

Off lately recursion has become much more fascinating than ever it was to me. And the obvious catalyst in this has been computer graphics. Without visualization its impossible to appreciate the beauty of recursion, trees, sorting algorithms, etc!
Having admired the Sierpinski triangles I wondered how such an experimentation would look upon squares. And I came up with the following written in devCPP & Allegro graphics library-
#include <allegro.h>

BITMAP *work;

void draw (int x,int y,int w){
int i,j,c,r,g,b;
if (x<0 || y<0 || x>639 || y>479 || w<5)
return;

int nw=w/2;
draw(x-w/2-1,y-w/2-1,nw);
draw(x+w/2+1,y+w/2+1,nw);
draw(x-w/2-1,y+w/2+1,nw);
draw(x+w/2+1,y-w/2-1,nw);

c=w;
for (w=c;w>=1;w--){
r=((float)(sin(w)*sin(w)*c/3)/(float)c)*(float)255;
g=((float)(c-w/2)/(float)c)*(float)255;
b=((float)(w/2)/(float)c)*(float)255;
if (w<1){
r=g=b=0;
}
rect(work,x-w/2,y-w/2,x+w/2,y+w/2, makecol (r,g,b));
}
w=c;
r=((float)(c-w)/(float)c)*(float)255;
g=((float)(c-w)/(float)c)*(float)255;
b=((float)w/(float)c)*(float)255;
rect(work,x-w/2-1,y-w/2-1,x+w/2+1,y+w/2+1, makecol (r/2,g/2,b/2));
}

int main (){
allegro_init();
install_keyboard();
set_color_depth(32);
set_gfx_mode (GFX_AUTODETECT_WINDOWED,640,480,0,0);

work = create_bitmap(640,480);
clear_to_color(work,makecol(255,255,255));

draw(320,240,200);
while (!key[KEY_ESC]){
vsync();
blit (work,screen,0,0,0,0,640,480);
}

allegro_exit();
return 0;
}
END_OF_MAIN();















Some circular modifications -

#include <allegro.h>

BITMAP *work;

void draw (int x,int y,int w){
int i,j,c,r,g,b;
if (x<0 || y<0 || x>SCREEN_W || y>SCREEN_H || w<5)
return;

int nw=(float)w*(float)(.5);
draw(x-w/2-1,y-w/2-1,nw);
draw(x+w/2+1,y+w/2+1,nw);
draw(x-w/2-1,y+w/2+1,nw);
draw(x+w/2+1,y-w/2-1,nw);

c=w;
for (w=c;w>=1;w--){
r=((float)(w/2)/(float)c)*(float)255;
g=((float)(c-w/2)/(float)c)*(float)255;
b=((float)(c-w/2)/(float)c)*(float)255;
if (w<1){
r=g=b=0;
}
circlefill (work,x,y,w/2,makecol (r,g,b));
}
}

int main (){
allegro_init();
install_keyboard();
set_color_depth(32);
set_gfx_mode (GFX_AUTODETECT_WINDOWED,800,600,0,0);

work = create_bitmap(SCREEN_W,SCREEN_H);
clear_to_color(work,makecol(255,255,255));

draw(SCREEN_W/2,SCREEN_H/2,300);
while (!key[KEY_ESC]){
vsync();
blit (work,screen,0,0,0,0,SCREEN_W,SCREEN_H);
}

allegro_exit();
return 0;
}
END_OF_MAIN();































beautiful! what more can I say.

Labels: , , , ,