Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

https://doi.org/10.5201/ipol.2011.g_iics
29 June 2020, 11:03:09 UTC
  • Code
  • Branches (1)
  • Releases (0)
  • Visits
    • Branches
    • Releases
    • HEAD
    No releases to show
  • 99c00a5
  • /
  • cwinterp-src
  • /
  • fitsten.c
Raw File Download

To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
Select below a type of object currently browsed in order to display its associated SWHID and permalink.

  • content
  • directory
  • revision
  • snapshot
origin badgecontent badge
swh:1:cnt:279caa371d5b481f52b205d30a7d18d926c86e49
origin badgedirectory badge
swh:1:dir:1909732c1eb1aa159b7f5bb6f727360f1a51f8b0
origin badgerevision badge
swh:1:rev:2f369309d6656c6bbbe0c0533385c5838cd165bc
origin badgesnapshot badge
swh:1:snp:fdd60cabbff7cf177d6ab66a10db868a837b2d80

This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
Select below a type of object currently browsed in order to generate citations for them.

  • content
  • directory
  • revision
  • snapshot
(requires biblatex-software package)
Generating citation ...
(requires biblatex-software package)
Generating citation ...
(requires biblatex-software package)
Generating citation ...
(requires biblatex-software package)
Generating citation ...
Tip revision: 2f369309d6656c6bbbe0c0533385c5838cd165bc authored by Software Heritage on 01 January 2010, 00:00:00 UTC
ipol: Deposit 692 in collection ipol
Tip revision: 2f36930
fitsten.c
/** 
 * @file fitsten.c
 * @brief Select the best-fitting contour stencils 
 * @author Pascal Getreuer <getreuer@gmail.com>
 * 
 * 
 * Copyright (c) 2010-2011, Pascal Getreuer
 * All rights reserved.
 * 
 * This program is free software: you can use, modify and/or 
 * redistribute it under the terms of the simplified BSD License. You 
 * should have received a copy of this license along this program. If 
 * not, see <http://www.opensource.org/licenses/bsd-license.html>.
 */

#include <stdlib.h>
#include "fitsten.h"


#define PIXEL_STRIDE	3

/* Constants related to stencil edge weights */
/* mu = 3/4 * sqrt(2) */
#define W_MU        (1.060660171779821)
/* Divisor for axial stencils = 6 */
#define W_PI_2      (6.0)
/* Divisor for diagonal stencils = 4 sqrt(2) */
#define W_PI_4      (5.656854249492381)
/* Divisor for pi/8 stencils = 6(1 + sqrt(2))sqrt(2 - sqrt(2)) + 12 */
#define W_PI_8      (23.086554390135440)



/** @brief Compute the distance between to color pixels in YCbCr space */
static int Dist(int32_t *A, int32_t *B)
{
    int iDistR = A[0] - B[0];
    int iDistG = A[1] - B[1];
    int iDistB = A[2] - B[2];
    register int iDistY = 2*iDistR + 4*iDistG + iDistB;
    register int iDistU = -iDistR - 2*iDistG + 3*iDistB;
    register int iDistV = 4*iDistR - 3*iDistG - iDistB;
    return (abs(iDistY) + abs(iDistU) + abs(iDistV)) >> 4;
}


