Code

* INTL - fixed: "Crop to" dropdown strings not translated for PDF Import
[inkscape.git] / src / trace / filterset.cpp
index 2dace61ce44d007108c4f6dce93b394c0da44bf0..908985225aca001850fb908508478fec96197dab 100644 (file)
@@ -3,8 +3,9 @@
  *
  * Authors:
  *   Bob Jamison <rjamison@titan.com>
+ *   Stéphane Gimenez <dev@gim.name>
  *
- * Copyright (C) 2004 Bob Jamison
+ * Copyright (C) 2004-2006 Authors
  *
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
@@ -14,7 +15,7 @@
 
 #include "imagemap-gdk.h"
 #include "filterset.h"
-
+#include "quantize.h"
 
 /*#########################################################################
 ### G A U S S I A N  (smoothing)
@@ -353,18 +354,12 @@ grayMapCanny(GrayMap *gm, double lowThreshold, double highThreshold)
 {
     if (!gm)
         return NULL;
-    GrayMap *gaussGm = grayMapGaussian(gm);
-    if (!gaussGm)
-        return NULL;
-    /*gaussGm->writePPM(gaussGm, "gauss.ppm");*/
 
-    GrayMap *cannyGm = grayMapSobel(gaussGm, lowThreshold, highThreshold);
+    GrayMap *cannyGm = grayMapSobel(gm, lowThreshold, highThreshold);
     if (!cannyGm)
         return NULL;
     /*cannyGm->writePPM(cannyGm, "canny.ppm");*/
 
-    gaussGm->destroy(gaussGm);
-
     return cannyGm;
 }
 
@@ -405,500 +400,9 @@ gdkCanny(GdkPixbuf *img, double lowThreshold, double highThreshold)
     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;
