filterset.cpp revision a00d232ef8ecb04fb29c1c7ea67f8e14df15b309
/*
* Some filters for Potrace in Inkscape
*
* Authors:
* Bob Jamison <rjamison@titan.com>
*
* Copyright (C) 2004 Bob Jamison
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#include <cstdio>
#include <stdlib.h>
#include "imagemap-gdk.h"
#include "filterset.h"
/*#########################################################################
### G A U S S I A N (smoothing)
#########################################################################*/
/**
*
*/
static int gaussMatrix[] =
{
2, 4, 5, 4, 2,
4, 9, 12, 9, 4,
5, 12, 15, 12, 5,
4, 9, 12, 9, 4,
2, 4, 5, 4, 2
};
/**
*
*/
{
int firstX = 2;
int firstY = 2;
if (!newGm)
return NULL;
for (int y = 0 ; y<height ; y++)
{
for (int x = 0 ; x<width ; x++)
{
/* image boundaries */
{
continue;
}
/* all other pixels */
int gaussIndex = 0;
unsigned long sum = 0;
for (int i= y-2 ; i<=y+2 ; i++)
{
for (int j= x-2; j<=x+2 ; j++)
{
}
}
sum /= 159;
}
}
return newGm;
}
/**
*
*/
{
int firstX = 2;
int firstY = 2;
if (!newGm)
return NULL;
for (int y = 0 ; y<height ; y++)
{
for (int x = 0 ; x<width ; x++)
{
/* image boundaries */
{
continue;
}
/* all other pixels */
int gaussIndex = 0;
int sumR = 0;
int sumG = 0;
int sumB = 0;
for (int i= y-2 ; i<=y+2 ; i++)
{
for (int j= x-2; j<=x+2 ; j++)
{
}
}
}
}
return newGm;
}
/*#########################################################################
### C A N N Y E D G E D E T E C T I O N
#########################################################################*/
static int sobelX[] =
{
-1, 0, 1 ,
-2, 0, 2 ,
-1, 0, 1
};
static int sobelY[] =
{
1, 2, 1 ,
0, 0, 0 ,
-1, -2, -1
};
/**
* Perform Sobel convolution on a GrayMap
*/
double dLowThreshold, double dHighThreshold)
{
int firstX = 1;
int firstY = 1;
if (!newGm)
return NULL;
for (int y = 0 ; y<height ; y++)
{
for (int x = 0 ; x<width ; x++)
{
unsigned long sum = 0;
/* image boundaries */
{
sum = 0;
}
else
{
/* ### SOBEL FILTERING #### */
long sumX = 0;
long sumY = 0;
int sobelIndex = 0;
for (int i= y-1 ; i<=y+1 ; i++)
{
for (int j= x-1; j<=x+1 ; j++)
{
sobelX[sobelIndex++];
}
}
sobelIndex = 0;
for (int i= y-1 ; i<=y+1 ; i++)
{
for (int j= x-1; j<=x+1 ; j++)
{
sobelY[sobelIndex++];
}
}
/*### GET VALUE ### */
if (sum > 765)
sum = 765;
#if 0
/*### GET ORIENTATION (slow, pedantic way) ### */
double orient = 0.0;
if (sumX==0)
{
if (sumY==0)
orient = 0.0;
else if (sumY<0)
{
orient = 90.0;
}
else
orient = 90.0;
}
else
{
if (orient < 0.0)
orient += 180.0;
}
/*### GET EDGE DIRECTION ### */
int edgeDirection = 0;
if (orient < 22.5)
edgeDirection = 0;
else if (orient < 67.5)
edgeDirection = 45;
else if (orient < 112.5)
edgeDirection = 90;
else if (orient < 157.5)
edgeDirection = 135;
#else
/*### GET EDGE DIRECTION (fast way) ### */
int edgeDirection = 0; /*x,y=0*/
if (sumX==0)
{
if (sumY!=0)
edgeDirection = 90;
}
else
{
/*long slope = sumY*1024/sumX;*/
edgeDirection = 90;
edgeDirection = 45;
edgeDirection = 135;
}
#endif
/* printf("%ld %ld %f %d\n", sumX, sumY, orient, edgeDirection); */
/*### Get two adjacent pixels in edge direction ### */
unsigned long leftPixel;
unsigned long rightPixel;
if (edgeDirection == 0)
{
}
else if (edgeDirection == 45)
{
}
else if (edgeDirection == 90)
{
}
else /*135 */
{
}
/*### Compare current value to adjacent pixels ### */
/*### if less that either, suppress it ### */
sum = 0;
else
{
unsigned long highThreshold =
(unsigned long)(dHighThreshold * 765.0);
unsigned long lowThreshold =
(unsigned long)(dLowThreshold * 765.0);
if (sum >= highThreshold)
else if (sum < lowThreshold)
sum = 0; /* NONEDGE */
else
{
else
sum = 0; /* NONEDGE */
}
}
}/* else */
if (sum==0) /* invert light & dark */
sum = 765;
else
sum = 0;
}/* for (x) */
}/* for (y) */
return newGm;
}
/**
*
*/
GrayMap *
{
if (!gm)
return NULL;
if (!gaussGm)
return NULL;
/*gaussGm->writePPM(gaussGm, "gauss.ppm");*/
if (!cannyGm)
return NULL;
/*cannyGm->writePPM(cannyGm, "canny.ppm");*/
return cannyGm;
}
/**
*
*/
{
if (!img)
return NULL;
if (!grayMap)
return NULL;
/*grayMap->writePPM(grayMap, "gbefore.ppm");*/
if (!cannyGm)
return NULL;
/*grayMap->writePPM(grayMap, "gafter.ppm");*/
return newImg;
}
/*#########################################################################
### Q U A N T I Z A T I O N
#########################################################################*/
typedef struct OctreeNode_def OctreeNode;
/**
* The basic octree node
*/
struct OctreeNode_def
{
unsigned long r;
unsigned long g;
unsigned long b;
unsigned int index;
unsigned long nrPixels;
unsigned int nrChildren;
};
/**
* create an octree node, and initialize it
*/
{
if (!node)
return NULL;
node->r = 0;
node->g = 0;
node->b = 0;
node->nrChildren = 0;
for (int i=0 ; i<8 ; i++)
return node;
}
/**
* delete an octree node and its children
*/
{
if (!node)
return;
for (int i=0 ; i<8 ; i++)
}
/**
* delete the children of an octree node
*/
{
if (!node)
return;
node->nrChildren = 0;
for (int i=0 ; i<8 ; i++)
{
}
}
/**
* insert an RGB value into an octree node according to its
* high-order rgb vector bits
*/
{
int r = rgb.r;
int g = rgb.g;
int b = rgb.b;
int shift = 7;
{
/* update values of all nodes from the root to the leaf */
node->r += r;
node->g += g;
node->b += b;
(((b >> shift) & 1) ) ;
if (!child)
{
child = octreeNodeCreate();
node->nrChildren++;
}
shift--;
}
return newColor;
}
/**
* find an exact match for an RGB value, at the given bits
* per sample. if not found, return -1
*/
{
int r = rgb.r;
int g = rgb.g;
int b = rgb.b;
int shift = 7;
{
(((b >> shift) & 1) ) ;
if (!child)
return -1;
shift--;
}
printf("error. this should not happen\n");
return -1;
}
{
for (int i=0; i<nr ; i++)
printf(" ");
}
/**
* pretty-print an octree node and its children
*/
{
for (unsigned int i=0; i<8; i++)
{
if (!child)
continue;
}
}
/**
* Count how many nodes in this (sub)tree
*/
{
int count = 1;
for (unsigned int i=0; i<8; i++)
{
if (!child)
continue;
}
return count;
}
/**
* Count all of the leaf nodes in the octree
*/
{
if (!node)
return;
{
}
for (int i=0 ; i<8 ; i++)
}
/**
* Count all of the leaf nodes in the octree
*/
{
if (!node)
return 0;
if (node->nrChildren == 0)
return 1;
int leaves = 0;
for (int i=0 ; i<8 ; i++)
return leaves;
}
/**
* Mark all of the leaf nodes in the octree with an index nr
*/
{
if (!node)
return;
if (node->nrChildren == 0)
{
return;
}
for (int i=0 ; i<8 ; i++)
}
/**
* Find a node that has children, and that also
* has the lowest pixel count
*/
{
if (!node)
return;
if (node->nrChildren == 0)
{
*lowestLeaf = node;
return;
}
for (int i=0 ; i<8 ; i++)
}
/**
* reduce the leaves on an octree to a given number
*/
{
{
if (!lowestLeaf)
break; //should never happen
if (lowestLeaf==root)
{
printf("found no leaves\n");
continue;
}
if (!parent)
continue;
for (int i=0 ; i<8 ; i++)
{
if (child == lowestLeaf)
{
parent->nrChildren--;
break;
}
}
/*printf("leafCount:%d lowPixels:%lu\n",
leafCount, lowestLeaf->nrPixels);*/
}
int index = 0;
//printf("leafCount:%d\n", leafCount);
//octreeNodePrint(root, 0);
return leafCount;
}
/**
*
*/
{
if (!root)
return NULL;
{
{
}
}
{
return NULL;
}
/* octreeNodePrint(root, 0); */
return root;
}
/* Compare two rgb's for brightness, for the qsort() below */
static int compRGB(const void *a, const void *b)
{
return comp;
}
/**
*
*/
{
if (!palette)
{
return NULL;
}
int len = 0;
if (!rgbpal)
{
return NULL;
}
for (int i=0; i<len ; i++)
{
{
continue;
}
//printf("Pal: %d %d %d %d\n", rgb.r, rgb.g, rgb.b, index);
}
/* sort by brightness, to avoid high contrasts */
return rgbpal;
}
/**
* Return the closest color in the palette to the request
*/
{
/* slow method */
unsigned long closestMatch = 10000000;
RGB closestRGB = { 0 , 0, 0 };
*closestIndex = 0;
for (int i=0 ; i<paletteSize ; i++)
{
if (match < closestMatch)
{
*closestIndex = i;
closestRGB = entry;
}
}
return closestRGB;
}
/**
* Quantize an RGB image to a reduced number of colors. bitsPerSample
* is usually 3 - 5 out of 8 to conserve cpu and memory
*/
{
if (!rgbMap)
return NULL;
if (!otree)
{
return NULL;
}
/*Make sure we don't request more colors than actually exist*/
if (!rgbpal)
{
return NULL;
}
/*We have our original and palette. Make the new one*/
if (!newMap)
{
return NULL;
}
/* fill in the color lookup table */
for (int i=0 ; i< nrColors ; i++)
{
}
{
{
//int indexNr = octreeNodeFind(otree, rgb, bitsPerSample);
//printf("i:%d\n", indexNr);
//RGB quantRgb = rgbpal[indexNr];
int closestIndex;
}
}
return newMap;
}
/**
* Experimental. Work on this later
*/
{
int bitsPerSample = 4;
//gaussMap->writePPM(gaussMap, "rgbgauss.ppm");
//qMap->writePPM(qMap, "rgbquant.ppm");
/* RGB is quantized. There should now be a small set of (R+G+B) */
{
{
if (sum & 1)
sum = 765;
else
sum = 0;
/*printf("%d %d %d : %d\n", rgb.r, rgb.g, rgb.b, index);*/
}
}
return gm;
}
/*#########################################################################
### E N D O F F I L E
#########################################################################*/