<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wikidot="http://www.wikidot.com/rss-namespace">

	<channel>
		<title>Better Contour Textures - new forum threads</title>
		<link>http://contourtextures.wikidot.com/forum/start</link>
		<description>Threads in forums of the site &quot;Better Contour Textures&quot; - by an anti-aliased distance transform</description>
				<copyright></copyright>
		<lastBuildDate>Sun, 14 Jun 2026 23:05:36 +0000</lastBuildDate>
		
					<item>
				<guid>http://contourtextures.wikidot.com/forum/t-1074833</guid>
				<title>makedist.c, width / height</title>
				<link>http://contourtextures.wikidot.com/forum/t-1074833/makedist-c-width-height</link>
				<description></description>
				<pubDate>Mon, 05 Jan 2015 00:38:50 +0000</pubDate>
				<wikidot:authorName>jimhad</wikidot:authorName>				<wikidot:authorUserId>2039109</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>I believe that the parameters for width and height are switched around in makedist.c in the repository for OpenGL Insights? The calls to computegradient and edtaa3 should have the parameters switched. Since you recently updated the repository maybe you would like to fix it since it took me a couple of hours of head scratching :) Great work btw!</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://contourtextures.wikidot.com/forum/t-984944</guid>
				<title>Exact EDT?</title>
				<link>http://contourtextures.wikidot.com/forum/t-984944/exact-edt</link>
				<description>JFA is inexact; there exist linear-time EDT algorithms, highly paralleliseable</description>
				<pubDate>Thu, 14 Aug 2014 09:32:56 +0000</pubDate>
				<wikidot:authorName>cbrunschen</wikidot:authorName>				<wikidot:authorUserId>1951915</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>(Sorry for the lack of links; as a low-karma user I am not permitted to post those, it seems. I've tried to give clear references instead; apologies for anything I've gotten wrong.)</p> <p>The <em>Jump Flooding Algorithm</em> (JFA) as used here for calculating the distance transform is fairly quick and produces good, but not exact, results. But there also exist algorithms that produce the <em>exact</em> Euclidean Distance Transform (EDT) in linear time, such as described in <em>A General Algorithm for Computing Distance Transforms in Linear Time</em> (A. Meijster, J.B.T.M. Roerdink, W.H. Hesselink, A general algorithm for computing distance transforms in linear time, Computational Imaging and Vision 18 (8) (2000) 331–340) and <em>A Linear Time Algorithm for Computing Exact Euclidean Distance Transforms of Binary Images in Arbitrary Dimensions</em> (C.R. Maurer, R. Qi, and V. Raghavan, IEEE Transactions on Pattern Analysis and Machine Intelligence, 25(2):265–270, February 2003). This is straightforward to parallelise on CPUs, and has been implemented on GPUs (in Cuda) as well as the <em>Parallel Banding Algorithm</em> (Thanh-Tung Cao, Ke Tang, Anis Mohamed, and Tiow-Seng Tan, Proceedings of the 2010 ACM SIGGRAPH symposium on Interactive 3D Graphics and Games (I3D '10)).</p> <p>Would some of this be applicable here and possible to adapt to generate the anti-aliased distance transform? An exact algorithm would avoid the (small) errors still present in what Jump-Flooding calculates, and a linear-time algorithm might be able to calculate them a little bit more quickly as well; and a GPU implementation would seem to fit in well to be able to generate them from rendered content in real time within a game.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://contourtextures.wikidot.com/forum/t-920471</guid>
				<title>Improved edtaa, aka edtaa3func</title>
				<link>http://contourtextures.wikidot.com/forum/t-920471/improved-edtaa-aka-edtaa3func</link>
				<description>Genrerating AA DT maps in real time for the effects described in Green&#039;s paper.</description>
				<pubDate>Tue, 08 Jul 2014 09:54:52 +0000</pubDate>
				<wikidot:authorName>zebratov</wikidot:authorName>				<wikidot:authorUserId>1925824</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>Dear Prof.Gustavson,<br /> First, I tried the jump flood, which results with no AA.<br /> Second, I have read the AA EDT in the Pattern Recognition Letters.<br /> I run some tests on the produced DT and they produce nice AA effects, with limitless resolution.<br /> My Questions :<br /> 1) Is it is possible to implement it with Jump Flooding?<br /> 2) Can you please further explain the U,V you are referring to in that paper - i.e equations (6) and its illustration Fig.4 .<br /> i.e &quot; Therefore, the local gradients were used to improve the result only at the edge and very near it, where most<br /> of the larger absolute errors were located.&quot;<br /> and in fig.4, &quot;the hit point&quot; (black circle)<br /> 3) &quot;In our experiments, using the local gradient always improved<br /> the accuracy for edge pixels, where no other edge direction information was available&quot;<br /> Can you further explain this sentence - i.e: other edge direction information .</p> <p>Thank you,<br /> Zebratov</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://contourtextures.wikidot.com/forum/t-605008</guid>
				<title>License</title>
				<link>http://contourtextures.wikidot.com/forum/t-605008/license</link>
				<description>Change away from GNUGPL?</description>
				<pubDate>Wed, 19 Dec 2012 11:04:07 +0000</pubDate>
				<wikidot:authorName>hronet</wikidot:authorName>				<wikidot:authorUserId>1513681</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>Hi</p> <p>I was wondering about the use of GNUGPL - it essentially makes it impossible to use the software in any commercial product. Would it be meaningful to change it to either public domain, the MIT License, or the zlib-license?<br /> (in descending order of usefulness)</p> <p>Thanks!</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://contourtextures.wikidot.com/forum/t-442136</guid>
				<title>Unity C# version</title>
				<link>http://contourtextures.wikidot.com/forum/t-442136/unity-c-version</link>
				<description>I made a version for Unity in C#.</description>
				<pubDate>Fri, 10 Feb 2012 17:15:54 +0000</pubDate>
				<wikidot:authorName>Jasper Flick</wikidot:authorName>				<wikidot:authorUserId>1304472</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>Hi!</p> <p>I'm working on a text tool for the Unity3D game engine and I included a C# version of the EDTAA algorithm to create nice distance maps from font atlases. The Generate method takes the alpha channel of a source texture and generates the distances from that, either outside, inside, or both. Beyond that, it's conceptually the same code as edtaa3 and the post process part, although I approached a few things differently.</p> <p>Though it's Unity3D specific, it shouldn't be too hard to integrate the C# code into a non-Unity project.</p> <div class="code"> <pre><code>using UnityEngine; /// &lt;summary&gt; /// Utility class for generating distance maps from anti-aliased alpha maps. /// &lt;/summary&gt; public static class CCDistanceMapGenerator { /// &lt;summary&gt; /// How to fill the RGB channels of the generated distance map /// &lt;/summary&gt; public enum RGBMode { /// &lt;summary&gt; /// Set the RGB channels to 1. /// &lt;/summary&gt; White, /// &lt;summary&gt; /// Set the RGB channels to 0. /// &lt;/summary&gt; Black, /// &lt;summary&gt; /// Set the RGB channels to the computed distance. /// &lt;/summary&gt; Distance, /// &lt;summary&gt; /// Copy the source texture's RGB channels. /// &lt;/summary&gt; Source } private class Pixel { public float alpha, distance; public Vector2 gradient; public int dX, dY; } private static int width, height; private static Pixel[,] pixels; /// &lt;summary&gt; /// Generates a distance texture from the alpha channel of a source texture. /// &lt;/summary&gt; /// &lt;param name=&quot;source&quot;&gt; /// The source texture. Alpha values of 1 are considered inside, values of 0 are considered outside, and any other values are considered /// to be on the edge. Make sure the texture is readable and not compressed. /// &lt;/param&gt; /// &lt;param name=&quot;destination&quot;&gt; /// The destination texture. Must be the same size as the source texture. /// &lt;/param&gt; /// &lt;param name=&quot;maxInside&quot;&gt; /// The maximum pixel distance measured inside the boundary, resulting in an alpha value of 1. /// If set to zero, everything inside will have an alpha value of 1. /// &lt;/param&gt; /// &lt;param name=&quot;maxOutside&quot;&gt; /// The maximum pixel distance measured outside the boundary, resulting in an alpha value of 0. /// If set to zero, everything outside will have an alpha value of 0. /// &lt;/param&gt; /// &lt;param name=&quot;postProcessDistance&quot;&gt; /// Pixel distance from the boundary which will be post-processed using the boundary gradient. /// &lt;/param&gt; /// &lt;param name=&quot;rgbMode&quot;&gt; /// How to fill the destination texture's RGB channels. /// &lt;/param&gt; public static void Generate (Texture2D source, Texture2D destination, float maxInside, float maxOutside, float postProcessDistance, RGBMode rgbMode) { if(source.height != destination.height || source.width != destination.width){ Debug.LogError(&quot;Source and destination textures must be the same size.&quot;); return; } try{ source.GetPixel(0, 0); } catch{ Debug.LogError(&quot;Source texture is not read/write enabled.&quot;); return; } width = source.width; height = source.height; pixels = new Pixel[width, height]; int x, y; float scale; Color c = rgbMode == RGBMode.White ? Color.white : Color.black; for(y = 0; y &lt; height; y++){ for(x = 0; x &lt; width; x++){ pixels[x, y] = new Pixel(); } } if(maxInside &gt; 0f){ for(y = 0; y &lt; height; y++){ for(x = 0; x &lt; width; x++){ pixels[x, y].alpha = 1f - source.GetPixel(x, y).a; } } ComputeEdgeGradients(); GenerateDistanceTransform(); if(postProcessDistance &gt; 0f){ PostProcess(postProcessDistance); } scale = 1f / maxInside; for(y = 0; y &lt; height; y++){ for(x = 0; x &lt; width; x++){ c.a = Mathf.Clamp01(pixels[x, y].distance * scale); destination.SetPixel(x, y, c); } } } if(maxOutside &gt; 0f){ for(y = 0; y &lt; height; y++){ for(x = 0; x &lt; width; x++){ pixels[x, y].alpha = source.GetPixel(x, y).a; } } ComputeEdgeGradients(); GenerateDistanceTransform(); if(postProcessDistance &gt; 0f){ PostProcess(postProcessDistance); } scale = 1f / maxOutside; if(maxInside &gt; 0f){ for(y = 0; y &lt; height; y++){ for(x = 0; x &lt; width; x++){ c.a = 0.5f + (destination.GetPixel(x, y).a - Mathf.Clamp01(pixels[x, y].distance * scale)) * 0.5f; destination.SetPixel(x, y, c); } } } else{ for(y = 0; y &lt; height; y++){ for(x = 0; x &lt; width; x++){ c.a = Mathf.Clamp01(1f - pixels[x, y].distance * scale); destination.SetPixel(x, y, c); } } } } if(rgbMode == RGBMode.Distance){ for(y = 0; y &lt; height; y++){ for(x = 0; x &lt; width; x++){ c = destination.GetPixel(x, y); c.r = c.a; c.g = c.a; c.b = c.a; destination.SetPixel(x, y, c); } } } else if(rgbMode == RGBMode.Source){ for(y = 0; y &lt; height; y++){ for(x = 0; x &lt; width; x++){ c = source.GetPixel(x, y); c.a = destination.GetPixel(x, y).a; destination.SetPixel(x, y, c); } } } pixels = null; } private static void ComputeEdgeGradients () { float sqrt2 = Mathf.Sqrt(2f); for(int y = 1; y &lt; height - 1; y++){ for(int x = 1; x &lt; width - 1; x++){ Pixel p = pixels[x, y]; if(p.alpha &gt; 0f &amp;&amp; p.alpha &lt; 1f){ // estimate gradient of edge pixel using surrounding pixels float g = - pixels[x - 1, y - 1].alpha - pixels[x - 1, y + 1].alpha + pixels[x + 1, y - 1].alpha + pixels[x + 1, y + 1].alpha; p.gradient.x = g + (pixels[x + 1, y].alpha - pixels[x - 1, y].alpha) * sqrt2; p.gradient.y = g + (pixels[x, y + 1].alpha - pixels[x, y - 1].alpha) * sqrt2; p.gradient.Normalize(); } } } } private static float ApproximateEdgeDelta (float gx, float gy, float a) { // (gx, gy) can be either the local pixel gradient or the direction to the pixel if(gx == 0f || gy == 0f){ // linear function is correct if both gx and gy are zero // and still fair if only one of them is zero return 0.5f - a; } // normalize (gx, gy) float length = Mathf.Sqrt(gx * gx + gy * gy); gx = gx / length; gy = gy / length; // reduce symmetrical equation to first octant only // gx &gt;= 0, gy &gt;= 0, gx &gt;= gy gx = Mathf.Abs(gx); gy = Mathf.Abs(gy); if(gx &lt; gy){ float temp = gx; gx = gy; gy = temp; } // compute delta float a1 = 0.5f * gy / gx; if(a &lt; a1){ // 0 &lt;= a &lt; a1 return 0.5f * (gx + gy) - Mathf.Sqrt(2f * gx * gy * a); } if(a &lt; (1f - a1)){ // a1 &lt;= a &lt;= 1 - a1 return (0.5f - a) * gx; } // 1-a1 &lt; a &lt;= 1 return -0.5f * (gx + gy) + Mathf.Sqrt(2f * gx * gy * (1f - a)); } private static void UpdateDistance (Pixel p, int x, int y, int oX, int oY) { Pixel neighbor = pixels[x + oX, y + oY]; Pixel closest = pixels[x + oX - neighbor.dX, y + oY - neighbor.dY]; if(closest.alpha == 0f || closest == p){ // neighbor has no closest yet // or neighbor's closest is p itself return; } int dX = neighbor.dX - oX; int dY = neighbor.dY - oY; float distance = Mathf.Sqrt(dX * dX + dY * dY) + ApproximateEdgeDelta(dX, dY, closest.alpha); if(distance &lt; p.distance){ p.distance = distance; p.dX = dX; p.dY = dY; } } private static void GenerateDistanceTransform () { // perform anti-aliased Euclidean distance transform int x, y; Pixel p; // initialize distances for(y = 0; y &lt; height; y++){ for(x = 0; x &lt; width; x++){ p = pixels[x, y]; p.dX = 0; p.dY = 0; if(p.alpha &lt;= 0f){ // outside p.distance = 1000000f; } else if (p.alpha &lt; 1f){ // on the edge p.distance = ApproximateEdgeDelta(p.gradient.x, p.gradient.y, p.alpha); } else{ // inside p.distance = 0f; } } } // perform 8SSED (eight-points signed sequential Euclidean distance transform) // scan up for(y = 1; y &lt; height; y++){ // |P. // |XX p = pixels[0, y]; if(p.distance &gt; 0f){ UpdateDistance(p, 0, y, 0, -1); UpdateDistance(p, 0, y, 1, -1); } // --&gt; // XP. // XXX for(x = 1; x &lt; width - 1; x++){ p = pixels[x, y]; if(p.distance &gt; 0f){ UpdateDistance(p, x, y, -1, 0); UpdateDistance(p, x, y, -1, -1); UpdateDistance(p, x, y, 0, -1); UpdateDistance(p, x, y, 1, -1); } } // XP| // XX| p = pixels[width - 1, y]; if(p.distance &gt; 0f){ UpdateDistance(p, width - 1, y, -1, 0); UpdateDistance(p, width - 1, y, -1, -1); UpdateDistance(p, width - 1, y, 0, -1); } // &lt;-- // .PX for(x = width - 2; x &gt;= 0; x--){ p = pixels[x, y]; if(p.distance &gt; 0f){ UpdateDistance(p, x, y, 1, 0); } } } // scan down for(y = height - 2; y &gt;= 0; y--){ // XX| // .P| p = pixels[width - 1, y]; if(p.distance &gt; 0f){ UpdateDistance(p, width - 1, y, 0, 1); UpdateDistance(p, width - 1, y, -1, 1); } // &lt;-- // XXX // .PX for(x = width - 2; x &gt; 0; x--){ p = pixels[x, y]; if(p.distance &gt; 0f){ UpdateDistance(p, x, y, 1, 0); UpdateDistance(p, x, y, 1, 1); UpdateDistance(p, x, y, 0, 1); UpdateDistance(p, x, y, -1, 1); } } // |XX // |PX p = pixels[0, y]; if(p.distance &gt; 0f){ UpdateDistance(p, 0, y, 1, 0); UpdateDistance(p, 0, y, 1, 1); UpdateDistance(p, 0, y, 0, 1); } // --&gt; // XP. for(x = 1; x &lt; width; x++){ p = pixels[x, y]; if(p.distance &gt; 0f){ UpdateDistance(p, x, y, -1, 0); } } } } private static void PostProcess (float maxDistance) { // adjust distances near edges based on the local edge gradient for(int y = 0; y &lt; height; y++){ for(int x = 0; x &lt; width; x++){ Pixel p = pixels[x, y]; if((p.dX == 0 &amp;&amp; p.dY == 0) || p.distance &gt;= maxDistance){ // ignore edge, inside, and beyond max distance continue; } float dX = p.dX, dY = p.dY; Pixel closest = pixels[x - p.dX, y - p.dY]; Vector2 g = closest.gradient; if(g.x == 0f &amp;&amp; g.y == 0f){ // ignore unknown gradients (inside) continue; } // compute hit point offset on gradient inside pixel float df = ApproximateEdgeDelta(g.x, g.y, closest.alpha); float t = dY * g.x - dX * g.y; float u = -df * g.x + t * g.y; float v = -df * g.y - t * g.x; // use hit point to compute distance if(Mathf.Abs(u) &lt;= 0.5f &amp;&amp; Mathf.Abs(v) &lt;= 0.5f){ p.distance = Mathf.Sqrt((dX + u) * (dX + u) + (dY + v) * (dY + v)); } } } } }</code></pre></div> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://contourtextures.wikidot.com/forum/t-396481</guid>
				<title>Sharp Corners</title>
				<link>http://contourtextures.wikidot.com/forum/t-396481/sharp-corners</link>
				<description>Are sharp corners rounded off?</description>
				<pubDate>Fri, 30 Sep 2011 13:08:14 +0000</pubDate>
				<wikidot:authorName>MeepMeep</wikidot:authorName>				<wikidot:authorUserId>220256</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>Does your algorithm handle sharp corners better than Valve's method?</p> <p>With Valve's method sharp corners turn into rounded corners as mentioned in their paper. Their solution for this, a channel for each edge, doesn't really seem like a good fit for something like a text glyph.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://contourtextures.wikidot.com/forum/t-374611</guid>
				<title>C version only</title>
				<link>http://contourtextures.wikidot.com/forum/t-374611/c-version-only</link>
				<description>C version of matlab/octave code</description>
				<pubDate>Tue, 19 Jul 2011 17:38:06 +0000</pubDate>
				<wikidot:authorName>Nicolas Rougier</wikidot:authorName>				<wikidot:authorUserId>1034415</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>Hi,</p> <p>Here is a C only version of the matlab/octave code. It only needs edtaa3func.c.<br /> Hope this is useful.</p> <p>Nicolas</p> <div class="code"> <pre><code>#include &lt;stdlib.h&gt; #include &lt;string.h&gt; #include &lt;stdio.h&gt; #include &lt;math.h&gt; #include &quot;edtaa3func.c&quot; // Define some fixed size types. typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned int uint32; // TGA Header struct to make it simple to dump a TGA to disc. #if defined(_MSC_VER) || defined(__GNUC__) #pragma pack(push, 1) #pragma pack(1) // Dont pad the following struct. #endif typedef struct _TGA_header { uint8 idLength, // Length of optional identification sequence. paletteType, // Is a palette present? (1=yes) imageType; // Image data type (0=none, 1=indexed, 2=rgb, // 3=grey, +8=rle packed). uint16 firstPaletteEntry, // First palette index, if present. numPaletteEntries; // Number of palette entries, if present. uint8 paletteBits; // Number of bits per palette entry. uint16 x, // Horiz. pixel coord. of lower left of image. y, // Vert. pixel coord. of lower left of image. width, // Image width in pixels. height; // Image height in pixels. uint8 depth, // Image color depth (bits per pixel). descriptor; // Image attribute flags. } TGA_header; #if defined(_MSC_VER) || defined(__GNUC__) #pragma pack(pop) #endif int TGA_write( char * filename, unsigned int width, unsigned int height, unsigned char *data ) { TGA_header header; memset( &amp;header, 0, sizeof(TGA_header) ); header.imageType = 3; header.width = width; header.height = height; header.depth = 8; header.descriptor = 0x20; FILE *file; file = fopen(filename, &quot;wb&quot;); if( !file ) { fprintf(stderr, &quot;Failed to write file\n&quot;); return 0; } fwrite( (const char *) &amp;header, sizeof(TGA_header), 1, file ); fwrite( data, sizeof(unsigned char), width * height, file); fclose(file); return 1; } unsigned char *TGA_read( char *filename, unsigned int * width, unsigned int * height, unsigned int * depth ) { FILE *file; unsigned char type[4]; unsigned char info[6]; file = fopen( filename, &quot;rb&quot; ); if( !file ) { return 0; } fread( &amp;type, sizeof (char), 3, file ); fseek( file, 12, SEEK_SET ); fread( &amp;info, sizeof (char), 6, file ); /* Only image type (color) or 3 (greyscale) */ if( type[1] != 0 || (type[2] != 2 &amp;&amp; type[2] != 3) ) { fclose( file ); return 0; } *width = info[0] + info[1] * 256; *height = info[2] + info[3] * 256; *depth = info[4] / 8; if( *depth != 1 &amp;&amp; *depth != 3 &amp;&amp; *depth != 4 ) { fclose(file); return 0; } // Allocate memory for image data unsigned long size = *height * *width * *depth; unsigned char *data = (unsigned char *) malloc( size * sizeof(unsigned char) ); // Read in image data fread( data, sizeof(unsigned char), size, file ); fclose( file ); return data; } unsigned char * make_distance_map( unsigned char *img, unsigned int width, unsigned int height ) { short * xdist = (short *) malloc( width * height * sizeof(short) ); short * ydist = (short *) malloc( width * height * sizeof(short) ); double * gx = (double *) calloc( width * height, sizeof(double) ); double * gy = (double *) calloc( width * height, sizeof(double) ); double * data = (double *) calloc( width * height, sizeof(double) ); double * outside = (double *) calloc( width * height, sizeof(double) ); double * inside = (double *) calloc( width * height, sizeof(double) ); int i; // Convert img into double (data) double img_min = 255, img_max = -255; for( i=0; i&lt;width*height; ++i) { double v = img[i]; data[i] = v; if (v &gt; img_max) img_max = v; if (v &lt; img_min) img_min = v; } // Rescale image levels between 0 and 1 for( i=0; i&lt;width*height; ++i) { data[i] = (img[i]-img_min)/img_max; } // Compute outside = edtaa3(bitmap); % Transform background (0's) computegradient( data, height, width, gx, gy); edtaa3(data, gx, gy, height, width, xdist, ydist, outside); for( i=0; i&lt;width*height; ++i) if( outside[i] &lt; 0 ) outside[i] = 0.0; // Compute inside = edtaa3(1-bitmap); % Transform foreground (1's) memset(gx, 0, sizeof(double)*width*height ); memset(gy, 0, sizeof(double)*width*height ); for( i=0; i&lt;width*height; ++i) data[i] = 1 - data[i]; computegradient( data, height, width, gx, gy); edtaa3(data, gx, gy, height, width, xdist, ydist, inside); for( i=0; i&lt;width*height; ++i) if( inside[i] &lt; 0 ) inside[i] = 0.0; // distmap = outside - inside; % Bipolar distance field unsigned char *out = (unsigned char *) malloc( width * height * sizeof(unsigned char) ); for( i=0; i&lt;width*height; ++i) { outside[i] -= inside[i]; outside[i] = 128+outside[i]*16; if( outside[i] &lt; 0 ) outside[i] = 0; if( outside[i] &gt; 255 ) outside[i] = 255; out[i] = 255 - (unsigned char) outside[i]; } free( xdist ); free( ydist ); free( gx ); free( gy ); free( data ); free( outside ); free( inside ); return out; } int main( int argc, char **argv ) { unsigned int width=0, height=0, depth=0; unsigned char *img = TGA_read(&quot;texture.tga&quot;, &amp;width, &amp;height, &amp;depth); if (!img) { fprintf( stderr, &quot;Failed to read image !\n&quot; ); return EXIT_FAILURE; } printf(&quot;Image dimension: %d x %d x %d\n&quot;, width, height, depth); if (depth != 1) { fprintf( stderr, &quot;Image has to be grayscale !\n&quot; ); free(img); return EXIT_FAILURE; } unsigned char *out = make_distance_map(img, width, height); TGA_write(&quot;texture-distance.tga&quot;, width, height, out); free(img); free(out); return EXIT_SUCCESS; }</code></pre></div> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://contourtextures.wikidot.com/forum/t-367798</guid>
				<title>Bug Fix</title>
				<link>http://contourtextures.wikidot.com/forum/t-367798/bug-fix</link>
				<description>Fixed code against infinite iteration</description>
				<pubDate>Tue, 21 Jun 2011 14:20:28 +0000</pubDate>
				<wikidot:authorName>trigrou</wikidot:authorName>				<wikidot:authorUserId>993936</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>Hi,<br /> I tried the code but on my hardware it runs infinitely. Looking and debugging with printf inside edtaa3func.c it seems that it does not converge maybe because of floating point error.<br /> So I introduced a threshold to let the do while a chance to quit the function.</p> <p>I put the code on github<br /> <a href="https://github.com/cedricpinson/DistanceMapGenerator">https://github.com/cedricpinson/DistanceMapGenerator</a></p> <p>Cedric</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://contourtextures.wikidot.com/forum/t-363559</guid>
				<title>help for a new programmer in this area</title>
				<link>http://contourtextures.wikidot.com/forum/t-363559/help-for-a-new-programmer-in-this-area</link>
				<description></description>
				<pubDate>Fri, 27 May 2011 09:59:08 +0000</pubDate>
				<wikidot:authorName>htemp</wikidot:authorName>				<wikidot:authorUserId>946731</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>Firstly I want to thank you for your time and great effort you provide in this website.<br /> I am a new researcher in this field, and I try to evolve my knowledge. I have read several articles and yourself, I learn some concepts and it is not quite sure though.<br /> I took you to direct me,<br /> I am grateful for your attention to my letter.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://contourtextures.wikidot.com/forum/t-301472</guid>
				<title>Level Set Contour Textures</title>
				<link>http://contourtextures.wikidot.com/forum/t-301472/level-set-contour-textures</link>
				<description></description>
				<pubDate>Fri, 21 Jan 2011 15:25:06 +0000</pubDate>
				<wikidot:authorName>Florian Oeser</wikidot:authorName>				<wikidot:authorUserId>684659</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>Hello,</p> <p>first off all i like to say thank you for the great paper you're providing here. I also found your paper &quot;Level Set Contour Textures&quot; <a href="http://webstaff.itn.liu.se/~stegu/contourtextures/">here</a>. Now i ask my self why this paper isn't also linked on this website because it wasn't easy to find it. Is it still under work and you haven't submit this? Or did i simple overseen something? :)</p> <p>I'm currently writing my bachelor thesis related to Chris Green's approach and i like to mention your papers (aaedt and lsctex). Is it possible to provide me a bibtex for lsctex?<br /> And furthermore i like to ask if i''m allowed to use some figures from maybe both of the papers. Actually i don't know exactly which ones but i thought it's a good idea to ask before in general.</p> <p>Thanks and regards,</p> <p>Florian Oeser</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://contourtextures.wikidot.com/forum/t-287422</guid>
				<title>Compiling demo on Mac OS X</title>
				<link>http://contourtextures.wikidot.com/forum/t-287422/compiling-demo-on-mac-os-x</link>
				<description>I&#039;m having trouble getting the source to compile on Mac OS X</description>
				<pubDate>Sat, 27 Nov 2010 20:33:09 +0000</pubDate>
				<wikidot:authorName>Daniel Brauer</wikidot:authorName>				<wikidot:authorUserId>633061</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>First, I'd just like to say that this looks like an excellent idea. It always bothered me that other contour texture generators used only binary data, because that's not usually what you have. The easiest format to find for both vector images and fonts is anti-aliased bitmaps.</p> <p>I'm only just starting with this, but I can't get the demo to compile on my Mac. I've installed GLFW 2.7. It's been a while since I've compiled anything from the command line, so forgive me if I'm missing something obvious. Here's the output from gcc:</p> <div class="code"> <pre><code>/bin/sh bundle.sh GLSL-contourtextures gcc -o GLSL-contourtextures.app/Contents/MacOS/GLSL-contourtextures GLSL-contourtextures.c -lglfw -framework Carbon -framework AGL -framework OpenGL Undefined symbols: &quot;.objc_class_name_NSAutoreleasePool&quot;, referenced from: literal-pointer@__OBJC@__cls_refs@NSAutoreleasePool in libglfw.a(cocoa_window.o) literal-pointer@__OBJC@__cls_refs@NSAutoreleasePool in libglfw.a(cocoa_init.o) &quot;_objc_msgSend_fpret&quot;, referenced from: -[GLFWContentView mouseMoved:] in libglfw.a(cocoa_window.o) -[GLFWContentView mouseMoved:] in libglfw.a(cocoa_window.o) -[GLFWContentView scrollWheel:] in libglfw.a(cocoa_window.o) __glfwPlatformSetTime in libglfw.a(cocoa_time.o) __glfwPlatformGetTime in libglfw.a(cocoa_time.o) &quot;.objc_class_name_NSBundle&quot;, referenced from: literal-pointer@__OBJC@__cls_refs@NSBundle in libglfw.a(cocoa_init.o) &quot;.objc_class_name_NSOpenGLPixelFormat&quot;, referenced from: literal-pointer@__OBJC@__cls_refs@NSOpenGLPixelFormat in libglfw.a(cocoa_window.o) &quot;.objc_class_name_NSOpenGLContext&quot;, referenced from: literal-pointer@__OBJC@__cls_refs@NSOpenGLContext in libglfw.a(cocoa_window.o) &quot;.objc_class_name_NSString&quot;, referenced from: literal-pointer@__OBJC@__cls_refs@NSString in libglfw.a(cocoa_window.o) literal-pointer@__OBJC@__cls_refs@NSString in libglfw.a(cocoa_init.o) &quot;.objc_class_name_NSScreen&quot;, referenced from: literal-pointer@__OBJC@__cls_refs@NSScreen in libglfw.a(cocoa_window.o) &quot;.objc_class_name_NSMenu&quot;, referenced from: literal-pointer@__OBJC@__cls_refs@NSMenu in libglfw.a(cocoa_init.o) &quot;_objc_msgSend_stret&quot;, referenced from: -[GLFWWindowDelegate windowDidResize:] in libglfw.a(cocoa_window.o) -[GLFWWindowDelegate windowDidResize:] in libglfw.a(cocoa_window.o) -[GLFWContentView mouseMoved:] in libglfw.a(cocoa_window.o) __glfwPlatformSetWindowPos in libglfw.a(cocoa_window.o) __glfwPlatformSetWindowPos in libglfw.a(cocoa_window.o) __glfwPlatformSetWindowPos in libglfw.a(cocoa_window.o) __glfwPlatformSetWindowPos in libglfw.a(cocoa_window.o) &quot;.objc_class_name_NSCursor&quot;, referenced from: literal-pointer@__OBJC@__cls_refs@NSCursor in libglfw.a(cocoa_window.o) &quot;_objc_msgSendSuper&quot;, referenced from: -[GLFWContentView keyDown:] in libglfw.a(cocoa_window.o) -[GLFWApplication sendEvent:] in libglfw.a(cocoa_init.o) &quot;.objc_class_name_NSApplication&quot;, referenced from: .objc_class_name_GLFWApplication in libglfw.a(cocoa_init.o) &quot;_objc_msgSend&quot;, referenced from: __glfwPlatformPollEvents in libglfw.a(cocoa_window.o) __glfwPlatformPollEvents in libglfw.a(cocoa_window.o) __glfwPlatformPollEvents in libglfw.a(cocoa_window.o) __glfwPlatformPollEvents in libglfw.a(cocoa_window.o) __glfwPlatformPollEvents in libglfw.a(cocoa_window.o) __glfwPlatformPollEvents in libglfw.a(cocoa_window.o) __glfwPlatformWaitEvents in libglfw.a(cocoa_window.o) __glfwPlatformWaitEvents in libglfw.a(cocoa_window.o) __glfwPlatformWaitEvents in libglfw.a(cocoa_window.o) __glfwPlatformRefreshWindowParams in libglfw.a(cocoa_window.o) __glfwPlatformRefreshWindowParams in libglfw.a(cocoa_window.o) __glfwPlatformRefreshWindowParams in libglfw.a(cocoa_window.o) __glfwPlatformRefreshWindowParams in libglfw.a(cocoa_window.o) __glfwPlatformRefreshWindowParams in libglfw.a(cocoa_window.o) __glfwPlatformRefreshWindowParams in libglfw.a(cocoa_window.o) __glfwPlatformRefreshWindowParams in libglfw.a(cocoa_window.o) __glfwPlatformRefreshWindowParams in libglfw.a(cocoa_window.o) __glfwPlatformRefreshWindowParams in libglfw.a(cocoa_window.o) __glfwPlatformSwapInterval in libglfw.a(cocoa_window.o) __glfwPlatformSwapBuffers in libglfw.a(cocoa_window.o) __glfwPlatformRestoreWindow in libglfw.a(cocoa_window.o) __glfwPlatformIconifyWindow in libglfw.a(cocoa_window.o) __glfwPlatformSetWindowSize in libglfw.a(cocoa_window.o) __glfwPlatformSetWindowTitle in libglfw.a(cocoa_window.o) __glfwPlatformSetWindowTitle in libglfw.a(cocoa_window.o) -[GLFWContentView otherMouseDragged:] in libglfw.a(cocoa_window.o) -[GLFWContentView rightMouseDragged:] in libglfw.a(cocoa_window.o) -[GLFWContentView mouseDragged:] in libglfw.a(cocoa_window.o) -[GLFWWindowDelegate windowDidResize:] in libglfw.a(cocoa_window.o) -[GLFWContentView otherMouseUp:] in libglfw.a(cocoa_window.o) -[GLFWContentView otherMouseDown:] in libglfw.a(cocoa_window.o) -[GLFWContentView mouseMoved:] in libglfw.a(cocoa_window.o) -[GLFWContentView mouseMoved:] in libglfw.a(cocoa_window.o) -[GLFWContentView flagsChanged:] in libglfw.a(cocoa_window.o) -[GLFWContentView flagsChanged:] in libglfw.a(cocoa_window.o) -[GLFWContentView keyUp:] in libglfw.a(cocoa_window.o) -[GLFWContentView keyUp:] in libglfw.a(cocoa_window.o) -[GLFWContentView keyUp:] in libglfw.a(cocoa_window.o) -[GLFWContentView keyUp:] in libglfw.a(cocoa_window.o) -[GLFWContentView keyDown:] in libglfw.a(cocoa_window.o) -[GLFWContentView keyDown:] in libglfw.a(cocoa_window.o) -[GLFWContentView keyDown:] in libglfw.a(cocoa_window.o) -[GLFWContentView keyDown:] in libglfw.a(cocoa_window.o) -[GLFWContentView keyDown:] in libglfw.a(cocoa_window.o) __glfwPlatformSetMouseCursorPos in libglfw.a(cocoa_window.o) __glfwPlatformShowMouseCursor in libglfw.a(cocoa_window.o) __glfwPlatformHideMouseCursor in libglfw.a(cocoa_window.o) __glfwPlatformCloseWindow in libglfw.a(cocoa_window.o) __glfwPlatformCloseWindow in libglfw.a(cocoa_window.o) __glfwPlatformCloseWindow in libglfw.a(cocoa_window.o) __glfwPlatformCloseWindow in libglfw.a(cocoa_window.o) __glfwPlatformCloseWindow in libglfw.a(cocoa_window.o) __glfwPlatformCloseWindow in libglfw.a(cocoa_window.o) __glfwPlatformCloseWindow in libglfw.a(cocoa_window.o) __glfwPlatformCloseWindow in libglfw.a(cocoa_window.o) __glfwPlatformCloseWindow in libglfw.a(cocoa_window.o) __glfwPlatformCloseWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformOpenWindow in libglfw.a(cocoa_window.o) __glfwPlatformSetWindowPos in libglfw.a(cocoa_window.o) __glfwPlatformSetWindowPos in libglfw.a(cocoa_window.o) -[GLFWApplication sendEvent:] in libglfw.a(cocoa_init.o) -[GLFWApplication sendEvent:] in libglfw.a(cocoa_init.o) -[GLFWApplication sendEvent:] in libglfw.a(cocoa_init.o) -[GLFWApplication sendEvent:] in libglfw.a(cocoa_init.o) __glfwPlatformTerminate in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) __glfwPlatformInit in libglfw.a(cocoa_init.o) &quot;.objc_class_name_NSWindow&quot;, referenced from: literal-pointer@__OBJC@__cls_refs@NSWindow in libglfw.a(cocoa_window.o) &quot;.objc_class_name_NSMenuItem&quot;, referenced from: literal-pointer@__OBJC@__cls_refs@NSMenuItem in libglfw.a(cocoa_init.o) &quot;.objc_class_name_NSView&quot;, referenced from: .objc_class_name_GLFWContentView in libglfw.a(cocoa_window.o) &quot;_NSApp&quot;, referenced from: _NSApp$non_lazy_ptr in libglfw.a(cocoa_window.o) _NSApp$non_lazy_ptr in libglfw.a(cocoa_init.o) (maybe you meant: _NSApp$non_lazy_ptr) ld: symbol(s) not found collect2: ld returned 1 exit status make: *** [GLSL-contourtextures] Error 1</code></pre></div> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://contourtextures.wikidot.com/forum/t-245467</guid>
				<title>creating textures</title>
				<link>http://contourtextures.wikidot.com/forum/t-245467/creating-textures</link>
				<description></description>
				<pubDate>Wed, 02 Jun 2010 18:29:52 +0000</pubDate>
				<wikidot:authorName>pswin</wikidot:authorName>				<wikidot:authorUserId>491625</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>hi<br /> i want to use it for my game engine font system but i have some problems:</p> <p>1. how can i create textures?, any tool or source code<br /> 2. wich size for fonts is best? (for example 12)</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://contourtextures.wikidot.com/forum/t-188436</guid>
				<title>Artefacts in the demo</title>
				<link>http://contourtextures.wikidot.com/forum/t-188436/artefacts-in-the-demo</link>
				<description>Some rather nasty artefacts can appear in the demo, particularly with Nvidia GPUs. These are problems with the demo itself, and are not to be taken as defects of either Green&#039;s method or my own distance transform.</description>
				<pubDate>Tue, 13 Oct 2009 11:34:06 +0000</pubDate>
				<wikidot:authorName>stegu</wikidot:authorName>				<wikidot:authorUserId>30391</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>There are some unwanted artefacts in the demo that people have commented on:</p> <p><strong>On extreme minification, the texture becomes gray.</strong></p> <p>This is due to the 8-bit texture precision. The same limitation is seen in Chris Green's original implementation of the method. Distances more than 8 pixels from the edge are clamped, which yields incorrect antialiasing on extreme minification. The remedy is to either generate a stack of traditional mipmaps (mipmapping is not used in the current demo) and switch to conventional texturing under minification, or to use 16-bit precision for the distance map to store a correct distance value for all pixels. The 8-bit encoding was chosen for maximum compatibility with old versions of OpenGL. A 16-bit encoding could be done either by using a native 16-bit texture format, or by using two 8-bit pixels per distance value and compositing them to a higher precision value in the shader. I have used both with good results.</p> <p><strong>Tilting the polygon out of the screen plane gives nasty artefacts with an Nvidia GPU.</strong></p> <p>This is a strange bug related to the automatic derivative functions dFdx() and dFdy() and the related function fwidth() in GLSL. I have not yet been able to isolate the cause of this, but it is a problem specific to Nvidia GPUs. I tested this only on my ATI card, and there it works OK.<br /> (BTW, I should have written aastep=length(vec2(dFdx(D), dFdy(D))), not aastep=0.5*length(fwidth(uv)) in the demo, but that is unrelated to the bug. I have now changed that in the archives. The antialiasing is now anisotropic and analytically correct on an ATI GPU.)</p> <p>In another demo I store the gradients explicitly in the texture <em>and</em> use 16 bits for the distance value. That gives better minification, and no antialiasing problems with Nvidia GPUs because the distance field is not differentiated using dFdx() and dFdy(). The pattern is also smoother because I use a different interpolation scheme that turned out not to be such a great idea after all (it wasn't bad, but more trouble than it was worth):</p> <p><a href="http://www.itn.liu.se/~stegu/contourtextures/">A nicer, but slightly different demo</a></p> 
				 	]]>
				</content:encoded>							</item>
				</channel>
</rss>