Search Home Members Contacts
About Us
Products
Downloads
Community
Support
Pages: [1]
  Print  
Author Topic: Perlin generation & Interpolation Smoothing (SOLVED)  (Read 535 times)
newborn
Customers
Community Member
*****
Posts: 2417


WWW
« on: June 23, 2008, 09:15:05 PM »

I didn't want to hi-jack someone else's thread to post about my issues, so here it is:



I don't like the result of the smooth interpolation in both case. The linear interpolation gives straight lines and the cosine interpolation gives funny squares.

Anyone came up with a bicubic or whatever else solution that brings a better result on the generated perlin? As I understand it, it should simply be a parabolic LERP, no?
« Last Edit: June 27, 2008, 06:50:37 PM by newborn » Logged

Lenn
Customers
Community Member
*****
Posts: 351

Ivan Miskelic


« Reply #1 on: June 23, 2008, 09:38:20 PM »

I think I saw a useful function in the Ammunition SDK for this. You can download it for free.

Let me look...

..
ohyeah here it is, have a look:

ResizeBicubic()
Code:

 /// <summary>
    /// Resize image using bicubic interpolation
    /// </summary>
    ///
    /// <remarks></remarks>
    ///
public class ResizeBicubic : FilterResize
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="ResizeBicubic"/> class
        /// </summary>
        ///
        /// <param name="newWidth">Width of new image</param>
        /// <param name="newHeight">Height of new image</param>
        ///
public ResizeBicubic( int newWidth, int newHeight ) :
            base( newWidth, newHeight )
        {
}

        /// <summary>
        /// Process the filter on the specified image
        /// </summary>
        ///
        /// <param name="sourceData">Source image data</param>
        /// <param name="destinationData">Destination image data</param>
        ///
        protected override unsafe void ProcessFilter( BitmapData sourceData, BitmapData destinationData )
        {
            // get source image size
            int width   = sourceData.Width;
            int height  = sourceData.Height;

            int pixelSize = ( sourceData.PixelFormat == PixelFormat.Format8bppIndexed ) ? 1 : 3;
            int srcStride = sourceData.Stride;
            int dstOffset = destinationData.Stride - pixelSize * newWidth;
            double xFactor = (double) width / newWidth;
            double yFactor = (double) height / newHeight;

            // do the job
            byte* src = (byte*) sourceData.Scan0.ToPointer( );
            byte* dst = (byte*) destinationData.Scan0.ToPointer( );

            // coordinates of source points and cooefficiens
            double  ox, oy, dx, dy, k1, k2;
            int     ox1, oy1, ox2, oy2;
            // destination pixel values
            double r, g, b;
            // width and height decreased by 1
            int ymax = height - 1;
            int xmax = width - 1;
            // temporary pointer
            byte* p;

            // check pixel format
            if ( destinationData.PixelFormat == PixelFormat.Format8bppIndexed )
            {
                // grayscale
                for ( int y = 0; y < newHeight; y++ )
                {
                    // Y coordinates
                    oy  = (double) y * yFactor - 0.5;
                    oy1 = (int) oy;
                    dy  = oy - (double) oy1;

                    for ( int x = 0; x < newWidth; x++, dst++ )
                    {
                        // X coordinates
                        ox  = (double) x * xFactor - 0.5f;
                        ox1 = (int) ox;
                        dx  = ox - (double) ox1;

                        // initial pixel value
                        g = 0;

                        for ( int n = -1; n < 3; n++ )
                        {
                            // get Y cooefficient
                            k1 = Interpolation.BiCubicKernel( dy - (double) n );

                            oy2 = oy1 + n;
                            if ( oy2 < 0 )
                                oy2 = 0;
                            if ( oy2 > ymax )
                                oy2 = ymax;

                            for ( int m = -1; m < 3; m++ )
                            {
                                // get X cooefficient
                                k2 = k1 * Interpolation.BiCubicKernel( (double) m - dx );

                                ox2 = ox1 + m;
                                if ( ox2 < 0 )
                                    ox2 = 0;
                                if ( ox2 > xmax )
                                    ox2 = xmax;

                                g += k2 * src[oy2 * srcStride + ox2];
                            }
                        }
                        *dst = (byte) g;
                    }
                    dst += dstOffset;
                }
            }
            else
            {
                // RGB
                for ( int y = 0; y < newHeight; y++ )
                {
                    // Y coordinates
                    oy  = (double) y * yFactor - 0.5f;
                    oy1 = (int) oy;
                    dy  = oy - (double) oy1;

                    for ( int x = 0; x < newWidth; x++, dst += 3 )
                    {
                        // X coordinates
                        ox  = (double) x * xFactor - 0.5f;
                        ox1 = (int) ox;
                        dx  = ox - (double) ox1;

                        // initial pixel value
                        r = g = b = 0;

                        for ( int n = -1; n < 3; n++ )
                        {
                            // get Y cooefficient
                            k1 = Interpolation.BiCubicKernel( dy - (double) n );

                            oy2 = oy1 + n;
                            if ( oy2 < 0 )
                                oy2 = 0;
                            if ( oy2 > ymax )
                                oy2 = ymax;

                            for ( int m = -1; m < 3; m++ )
                            {
                                // get X cooefficient
                                k2 = k1 * Interpolation.BiCubicKernel( (double) m - dx );

                                ox2 = ox1 + m;
                                if ( ox2 < 0 )
                                    ox2 = 0;
                                if ( ox2 > xmax )
                                    ox2 = xmax;

                                // get pixel of original image
                                p = src + oy2 * srcStride + ox2 * 3;

                                r += k2 * p[RGB.R];
                                g += k2 * p[RGB.G];
                                b += k2 * p[RGB.B];
                            }
                        }

                        dst[RGB.R] = (byte) r;
                        dst[RGB.G] = (byte) g;
                        dst[RGB.B] = (byte) b;
                    }
                    dst += dstOffset;
                }
            }
        }
    }