-    OctreeNode *parent;
-    OctreeNode *children[8];
-};
-
-
-/**
- * create an octree node, and initialize it
- */
-OctreeNode *octreeNodeCreate()
-{
-    OctreeNode *node = (OctreeNode *)malloc(sizeof(OctreeNode));
-    if (!node)
-        return NULL;
-    node->r             = 0;
-    node->g             = 0;
-    node->b             = 0;
-    node->index         = 0;
-    node->nrPixels      = 0;
-    node->nrChildren    = 0;
-    node->parent        = NULL;
-    for (int i=0 ; i<8 ; i++)
-        node->children[i] = NULL;
-    return node;
-}
-
-/**
- *  delete an octree node and its children
- */
-void octreeNodeDelete(OctreeNode *node)
-{
-    if (!node)
-        return;
-    for (int i=0 ; i<8 ; i++)
-        octreeNodeDelete(node->children[i]);
-    free(node);
-}
-
-
-/**
- *  delete the children of an octree node
- */
-void octreeNodeDeleteChildren(OctreeNode *node)
-{
-    if (!node)
-        return;
-    node->nrChildren = 0;
-    for (int i=0 ; i<8 ; i++)
-        {
-        octreeNodeDelete(node->children[i]);
-        node->children[i]=NULL;
-        }
-}
-
-
-
-
-/**
- *  insert an RGB value into an octree node according to its
- *  high-order rgb vector bits
- */
-int octreeNodeInsert(OctreeNode *root, RGB rgb, int bitsPerSample)
-{
-    OctreeNode *node = root;
-    int newColor     = FALSE;
-    int r            = rgb.r;
-    int g            = rgb.g;
-    int b            = rgb.b;
-
-    int shift = 7;
-    for (int bit=0 ; bit<bitsPerSample ; bit++)
-        {
-        /* update values of all nodes from the root to the leaf */
-        node->r += r;
-        node->g += g;
-        node->b += b;
-        node->nrPixels++;
-        int index = (((r >> shift) & 1) << 2) |
-                   (((g >> shift) & 1) << 1) |
-                    (((b >> shift) & 1)     ) ;
-
-        OctreeNode *child = node->children[index];
-        if (!child)
-            {
-            child                 = octreeNodeCreate();
-            node->children[index] = child;
-            child->parent         = node;
-            node->nrChildren++;
-           newColor              = TRUE;
-            }
-        node = child; /*next level*/
-        shift--;
-        }
-    return newColor;
-}
-
-
-
-
-
-/**
- *  find an exact match for an RGB value, at the given bits
- *  per sample.  if not found, return -1
- */
-int octreeNodeFind(OctreeNode *root, RGB rgb, int bitsPerSample)
-{
-    OctreeNode *node = root;
-    int r            = rgb.r;
-    int g            = rgb.g;
-    int b            = rgb.b;
-
-    int shift = 7;
-    for (int bit=0 ; bit<bitsPerSample ; bit++)
-        {
-        int index = (((r >> shift) & 1) << 2) |
-                   (((g >> shift) & 1) << 1) |
-                    (((b >> shift) & 1)     ) ;
-
-        OctreeNode *child = node->children[index];
-        if (!child)
-            return -1;
-        node = child; /*next level*/
-        shift--;
-        }
-    printf("error.  this should not happen\n");
-    return -1;
-}
-
-
-
-static void spaces(int nr)
-{
-    for (int i=0; i<nr ; i++)
-        printf(" ");
-}
-
-/**
- *  pretty-print an octree node and its children
- */
-void octreeNodePrint(OctreeNode *node, int indent)
-{
-    spaces(indent); printf("####Node###\n");
-    spaces(indent); printf("r :%lu\n", node->r);
-    spaces(indent); printf("g :%lu\n", node->g);
-    spaces(indent); printf("b :%lu\n", node->b);
-    spaces(indent); printf("i :%d\n", node->index);
-    for (unsigned int i=0; i<8; i++)
-        {
-        OctreeNode *child = node->children[i];
-        if (!child)
-            continue;
-        spaces(indent); printf("   child %d :", i);
-        octreeNodePrint(child, indent+4);
-        }
-}
-
-/**
- *  Count how many nodes in this (sub)tree
- */
-static int octreeNodeCount(OctreeNode *node)
-{
-    int count = 1;
-    for (unsigned int i=0; i<8; i++)
-        {
-        OctreeNode *child = node->children[i];
-        if (!child)
-            continue;
-        count += octreeNodeCount(child);
-        }
-    return count;
-}
-
-
-
-
-/**
- * Count all of the leaf nodes in the octree
- */
-static void octreeLeafArray(OctreeNode *node, OctreeNode **array, int arraySize, int *len)
-{
-    if (!node)
-        return;
-    if (node->nrChildren == 0 && *len < arraySize)
-        {
-        array[*len] = node;
-        *len = *len + 1;
-        }
-    for (int i=0 ; i<8 ; i++)
-        octreeLeafArray(node->children[i], array, arraySize, len);
-}
-
-
-
-/**
- *  Count all of the leaf nodes in the octree
- */
-static int octreeLeafCount(OctreeNode *node)
-{
-    if (!node)
-        return 0;
-    if (node->nrChildren == 0)
-        return 1;
-    int leaves = 0;
-    for (int i=0 ; i<8 ; i++)
-        leaves += octreeLeafCount(node->children[i]);
-    return leaves;
-}
-
-/**
- * Mark all of the leaf nodes in the octree with an index nr
- */
-static void octreeLeafIndex(OctreeNode *node, int *index)
-{
-    if (!node)
-        return;
-    if (node->nrChildren == 0)
-        {
-        node->index = *index;
-        *index = *index + 1;
-        return;
-        }
-    for (int i=0 ; i<8 ; i++)
-        octreeLeafIndex(node->children[i], index);
-}
-
-
-
-/**
- * Find a node that has children, and that also
- * has the lowest pixel count
- */
-static void octreefindLowestLeaf(OctreeNode *node, OctreeNode **lowestLeaf)
-{
-    if (!node)
-        return;
-    if (node->nrChildren == 0)
-        {
-        if (node->nrPixels < (*lowestLeaf)->nrPixels)
-            *lowestLeaf = node;
-        return;
-        }
-   
-    for (int i=0 ; i<8 ; i++)
-        octreefindLowestLeaf(node->children[i], lowestLeaf);
-}
-
-
-/**
- * reduce the leaves on an octree to a given number
- */
-int octreePrune(OctreeNode *root, int nrColors)
-{
-    int leafCount = octreeLeafCount(root);
-
-    while (leafCount > nrColors)
-        {
-        OctreeNode *lowestLeaf = root;    
-        octreefindLowestLeaf(root, &lowestLeaf);
-
-        if (!lowestLeaf)
-            break; //should never happen
-
-       if (lowestLeaf==root)
-            {
-            printf("found no leaves\n");
-            continue;
-            }
-
-        OctreeNode *parent = lowestLeaf->parent;
-        if (!parent)
-            continue;
-
-        for (int i=0 ; i<8 ; i++)
-            {
-            OctreeNode *child = parent->children[i];
-            if (child == lowestLeaf)
-                {
-                parent->nrChildren--;
-                octreeNodeDelete(child);
-                parent->children[i] = NULL;
-                break;
-                }
-            }
-        /*printf("leafCount:%d lowPixels:%lu\n",
-               leafCount, lowestLeaf->nrPixels);*/
-        leafCount = octreeLeafCount(root);
-        }
-    int index = 0;
-    octreeLeafIndex(root, &index);
-    
-    //printf("leafCount:%d\n", leafCount);
-    //octreeNodePrint(root, 0);
-
-    return leafCount;
-}
-
-
-
-/**
- *
- */
-OctreeNode *octreeBuild(RgbMap *rgbMap, int bitsPerSample, int nrColors)
-{
-    OctreeNode *root = octreeNodeCreate();
-    if (!root)
-        return NULL;
-    for (int y=0 ; y<rgbMap->height ; y++)
-        {
-        for (int x=0 ; x<rgbMap->width ; x++)
-            {
-            RGB rgb = rgbMap->getPixel(rgbMap, x, y);
-            octreeNodeInsert(root, rgb, bitsPerSample);
-            }
-        }
-
-    if (octreePrune(root, nrColors)<0)
-        {
-        octreeNodeDelete(root);
-        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)
-{
-    RGB *ra = (RGB *)a;
-    RGB *rb = (RGB *)b;
-    int ba = ra->r + ra->g + ra->b;
-    int bb = rb->r + rb->g + rb->b;
-    int comp = ba - bb;
-    return comp;
-}
-
-/**
- *
- */
-RGB *makeRGBPalette(OctreeNode *root, int nrColors)
-{
-
-    OctreeNode **palette = (OctreeNode **)malloc(nrColors * sizeof(OctreeNode *));
-    if (!palette)
-        {
-        return NULL;
-        }
-    int len = 0;
-    octreeLeafArray(root, palette, nrColors, &len);
-
-    RGB *rgbpal = (RGB *)malloc(len * sizeof(RGB));
-    if (!rgbpal)
-        {
-        free(palette);
-        return NULL;
-        }
-
-    for (int i=0; i<len ; i++)
-        {
-        OctreeNode *node = palette[i];
-        RGB rgb;
-        if (node->nrPixels == 0)
-            {
-            continue;
-            }
-        rgb.r = (unsigned char)( (node->r / node->nrPixels) & 0xff);
-        rgb.g = (unsigned char)( (node->g / node->nrPixels) & 0xff);
-        rgb.b = (unsigned char)( (node->b / node->nrPixels) & 0xff);
-        int index = node->index;
-        //printf("Pal: %d %d %d %d\n", rgb.r, rgb.g, rgb.b, index);
-        rgbpal[index]=rgb;
-        }
-
-    free(palette);
-    
-    /* sort by brightness, to avoid high contrasts */
-    qsort((void *)rgbpal, len, sizeof(RGB), compRGB);
-
-    return rgbpal;
-}
-
-
-/**
- *  Return the closest color in the palette to the request
- */
-RGB lookupQuantizedRGB(RGB *rgbpalette, int paletteSize, RGB candidate, int *closestIndex)
-{
-    /* slow method */
-    unsigned long closestMatch = 10000000;
-    RGB closestRGB = { 0 , 0, 0 };
-    *closestIndex = 0;
-    for (int i=0 ; i<paletteSize ; i++)
-        {
-        RGB entry = rgbpalette[i];
-        unsigned long dr    = candidate.r - entry.r;
-        unsigned long dg    = candidate.g - entry.g;
-        unsigned long db    = candidate.b - entry.b;
-        unsigned long match = dr * dr + dg * dg + db * db;
-        if (match < closestMatch)
-            {
-            *closestIndex = i;
-            closestMatch  = match;
-            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
- */
-IndexedMap *rgbMapQuantize(RgbMap *rgbMap, int bitsPerSample, int nrColors)
-{
-    if (!rgbMap)
-        return NULL;
-
-    OctreeNode *otree = octreeBuild(rgbMap, bitsPerSample, nrColors);
-    if (!otree)
-        {
-        return NULL;
-        }
-        
-    /*Make sure we don't request more colors than actually exist*/
-    int nodeCount = octreeLeafCount(otree);
-    if (nodeCount < nrColors)
-        nrColors = nodeCount;
-
-    RGB *rgbpal = makeRGBPalette(otree, nrColors);
-    if (!rgbpal)
-        {
-        octreeNodeDelete(otree);
-        return NULL;
-        }
-
-    /*We have our original and palette. Make the new one*/
-    IndexedMap *newMap = IndexedMapCreate(rgbMap->width, rgbMap->height);
-    if (!newMap)
-        {
-        free(rgbpal);
-        octreeNodeDelete(otree);
-        return NULL;
-        }
-     
-    /* fill in the color lookup table */
-    for (int i=0 ; i< nrColors ; i++)
-        {
-        newMap->clut[i] = rgbpal[i];
-        }
-    newMap->nrColors = nrColors;
-
-    for (int y=0 ; y<rgbMap->height ; y++)
-        {
-        for (int x=0 ; x<rgbMap->width ; x++)
-            {
-            RGB rgb = rgbMap->getPixel(rgbMap, x, y);
-            //int indexNr = octreeNodeFind(otree, rgb, bitsPerSample);
-            //printf("i:%d\n", indexNr);
-            //RGB quantRgb = rgbpal[indexNr];
-            int closestIndex;
-            RGB quantRgb = lookupQuantizedRGB(rgbpal, nrColors, rgb, &closestIndex);
-            newMap->setPixel(newMap, x, y, (unsigned int)closestIndex); 
-            }
-        }
-
-    free(rgbpal);
-    octreeNodeDelete(otree);
-
-    return newMap;
-}
-
-
 
 /**
  *  Experimental.  Work on this later
@@ -906,18 +410,16 @@ IndexedMap *rgbMapQuantize(RgbMap *rgbMap, int bitsPerSample, int nrColors)
 GrayMap *quantizeBand(RgbMap *rgbMap, int nrColors)
 {
 
-    int bitsPerSample = 4;
-
     RgbMap *gaussMap = rgbMapGaussian(rgbMap);
     //gaussMap->writePPM(gaussMap, "rgbgauss.ppm");
 
-    IndexedMap *qMap = rgbMapQuantize(gaussMap, bitsPerSample, nrColors);
+    IndexedMap *qMap = rgbMapQuantize(gaussMap, nrColors);
     //qMap->writePPM(qMap, "rgbquant.ppm");
     gaussMap->destroy(gaussMap);
 
     GrayMap *gm = GrayMapCreate(rgbMap->width, rgbMap->height);
 
-    /* RGB is quantized.  There should now be a small set of (R+G+B) */
+    // RGB is quantized.  There should now be a small set of (R+G+B)
     for (int y=0 ; y<qMap->height ; y++)
         {
         for (int x=0 ; x<qMap->width ; x++)
@@ -928,7 +430,7 @@ GrayMap *quantizeBand(RgbMap *rgbMap, int nrColors)
                 sum = 765;
             else
                 sum = 0;
-            /*printf("%d %d %d : %d\n", rgb.r, rgb.g, rgb.b, index);*/
+           // printf("%d %d %d : %d\n", rgb.r, rgb.g, rgb.b, index);
             gm->setPixel(gm, x, y, sum);
             }
         }
@@ -939,12 +441,6 @@ GrayMap *quantizeBand(RgbMap *rgbMap, int nrColors)
 }
 
 
-
-
-
-
-
-
 /*#########################################################################
 ### E N D    O F    F I L E
 #########################################################################*/