Re: [Tuxpaint-dev] stamp production tool

2004-12-01 Thread Bill Kendrick
On Wed, Dec 01, 2004 at 03:32:56PM -0500, Albert Cahalan wrote:
> Here's a little tool I just made for creating alpha channels.
> It should be useful whenever you have a simple background.

Don't have time to read your entire e-mail, but cool! Thanks!
I realize alpha channels can be complex, and have always wanted some
tools to help with the alpha stuff.

I thought a little "Add alpha" GUI might be neat.  It coudl also have
checkboxes and settings for the other various options stamps can have
(copy a random sfx and save it as an appropriate WAV... add a text desc...
turn on tinting / no-flip / default scale / etc.)

Thx

-bill!
___
Tuxpaint-dev mailing list
[EMAIL PROTECTED]
http://tux4kids.net/mailman/listinfo/tuxpaint-dev


[Tuxpaint-dev] stamp production tool

2004-12-01 Thread Albert Cahalan
Here's a little tool I just made for creating alpha channels.
It should be useful whenever you have a simple background.

1. save the original as a binary *.ppm file
2. save another copy, with the foreground painted away
3. save another copy, with the background painted away
4. run the tool to create an alpha image

Now you have a rough alpha image. Edit it as needed to
make the opaque parts fully white and the transparent
parts fully black. To avoid background color fringes on
the finished stamp, use the tool again. Feed it all 4
images you have, and you'll get back a new foreground
image that doesn't have any background mixed with it.

Note: the crazy colors are somewhat OK; they come from
the effectively limited bit depth of foreground objects
in semi-transparent areas being expanded to a full 8 bits.
Things should work out OK when the image is used.

A possible enhancement might be to blur the images in
proportion to transparency. This would reduce noise.

BTW, the alpha image is not a true *.pgm file. It's linear.
The *.ppm files all use the sRGB color space.

/

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

static unsigned width, height;

#define TYPE_PGM '5'
#define TYPE_PPM '6'

//
// quick hack reader for binary P*M files
static unsigned char *readpnm(const char *name, int desired){
  int fd = open(name, O_RDONLY);
  char *cp;
  int type;
  struct stat sbuf;
  fstat(fd, &sbuf);
  cp = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
  close(fd);

  if(cp[0] != 'P') exit(7);
  type = cp[1];
  if(type != TYPE_PGM && type != TYPE_PPM) exit(56);
  cp += 2;
  while(*cp=='#' || isspace(*cp)){
if(*cp=='#') cp = strchr(cp, '\n');
else cp++;
  }
  width = strtoul(cp, &cp, 10);
  while(*cp=='#' || isspace(*cp)){
if(*cp=='#') cp = strchr(cp, '\n');
else cp++;
  }
  height = strtoul(cp, &cp, 10);
  while(*cp=='#' || isspace(*cp)){
if(*cp=='#') cp = strchr(cp, '\n');
else cp++;
  }
  if(strtoul(cp, &cp, 10)!=255) exit(33);

  cp++;

  if(type==desired)
return cp;
  if(type==TYPE_PGM){
// desired must have been 6 (color), but we want 5
// let'd pick the red channel
unsigned i = width*height;
unsigned char *data = mmap(0, i, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
while(i--){
  data[i] = cp[i*3];
}
return data;
  }
  if(type==TYPE_PPM){
// desired must have been 5 (greyscale), but we want 6
unsigned i = width*height;
unsigned char *data = mmap(0, i, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
while(i--){
  unsigned char tmp = cp[i];
  data[i*3+0] = tmp;
  data[i*3+1] = tmp;
  data[i*3+2] = tmp;
}
return data;
  }
  exit(93);
}



// project 1st vector onto 2nd vector, then divide by 2nd magnitude
static double vdist(double x, double y, double z, double x2, double y2, double 
z2){
  double dot= x *x2 + y *y2 + z *z2; // the dot product
  double magsquared = x2*x2 + y2*y2 + z2*z2; // the magnitude, squared
  return dot / magsquared;
}

///
// passed original, foreground, and background images, return an alpha channel
static unsigned char *mkalpha(const unsigned char *o, const unsigned char *f, 
const unsigned char *b){
  unsigned char *ret = malloc(width*height);
  unsigned i = width*height;
  while(i--){
unsigned char or = o[i*3+0];
unsigned char og = o[i*3+1];
unsigned char ob = o[i*3+2];
unsigned char fr = f[i*3+0];
unsigned char fg = f[i*3+1];
unsigned char fb = f[i*3+2];
unsigned char br = b[i*3+0];
unsigned char bg = b[i*3+1];
unsigned char bb = b[i*3+2];
if(fr==br && fg==bg && fb==bb){
  // foreground and background are same color... uh oh
  ret[i] = 128; // a random value :-(
  continue;
}
if(or==br && og==bg && ob==bb){
  // original and background are same color: alpha is 0
  ret[i] = 0;
  continue;
}
if(fr==or && fg==og && fb==ob){
  // foreground and original are same color: alpha is 1.0 or 255
  ret[i] = 255;
  continue;
}
double tmp;
// convert from sRGB to linear (gamma==1.0) RGB
tmp = or / 255.0; double oR = (tmp<=0.03928) ? tmp/12.92 : 
pow((tmp+0.055)/1.055,2.4);
tmp = og / 255.0; double oG = (tmp<=0.03928) ? tmp/12.92 : 
pow((tmp+0.055)/1.055,2.4);
tmp = ob / 255.0; double oB = (tmp<=0.03928) ? tmp/12.92 : 
pow((tmp+0.055)/1.055,2.4);
tmp = fr / 255.0; double fR = (tmp<=0.03928) ? tmp/12.92 : 
pow((tmp+0.055)/1.055,2.4);
tmp = fg / 255.0; double fG = (tmp<=0.03928) ? tmp/12.92 : 
pow((tmp+0.055)/1.055,2.4);
tmp = fb / 255.0; double fB = (tmp<=0.03928) ? tmp/12.92 : 
pow((tmp+0.055)/1.055,2.4);
tm