and ResizeBilinear()

Code:

/// <summary>
    /// Resize image using bilinear interpolation
    /// </summary>
    ///
    /// <remarks></remarks>
    ///
    public class ResizeBilinear : FilterResize
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="ResizeBilinear"/> class
        /// </summary>
        ///
        /// <param name="newWidth">Width of new image</param>
        /// <param name="newHeight">Height of new image</param>
        ///
public ResizeBilinear( int newWidth, int newHeight ) :
            base( newWidth, newHeight )
{
}

        /// <summary>
        /// Process the filter on the specified image
        /// </summary>
        ///
        /// <param name="sourceData">Source image data</param>
        /// <param name="destinationData">Destination image data</param>
        ///
        protected override unsafe void ProcessFilter( BitmapData sourceData, BitmapData destinationData )
        {
            // get source image size
            int width   = sourceData.Width;
            int height  = sourceData.Height;

            int pixelSize = ( sourceData.PixelFormat == PixelFormat.Format8bppIndexed ) ? 1 : 3;
            int srcStride = sourceData.Stride;
            int dstOffset = destinationData.Stride - pixelSize * newWidth;
            double xFactor = (double) width / newWidth;
            double yFactor = (double) height / newHeight;

            // do the job
            byte* src = (byte*) sourceData.Scan0.ToPointer( );
            byte* dst = (byte*) destinationData.Scan0.ToPointer( );

            // coordinates of source points
            double  ox, oy, dx1, dy1, dx2, dy2;
            int     ox1, oy1, ox2, oy2;
            // width and height decreased by 1
            int ymax = height - 1;
            int xmax = width - 1;
            // temporary pointers
            byte* tp1, tp2;
            byte* p1, p2, p3, p4;

            // for each line
            for ( int y = 0; y < newHeight; y++ )
            {
                // Y coordinates
                oy  = (double) y * yFactor;
                oy1 = (int) oy;
                oy2 = ( oy1 == ymax ) ? oy1 : oy1 + 1;
                dy1 = oy - (double) oy1;
                dy2 = 1.0 - dy1;

                // get temp pointers
                tp1 = src + oy1 * srcStride;
                tp2 = src + oy2 * srcStride;

                // for each pixel
                for ( int x = 0; x < newWidth; x++ )
                {
                    // X coordinates
                    ox  = (double) x * xFactor;
                    ox1 = (int) ox;
                    ox2 = ( ox1 == xmax ) ? ox1 : ox1 + 1;
                    dx1 = ox - (double) ox1;
                    dx2 = 1.0 - dx1;

                    // get four points
                    p1 = tp1 + ox1 * pixelSize;
                    p2 = tp1 + ox2 * pixelSize;
                    p3 = tp2 + ox1 * pixelSize;
                    p4 = tp2 + ox2 * pixelSize;

                    // interpolate using 4 points
                    for ( int i = 0; i < pixelSize; i++, dst++, p1++, p2++, p3++, p4++ )
                    {
                        *dst = (byte) (
                            dy2 * ( dx2 * ( *p1 ) + dx1 * ( *p2 ) ) +
                            dy1 * ( dx2 * ( *p3 ) + dx1 * ( *p4 ) ) );
                    }
                }
                dst += dstOffset;
            }
        }
    }