/** 
* @brief Select the best-fitting contour stencils 
*
* @param Stencil pointer to array of size Width by Height to be filled with 
*        the best-fitting stencil for each pixels
* @param Image the input RGB image 
* @param Width, Height image dimensions
* @param StencilMul multiply the stencil index by this factor 
*
* \c FitStencils finds the best-fitting stencil at each pixel of the input 
* image
* \f[ \mathcal{S}^\star(k) = \arg\min_{\mathcal{S}\in\Sigma} 
*     \tfrac{1}{|\mathcal{S}|} (\mathcal{S} \star [v])(k) \f]
* to estimate the local contour orientation.  The result \c Stencil is a 
* two-dimensional array with the index (0, 1, ..., or 7) of the best-fitting
* stencil for each pixel.  The stencil TV estimates
* \f$(\mathcal{S} \star [v])(k)\f$ are filtered by [1,2,1; 2,4,2; 1,2,1]/16
* to improve reliability.
* 
* For efficiency in \c CWFirstPass and \c CWCorrectionPass, the stencil 
* indices are multiplied by \c StencilMul (so that the index may be used 
* directly as an offset into the samples table).
*/
int FitStencils(int *Stencil, int32_t *Image, int Width, int Height, int StencilMul)
{
    const int Stride = PIXEL_STRIDE*Width;
    const int TVStride = 8*Width;
    int *StencilTv; /* Contour stencil total variations estimates TV[S]            */
    int Dh[3][2];   /* Horizontal differences computed over the current 3x3 window */
    int Dv[2][3];   /* Vertical differences                                        */
    int Da[2][2];   /* Diagonal differences |Image(m,n) - Image(m+1,n+1)|          */
    int Db[2][2];   /* Diagonal differences |Image(m+1,n) - Image(m,n+1)|          */
    int *TvPtr, TvMin, Temp;
    int x, y, k, S;

    
    if(!(StencilTv = (int *)malloc(sizeof(int)*8*Width*Height)))
        return 0;
    
    TvPtr = StencilTv;
    
    for(y = 0; y < Height; y++)
    {
        Dh[0][1] = 0;
        Dh[1][1] = 0;
        Dh[2][1] = 0;
        
        Dv[0][1] = 0;
        Dv[1][1] = 0;
        Dv[0][2] = (y > 0) ? Dist(Image - Stride, Image) : 0;
        Dv[1][2] = (y < Height-1) ? Dist(Image + Stride, Image) : 0;
        
        Da[0][1] = 0;
        Da[1][1] = 0;
        Db[0][1] = 0;
        Db[1][1] = 0;
    
        for(x = 0; x < Width; x++, Image += PIXEL_STRIDE, TvPtr += 8)
        {
            Dh[0][0] = Dh[0][1];
            Dh[1][0] = Dh[1][1];
            Dh[2][0] = Dh[2][1];
            
            Dv[0][0] = Dv[0][1];
            Dv[1][0] = Dv[1][1];
            Dv[0][1] = Dv[0][2];
            Dv[1][1] = Dv[1][2];
            
            Da[0][0] = Da[0][1];
            Da[1][0] = Da[1][1];
            
            Db[0][0] = Db[0][1];
            Db[1][0] = Db[1][1];
            
            if(x < Width-1)
            {
                Dh[1][1] = Dist(Image, Image+PIXEL_STRIDE);
            
                if(y > 0)
                {
                    Dh[0][1] = Dist(Image-Stride, Image-Stride+PIXEL_STRIDE);
                    Dv[0][2] = Dist(Image-Stride+PIXEL_STRIDE, Image+PIXEL_STRIDE);
                    Da[0][1] = Dist(Image-Stride, Image+PIXEL_STRIDE);
                    Db[0][1] = Dist(Image-Stride+PIXEL_STRIDE, Image);
                }
                
                if(y < Height-1)
                {
                    Dh[2][1] = Dist(Image+Stride, Image+Stride+PIXEL_STRIDE);
                    Dv[1][2] = Dist(Image+PIXEL_STRIDE, Image+Stride+PIXEL_STRIDE);
                    Da[1][1] = Dist(Image, Image+Stride+PIXEL_STRIDE);
                    Db[1][1] = Dist(Image+PIXEL_STRIDE, Image+Stride);
                }
            }
            else
            {
                Dh[0][1] = 0;
                Dh[1][1] = 0;
                Dh[2][1] = 0;
                
                Dv[0][2] = 0;
                Dv[1][2] = 0;
                
                Da[0][1] = 0;
                Da[1][1] = 0;
                
                Db[0][1] = 0;
                Db[1][1] = 0;
            }

            TvPtr[1] = (Db[1][0] + Db[0][1]) + Db[0][0] + Db[1][1];
            TvPtr[3] = (Dh[1][0] + Dh[1][1]) + Dh[0][0] + Dh[0][1] + Dh[2][0] + Dh[2][1];
            TvPtr[5] = (Da[0][0] + Da[1][1]) + Da[1][0] + Da[0][1];
            TvPtr[7] = (Dv[0][1] + Dv[1][1]) + Dv[0][0] + Dv[1][0] + Dv[0][2] + Dv[1][2];
        
            TvPtr[0] = (int)((TvPtr[7] + TvPtr[1]*W_MU) / W_PI_8 + 0.5);
            TvPtr[2] = (int)((TvPtr[1]*W_MU + TvPtr[3]) / W_PI_8 + 0.5);
            TvPtr[4] = (int)((TvPtr[3] + TvPtr[5]*W_MU) / W_PI_8 + 0.5);
            TvPtr[6] = (int)((TvPtr[5]*W_MU + TvPtr[7]) / W_PI_8 + 0.5);
            
            TvPtr[1] = (int)(TvPtr[1] / W_PI_4 + 0.5);
            TvPtr[3] = (int)(TvPtr[3] / W_PI_2 + 0.5);
            TvPtr[5] = (int)(TvPtr[5] / W_PI_4 + 0.5);
            TvPtr[7] = (int)(TvPtr[7] / W_PI_2 + 0.5);
        }
    }
    
    TvPtr = StencilTv;
    
    for(y = 0; y < Height; y++)
    {
        for(x = 0; x < Width; x++, TvPtr += 8, Stencil++)
        {
            if(1 <= x && x < Width - 1 && 1 <= y && y < Height - 1)
            {
                /* Filter the TV estimates by [1,2,1; 2,4,2; 1,2,1] */
                TvMin = TvPtr[-TVStride - 8] + TvPtr[-TVStride + 8]
                        + TvPtr[TVStride - 8] + TvPtr[TVStride + 8]
                        + ((TvPtr[-TVStride] + TvPtr[-8]
                        + TvPtr[8] + TvPtr[TVStride]) << 1)
                        + (TvPtr[0] << 2);
                S = 0;
            
                for(k = 1; k < 8; k++)
                {
                    Temp = TvPtr[k - TVStride - 8] + TvPtr[k - TVStride + 8]
                        + TvPtr[k + TVStride - 8] + TvPtr[k + TVStride + 8]
                        + ((TvPtr[k - TVStride] + TvPtr[k - 8]
                        + TvPtr[k + 8] + TvPtr[k + TVStride]) << 1)
                        + (TvPtr[k] << 2);
                    
                    if(Temp < TvMin)
                    {
                        TvMin = Temp;
                        S = k;
                    }
                        
                }
            }
            else
            {
                TvMin = TvPtr[0];
                S = 0;
                
                for(k = 1; k < 8; k++)
                    if(TvPtr[k] < TvMin)
                        TvMin = TvPtr[S = k];
            }
            
            *Stencil = StencilMul * S;
        }
    }
    
    free(StencilTv);
    return 1;
}

back to top

Software Heritage — Copyright (C) 2015–2026, The Software Heritage developers. License: GNU AGPLv3+.
The source code of Software Heritage itself is available on our development forge.
The source code files archived by Software Heritage are available under their own copyright and licenses.
Terms of use: Archive access, API— Content policy— Contact— JavaScript license information— Web API