IdeaMonk

thoughts, ideas, code and other things...

Wednesday, November 11, 2009

PyMos - Creating mosaics of your photos was never easier

PyMos is a Python script/module that helps you generate those fancy photo mosaics wherein a large image is made out of tiny thumbnails of other images. But from a distance, the mosaic looks like original image. Here is an example.
PyMos just started as an random hack which later turned into an impromptu hackathon as Yuvi puts it. Man it was fun to work together with someone for the first time, to learn so many new things, and to get more awesome ideas through discussion. Some of the noteworthy things I came through this project are - argparse, PIL, setuptools, some more git gyaan, that colorspace can be also treated like x-y-z vectors, logging in python, caching things using Pickle to save time, writing re-usable code, checking code against standards using pylint, rounding off corners and adding shadows with css, and what not.
I never wished to put too much in the blog about it. Just finished the project page for PyMos an hour ago - Get to know more about PyMos at its project page.

this is how it should look.

Besides that, while making the page I noticed a few things -
  • I happened to find a nice motive for PyMos' existence - these people who sell mosaics as a service. PyMos liberates you financially, intellectually and gives you freedom to mix-n-mash to make your own custom version... for it is a F/OSS
  • The project page would look nice in modern browsers only as I've utilized CSS3 @font-face to pull in some nice fonts.
  • I've also used CSS to save time doing round corners and shadows, so again you need a good browser that supports it, currently Firefox 3.5+ and webkit based ones.
  • By the way, PyMos project page is totally made on Linux, thanks to wine for letting me run Photoshop 7, I no longer have to look towards windows in any case, not even in times of creativity blues.
  • Since I'm not an advanced user of Photoshop, I hardly find any differences in cs3 or 7 as far as the way I use.
So, have fun making some cool mosaics with PyMos :)

Labels: , , , , , ,

Wednesday, November 19, 2008

Another processing adventure


Labels: , ,

Tuesday, November 18, 2008

Some work in Process (progress ?!)

Some work I've been recently doing in Processing 1.0. I can't show applets for these, each of them too more than 20 minutes to render! Will talk more about how I did the second one and 4th one in detail later. All this began in C++ and allegro one day... I haven't yet got the effects I wished to program :| but, processing is taking these experiments into a whole new direction!











An example for what I call circulation-fx -
Put this image into data folder int the processing project you created
This is the code that breaks it into beautiful circles -

/* Circulation-fx */
/* crappy-test version */

PGraphics buffer,checkbak;
PFont font;
PImage girl;
color blend1, blend2,src,original,test;
/* ******************* configuration variables */
int tolerance = 15, bmax = 100, bsize;
// adjust tolerance and bmax(max size for circles)

int sX, sY;
boolean possible = true;
float stime;
char c;
String s;

void setup(){
noLoop();

background (255,255,255);

/* *************** change the image here ********************** */
girl = loadImage ("surfing.jpg");
size(girl.width,girl.height);
buffer = createGraphics (girl.width,girl.height,P3D);
buffer.beginDraw();
buffer.noStroke();
buffer.background(255);
buffer.textFont(font);
buffer.endDraw();

stime=millis();
loop();
}

void draw(){
buffer.beginDraw();

possible = true;
bsize=2;

sX=int(random(screen.width));
sY=int(random(screen.height));
test = girl.get(sX,sY);

original=blend2=blend1 = girl.get (sX,sY);

while (possible && bsize<= tolerance && abs(blue(blend1)-blue(blend2)) <= tolerance && abs(green(blend1)-green(blend2)) <= tolerance){ bsize+=1; blend1=blend2; } else { possible=false; } if (bsize>bmax)
possible=false;
}

// crappy string hack
c=(char)(random(25)); c=char(c+'a'+1); s=""; s=s+c;
buffer.stroke((int)red(original),(int)green(original),(int)blue(original),
255- ((float)bsize/float(bmax))*200
);

buffer.noFill();
buffer.ellipse( sX,sY,bsize,bsize);

image(buffer,0,0);

if (millis()-stime >= 20000){
stime=millis();
saveFrame("out/frame-#######.png");
}

buffer.endDraw();
}

void mousePressed(){
noLoop();
}

void mouseReleased(){
loop();
}
Don't forget to have an 'out' folder in the project folder and the image in the 'data' folder.
have a look here too...

Labels: , ,

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: , , ,