Logged

Theres a shadow just behind me. shrouding every step I take.
Making every promise empty. pointing every finger at me.
Waiting like a stalking butler, who upon the finger rests.
Murder now the path of must we, just because the son has come.
newborn
Customers
Community Member
*****
Posts: 2417


WWW
« Reply #2 on: June 24, 2008, 05:39:58 AM »

Thanks Lenn, I think this is exactly what I was looking for.
Logged

Raine
Customers
Community Member
*****
Posts: 1086


« Reply #3 on: June 24, 2008, 07:41:28 AM »

As far as I can remember, VB has no unsafe context keyword. Moreover, I don't see any fixed statement before using the pointers...

http://msdn.microsoft.com/en-us/library/f58wzh21(VS.80).aspx
Logged

Lenn
Customers
Community Member
*****
Posts: 351

Ivan Miskelic


« Reply #4 on: June 24, 2008, 12:44:31 PM »

Thanks Lenn, I think this is exactly what I was looking for.

No probs, hope it helps. Wink

Logged

Theres a shadow just behind me. shrouding every step I take.
Making every promise empty. pointing every finger at me.
Waiting like a stalking butler, who upon the finger rests.
Murder now the path of must we, just because the son has come.
newborn
Customers
Community Member
*****
Posts: 2417


WWW
« Reply #5 on: June 27, 2008, 06:50:24 PM »

Alright, took a while but I finally got it working as I wanted to:

Logged

Zaknafein
Customers
Community Member
*****
Posts: 2593


WWW
« Reply #6 on: June 28, 2008, 01:26:58 AM »

Since I'll be looking into bicubic interpolation soon, can you give us a little info on how you solved it? Did you just use the straight code from the Ammunition SDK?
Logged

zaknafein.
>> the instruction limit : my blog & samples repository! <<
newborn
Customers
Community Member
*****
Posts: 2417


WWW
« Reply #7 on: July 02, 2008, 06:07:32 AM »

Sorry for the long delay Zak, I was away to some other province for the long weekend.

No, I did not take anything out of ammo SDK, I simply sed the new Perlin generation system:


http://mrl.nyu.edu/~perlin/paper445.pdf

http://http.developer.nvidia.com/GPUGems/gpugems_ch05.html

http://mrl.nyu.edu/~perlin/noise/

http://www.vbaccelerator.com/home/VB/code/vbMedia/Algorithmic_Images/Perlin_Noise/article.asp
Logged

Pages: [1]
  Print  
 
Jump to:  

Powered by SMF 1.1.3 | SMF © 2006-2007, Simple Machines LLC
Seo4Smf v0.2 © Webmaster's Talks