Click here to Skip to main content
Click here to Skip to main content

Pixel Shader for Edge Detection and Cartoon Effect

By , 19 Aug 2010
 

Introduction

This article explains the implementation of the Sobel Edge Detection method in a pixel shader using C++. And also the implementation of Cartoon effect of an image with edge information.

TajMahal.jpg

Input image (TajMahal.bmp)

EdgeDetection_CartoonEffectOff.jpg

Screenshot of edge detection output of TajMahal.bmp

EdgeDetection_CartoonEffect.jpg

Screenshot of Cartoon effect output of TajMahal.bmp

Untitled.jpg

Another screenshot of Cartoon effect

Background

Edge detection is simple image processing, which aims at identifying points in a digital image at which the image brightness changes sharply, or more formally, has discontinuities. Sobel Edge detection uses implementation of the Sobel operator as explained in http://en.wikipedia.org/wiki/Sobel_operator.

After implementing edge detection, I found a simple technique to make the cartoon effect image by combining the input image and its edge image.

Using the code

Initially, we can look at the C++ implementation of the Sobel Edge detection method. Two kernels are applied to each pixel. One kernel finds the color change [gradient] in the X direction, and the other finds the color change [gradient] in the Y direction.

GradientMatrices.png

The below section describes how these matrices are applied to a sample image.

This is the sample image, and we can see how the X directional and Y directional gradient calculations work.

Test.jpg

Sample image used to explain the X directional and Y directional gradient calculation

X direction gradient calculation

The code below finds out the changes in the X direction. Just find the weighted sum of the surrounding 3 * 3 pixels.

// Initializing X direction gradient kernel.
GX[0][0] = -1; GX[0][1] = 0; GX[0][2] = 1;
GX[1][0] = -2; GX[1][1] = 0; GX[1][2] = 2;
GX[2][0] = -1; GX[2][1] = 0; GX[2][2] = 1;

// Looping to findout change in X diretion
for(I=-1; I<=1; I++)
{
    for(J=-1; J<=1; J++)
    {
        sumX = sumX + (int)( (*(stOriginalImage_i.pData + nX + I +
            (nY + J)*stOriginalImage_i.nCols)) * GX[I+1][J+1]);
    }
}

Here is the output image of the X directional gradient calculation:

Test_X.jpg

The output of the X directional gradient calculation

Y direction gradient calculation

The code below finds out the changes in the Y direction. Just find the weighted sum of the surrounding 3 * 3 pixels.

// Initializing Y direction gradient kernel.
GY[0][0] =  1; GY[0][1] =  2; GY[0][2] =  1;
GY[1][0] =  0; GY[1][1] =  0; GY[1][2] =  0;
GY[2][0] = -1; GY[2][1] = -2; GY[2][2] = -1;
// Looping to findout change in Y diretion
for(I=-1; I<=1; I++)
{
    for(J=-1; J<=1; J++)
    {
        sumY = sumY + (int)( (*(stOriginalImage_i.pData + nX + I + 
            (nY + J)*stOriginalImage_i.nCols)) * GY[I+1][J+1]);
    }
}

Here is the output image of the Y directional gradient calculation:

Test_Y.jpg

Output image of the Y directional gradient calculation

Final image calculation

Finally, the X and Y directional gradient values are combined with the following equation:

Sum.png

and the code:

SUM =  sqrt(double(sumX * sumX) + double(sumY * sumY));

Here is the output:

Test_Output.jpg

Output image of the test bitmap

Edge Detection of RGB Image

This logic is used to find out the gradient for a single component image. I used this algorithm for each component of the input image [R, G, B] separately and combined the output together.

// Extract each component[R,G,B] to separate buffer to find gradient in 
// each component.
BYTE* pbyTemp = pbyBMP_io;
for (int n= 0; n < nWidth * nHeight; n++)
{
    originalImageR.pData[n] = *pbyTemp++; // Blue
    originalImageG.pData[n] = *pbyTemp++; // Green
    originalImageB.pData[n] = *pbyTemp++; // Red
}

// Find Gradient of each component separately.
FindEdge( originalImageR, OutputRed );
FindEdge( originalImageG, OutputGreen );
FindEdge( originalImageB, OutputBlue );

// Combine RGB gradient information to a output buffer.
pbyTemp = pbyBMP_io;
for (int n= 0; n < nWidth * nHeight; n++)
{
    *pbyTemp++ = OutputRed.pData[n];
    *pbyTemp++ = OutputGreen.pData[n];
    *pbyTemp++ = OutputBlue.pData[n];
}

Here is the entire code of the gradient calculation of a component:

void EdgeDetectCPU::FindEdge( ImageInfo_t& stOriginalImage_i, 
                              ImageInfo_t& stEdgeImage_o )
{
    int        nX, nY,I, J;
    long            sumX, sumY;
    int            nColors, SUM;
    int            GX[3][3];
    int            GY[3][3];
    // Allocate output buffer
    stEdgeImage_o.pData = 
      new BYTE[stOriginalImage_i.nCols * stOriginalImage_i.nRows];

    // X Directional Gradient matrix.
    GX[0][0] = -1; GX[0][1] = 0; GX[0][2] = 1;
    GX[1][0] = -2; GX[1][1] = 0; GX[1][2] = 2;
    GX[2][0] = -1; GX[2][1] = 0; GX[2][2] = 1;

    // Y Directional Gradient matrix.
    GY[0][0] =  1; GY[0][1] =  2; GY[0][2] =  1;
    GY[1][0] =  0; GY[1][1] =  0; GY[1][2] =  0;
    GY[2][0] = -1; GY[2][1] = -2; GY[2][2] = -1;

    // Iterate each pixels in the image.
    for(nY=0; nY<=(stOriginalImage_i.nRows-1); nY++)
    {
        for(nX=0; nX<=(stOriginalImage_i.nCols-1); nX++)
        {
            sumX = 0;
            sumY = 0;

            SUM = 0;
            // Skip top,bottom, left and right pixels.
            if( !(nX==0 || nX==stOriginalImage_i.nCols-1 || 
                  nY==0 || nY==stOriginalImage_i.nRows-1))
            {
                // Looping to findout change in X direction
                for(I=-1; I<=1; I++)
                {
                    for(J=-1; J<=1; J++)
                    {
                        sumX = sumX + (int)( (*(stOriginalImage_i.pData + nX + I + 
                            (nY + J)*stOriginalImage_i.nCols)) * GX[I+1][J+1]);
                    }
                }

                // Looping to find out change in Y direction
                for(I=-1; I<=1; I++)
                {
                    for(J=-1; J<=1; J++)
                    {
                        sumY = sumY + (int)( (*(stOriginalImage_i.pData + nX + I + 
                            (nY + J)*stOriginalImage_i.nCols)) * GY[I+1][J+1]);
                    }
                }
                SUM =  sqrt(double(sumX * sumX) + double(sumY * sumY));
            }

            if(SUM>255) SUM=255;
            if(SUM<0) SUM=0;
            *(stEdgeImage_o.pData + nX + nY * stOriginalImage_i.nCols) = 
                                    255 - (unsigned char)(SUM);
        }
    }
}

Cartoon Effect Implementation

The edge information of an image is now done. Cartoon effect can be simply created with this edge image and its input data. Just combine the edge image and its corresponding input image. The following figure illustrates the creation of a cartoon effect with the edge image.

HowCartoonEffect.jpg

Cartoon effect created by combining the edge image and input image

The following code explains the Cartoon effect implementation with the edge image. EdgeDetectCPU::FindEdge is modified to create a cartoon effect or edge image based on the m_bCartoonEffect flag.

if(SUM>255) SUM=255;
if(SUM<0) SUM=0;
int nOut = 0;
// Checking Cartoon Effect flag to create final image.
if( m_bCartoonEffect )
{
    // Make Cartoon effect by combining edge information and original image.
    nOut = (SUM * 0.5) + (*(stOriginalImage_i.pData + nX + 
            nY * stOriginalImage_i.nCols) * 0.5);
}
else
{
    // Creating displayable edge data.
    nOut = 255 - (unsigned char)(SUM);
}
*(stEdgeImage_o.pData + nX + nY * stOriginalImage_i.nCols) = nOut;

Pixel Shader Implementation

I hope this logic is very simple to port to a pixel shader, since the logic of the gradient calculation for a pixel is common function, and that can be applied to each pixel of the image. And the gradient calculation of a pixel does not depend on the output of the other pixel calculations (it is difficult to implement a pixel shader, if one pixel output depends on the output of the other pixel). Therefore, I removed the two for loops (that are used for the iteration of each pixel in the bitmap) in the pixel shader. The remaining task for creating the pixel shader is to convert some data types to the shader compatible data types. For example, the shader does not support two dimensional arrays, but it provides a matrix data type that can be used similar to a two dimensional array. Here is the X,Y gradient matrix declaration in the shader.

// X directional search matrix.
mat3 GX = mat3( -1.0, 0.0, 1.0,
               -2.0, 0.0, 2.0,
               -1.0, 0.0, 1.0 );
// Y directional search matrix.
mat3 GY =  mat3( 1.0,  2.0,  1.0,
                0.0,  0.0,  0.0,
                -1.0, -2.0, -1.0 );

The texture coordinates received in the pixel shader are used to find out the nX, nY values of the C++ for loop code.

// Findout X , Y index of incoming pixel from its texture coordinate.
float fXIndex = gl_TexCoord[0].s * fWidth;
float fYIndex = gl_TexCoord[0].t * fHeight;

And the entire pixel shader for edge detection and Cartoon effect is:

// Image texture.
uniform sampler2D ImageTexture;

// Width of Image.
uniform float fWidth;
// Height of Image.
uniform float fHeight;
// Indicating cartoon effect is enabled or not.
uniform float fCartoonEffect;

void main()
{
    // X directional search matrix.
    mat3 GX = mat3( -1.0, 0.0, 1.0,
                    -2.0, 0.0, 2.0,
                    -1.0, 0.0, 1.0 );
    // Y directional search matrix.
    mat3 GY =  mat3( 1.0,  2.0,  1.0,
                     0.0,  0.0,  0.0,
                    -1.0, -2.0, -1.0 );

    vec4  fSumX = vec4( 0.0,0.0,0.0,0.0 );
    vec4  fSumY = vec4( 0.0,0.0,0.0,0.0 );
    vec4 fTotalSum = vec4( 0.0,0.0,0.0,0.0 );

    // Findout X , Y index of incoming pixel
    // from its texture coordinate.
    float fXIndex = gl_TexCoord[0].s * fWidth;
    float fYIndex = gl_TexCoord[0].t * fHeight;

    /* image boundaries Top, Bottom, Left, Right pixels*/
    if( ! ( fYIndex < 1.0 || fYIndex > fHeight - 1.0 || 
            fXIndex < 1.0 || fXIndex > fWidth - 1.0 ))
    {
        // X Directional Gradient calculation.
        for(float I=-1.0; I<=1.0; I = I + 1.0)
        {
            for(float J=-1.0; J<=1.0; J = J + 1.0)
            {
                float fTempX = ( fXIndex + I + 0.5 ) / fWidth ;
                float fTempY = ( fYIndex + J + 0.5 ) / fHeight ;
                vec4 fTempSumX = texture2D( ImageTexture, vec2( fTempX, fTempY ));
                fSumX = fSumX + ( fTempSumX * vec4( GX[int(I+1.0)][int(J+1.0)],
                                                    GX[int(I+1.0)][int(J+1.0)],
                                                    GX[int(I+1.0)][int(J+1.0)],
                                                    GX[int(I+1.0)][int(J+1.0)]));
            }
        }

        { // Y Directional Gradient calculation.
            for(float I=-1.0; I<=1.0; I = I + 1.0)
            {
                for(float J=-1.0; J<=1.0; J = J + 1.0)
                {
                    float fTempX = ( fXIndex + I + 0.5 ) / fWidth ;
                    float fTempY = ( fYIndex + J + 0.5 ) / fHeight ;
                    vec4 fTempSumY = texture2D( ImageTexture, vec2( fTempX, fTempY ));
                    fSumY = fSumY + ( fTempSumY * vec4( GY[int(I+1.0)][int(J+1.0)],
                                                        GY[int(I+1.0)][int(J+1.0)],
                                                        GY[int(I+1.0)][int(J+1.0)],
                                                        GY[int(I+1.0)][int(J+1.0)]));
                }
            }
            // Combine X Directional and Y Directional Gradient.
            vec4 fTem = fSumX * fSumX + fSumY * fSumY;
            fTotalSum = sqrt( fTem );
        }
    }
    // Checking status of cartoon effect.
    if( 0.5 < fCartoonEffect )
    {
        // Creaing cartoon effect by combining
        // edge informatioon and original image data.
        fTotalSum = mix( fTotalSum, texture2D( ImageTexture, 
                         vec2( gl_TexCoord[0].s, gl_TexCoord[0].t)), 0.5);
    }
    else
    {
        // Creating displayable edge data.
        fTotalSum = vec4( 1.0,1.0,1.0,1.0) - fTotalSum;
    }
    
    gl_FragColor = ( fTotalSum );
}

The Cartoon effect or edge image is the output of this shader. This program will be executed for each pixels of the image, and this program will calculate the edge information for each pixel. Then at the final stage, the fCartoonEffect flag is used to make the output color of the shader. fCartoonEffect is set from the application to the shader based on the state of the CartoonEffect check box.

// Checking status of cartoon effect.
if( 0.5 < fCartoonEffect )
{
    // Creaing cartoon effect by combining edge
    // informatioon and original image data.
    fTotalSum = mix( fTotalSum, texture2D( ImageTexture, 
                     vec2( gl_TexCoord[0].s, gl_TexCoord[0].t)), 0.5);
}
else
{
    // Creating displayable edge data.
    fTotalSum = vec4( 1.0,1.0,1.0,1.0) - fTotalSum;
}

I think more explanation on this pixel shader is not required because we have already discussed the X directional and Y directional gradient (change) calculations in the above C++ logic.

Save Functionality

The Save button of the Edge Detection application can be used to save the output of the Edge Detection algorithm to a BMP file. The Save functionality simply reads the pixels from the screen using the glReadPixels() API.

Here is the code to read the pixel information from the screen:

pbyData = new BYTE[stImageArea.bottom * stImageArea.right  * 3];
if( 0 == pbyData )
{
    AfxMessageBox( L"Memory Allocation failed" );
    return;
}
glReadPixels( 0, 0, stImageArea.right, stImageArea.bottom, 
              GL_BGR_EXT, GL_UNSIGNED_BYTE, pbyData );
BMPLoader SaveBmp;
SaveBmp.SaveBMP( csFileName, stImageArea.right, stImageArea.bottom, pbyData );

The file name creation code for saving is a tricky one:

CString csFileName;
// This one create different names in CPU mode and GPU mode.
csFileName.Format( L"EdgeDetection_%s_%d.bmp", 
                 ( RUN_IN_CPU == m_nRunIn ) ? L"CPU" : L"GPU",
                 ( RUN_IN_CPU == m_nRunIn ) ? ++nCPUCount : ++nGPUCount );
CFileDialog SaveDlg( false, L"*.bmp", csFileName );

An example of different names generated in CPU and GPU mode: EdgeDetection_GPU_1.bmp, EdgeDetection_CPU_1.bmp.

Points of Interest

The 4 byte boundary padding of BMP data made some difficulty for edge detection calculation in CPU. The CPU edge detection is specially handled when the number of columns of the bitmap is not a multiple of 4. When edge detection is performed without considering the padding data [BMP file contains some unexpected value in the padding pixels], I get a strange output image, because the buffer provided to EdgeDetectCPU contains some unwanted data in the padded pixels. Therefore, I followed these steps to avoid the issue:

  1. Removed unexpected pixels padded at the right end of the image to make the columns a multiple of 4.
  2. Find out the edge image using EdgeDetect.EdgeDetect( m_nImageWidth, m_nImageHeight, pbyImage ).
  3. Added padding pixels (columns are made multiple of 4).

The code below handles this special case:

// Extract each component[R,G,B] to separate buffer to find gradient in 
// each component.
BYTE* pbyTemp = pbyBMP_io;
for (int n= 0; n < nWidth * nHeight; n++)
{
    originalImageR.pData[n] = *pbyTemp++; // Blue
    originalImageG.pData[n] = *pbyTemp++; // Green
    originalImageB.pData[n] = *pbyTemp++; // Red
}

// Find Gradient of each component separately.
FindEdge( originalImageR, OutputRed );
FindEdge( originalImageG, OutputGreen );
FindEdge( originalImageB, OutputBlue );

// Combine RGB gradient information to a output buffer.
pbyTemp = pbyBMP_io;
for (int n= 0; n < nWidth * nHeight; n++)
{
    *pbyTemp++ = OutputRed.pData[n];
    *pbyTemp++ = OutputGreen.pData[n];
    *pbyTemp++ = OutputBlue.pData[n];
}

BMPLoader::LoadBMP uses GDI+ to load an image file. It uses the GDIPlus::Bitmap class to read an image from a file. m_pBitmap->LockBits() provides the image data.

// Code for reading Image file from file using GDI+
Gdiplus::Bitmap* m_pBitmap = new Gdiplus::Bitmap(pFileName_i, true);

BYTE* pbyData = 0;
int nWidth = m_pBitmap->GetWidth();
int nHeight = m_pBitmap->GetHeight();
Gdiplus::Rect rect(0,0,nWidth,nHeight);
Gdiplus::BitmapData pBMPData;
m_pBitmap->LockBits( &rect,Gdiplus::ImageLockMode::ImageLockModeRead, 
                        PixelFormat24bppRGB, &pBMPData );
pbyData_o = new BYTE[nWidth * nHeight * 3];
nWidth_o = nWidth;
nHeight_o = nHeight;
if( 0 == pBMPData.Scan0 )
{
    return false;
}
BYTE* pSrc = (BYTE*)pBMPData.Scan0;
int nVert = nHeight - 1;
for( int nY = 0; nY < nHeight && nVert > 0; nY++ )
{
    // Avoid top and bottom difference.
    BYTE* pDest = pbyData_o + ( nWidth * nVert * 3 );
    memcpy( pDest, pSrc, 3 * nWidth);
    nVert--;
    pSrc += ( nWidth * 3 );
}
m_pBitmap->UnlockBits( &pBMPData );

History

  • 19 July 2010 - Initial version.
  • 28 July 2010 - Added the AppError class to display an error message if the shader creation fails.
  • 14 August 2010 - Added Cartoon effect functionality.
  • 20 August 2010 - Added JPEG, PNG image loading using GDI+.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Santhosh G_
India India
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5memberliam.lee25 Apr '13 - 16:37 
very good, thanks for your share!
GeneralRe: My vote of 5memberSanthosh G_26 Apr '13 - 4:15 
Thank you Smile | :)
QuestionOpenCLmemberFredWah9 Nov '12 - 7:32 
This looks excellent. In addition, it appears to be a good starting project for anyone who wants to create an OpenCl version
GeneralMy vote of 5membernefu_boy23 May '12 - 15:00 
The article explain the theory in a simply way.
GeneralRe: My vote of 5memberImABeginner24 Oct '12 - 17:49 
Thanks..
QuestionHow does Pixel Shader choose the Edge Points?memberMember 899307221 May '12 - 19:58 
I'm new on Digital Image Processing.When I read you article, I think your program works like this.After sobel operator to an image, Pixel Shader chooses the Edge Points and renders them.I want to know how to choose the Edge Points and what characters they fit.
I also hope you can recommend some books that you have read to me about Digital Image Procesing to me.
 
By the way, I'm a Chinese and my English is just so so.I hope your message.
Thanks.
AnswerRe: How does Pixel Shader choose the Edge Points?memberSanthosh_G23 May '12 - 7:33 
This application prepares a cartoon effect of an image by combining the edge points and source image. Its explained in "Cartoon Effect" implementation section.
 
The edge points are created by calculating the gradient in X direction and Y direction.
It just identifeis the difference of image in X direction and in Y direction. Then these differnces are combined to prepare final edge image.
Details are in "X direction gradient calculation", "Y direction gradient calculation", and "Final Image Calculation".
 
I'm also a beginner in Digital Image Processing, just started reading "Digital Image Processing", by Prentice Hall.
GeneralRe: How does Pixel Shader choose the Edge Points?membernefu_boy23 May '12 - 15:31 
Thanks for your reply!
You gave me a good answer.I don't think that I read your article carefully, so I shall read it again.Is the book that you suggest written by Rafael C. Gonzalez? Many articles refer that book.
Now, I think have another question that is similar to Mick Leong whom posted "Digital output". I want to extract coordinates of edge points, but I don't want objects like vector lines, circles and so on. Can you give me some suggestions? And I will explore the "Hough transform" to try to find something that I can utilize.
I will wait for your message.Thanks.It takes me about 1 hour to write this reply! Laugh | :laugh:
QuestionYour Machine not supports Opengls GL_ARB_fragment_shadermemberMember 775469514 Mar '11 - 20:56 
hi.
im new to openGL programing. found dis particualr proj on net & it was interesting so thought of workin on it, but when i tried to run the pgm building was fine. but during execussion i got a set of error as
1. Your Machine not supports Opengls GL_ARB_fragment_shader.
2. Your Machine not supports Opengls GL_ARB_vertex_shader.
3. wglGetProc failed for glCreateProgramObjectARB.
 
my system configuration is.
intel core2 duo.
windows 7 OS.
VB08.
 
is there any specific header files im suppose to include in vb.
AnswerRe: Your Machine not supports Opengls GL_ARB_fragment_shader [modified]membersanthosh4gCode22 Mar '11 - 7:13 
Hi,
 
If your machine not have a graphics card, the above errors will happen.
GL_ARB_fragment_shader, and GL_ARB_vertex_shader are opengl extensions for
pixel shader and vertex shader.
 
I hope still you can view the output with cpu version of Edgedetection application.

modified 16 Feb '12 - 10:28.

GeneralMy vote of 4memberMick Leong3 Mar '11 - 18:58 
Good article. Easy to follow. Demo program works ok compared to many other demos which does breaks on compile.
GeneralDigital outputmemberMick Leong1 Aug '10 - 21:13 
I have came across many articles on sobel, canny, laplace edge detectors - all seems to stop at the resulting convoluted image. I have not come across any article going to the next step. How to "best" extract the edges as line vectors (better still arcs, splines). It is easy for horizontal and vertical edges but oblique edges? You get 5 anyway.
GeneralRe: Digital outputmembersanthosh4gCode14 Aug '10 - 22:59 
Hi Mick,
Thanks for your vote of +5.
 
How to "best" extract the edges as line vectors (better still arcs, splines) ?
You need the edges as a collection of lines, right ?
I dont know the exact way to convert edges as lines.
It may be possible to convert edges as lines, by some processing on edge image.
AnswerRe: Digital outputmemberAttila Kúr19 Aug '10 - 9:38 
Mick, one way to detect vector lines / circles / arcs in an edge-detected image is to use Hough transform. However, you also need to pre-process that edge-detected image by denoising it first, in order to achieve better results.
GeneralRe: Digital outputmemberMick Leong22 Aug '10 - 20:23 
Thanks Attila
I am aware of various edge detection methods - canny, laplace, hough.... BUT thats not my problem - my problem is that all edge detectors software leaves the output in image pixels - I need an efficient method to trace the pixels and output as vectors (preferable two endpoints denoting the line vector - line could be short or long lines), I managed to trace horizontal and vertical lines easily - but its those slanted (aka diagonal lines that gives me a headache). Thanks
GeneralRe: Digital outputmemberAttila Kúr23 Aug '10 - 12:05 
That's exactly the point, Mick. Hough transform is not an edge detection technique - actually it's a "feature extraction technique". It takes the output of some edge detection technique (e.g. Sobel) as its input, but its output is a set of objects (e.g. arbitrarily rotated lines).
 
It's not an "edge detector" with an output in image pixels, but an "object detector" with an output of vectors (lines, arcs, circles).
Input: pixels, Output: vectors
GeneralRe: Digital outputmemberMick Leong24 Aug '10 - 23:53 
Attila
Thanks. I might have misunderstood the articles i have read. I shall re-read hough transform...
Many thanks
GeneralMy vote of 5memberMick Leong1 Aug '10 - 21:08 
Well written article.clear explanations.
QuestionYou like chinese ?memberAric Green28 Jul '10 - 15:55 
The up picture is "happy" and "luck" meanings.
I am not a genius, but shed more sweat!

AnswerRe: You like chinese ?membersanthosh4gCode28 Jul '10 - 23:32 
Now im studying japaneese, and I searched for Kanji letter of Happiness, and got this image.
In malayalam, meaning of Santhosh is similiar to Happiness.
AnswerRe: You like chinese ?memberMember 899307221 May '12 - 19:05 
I'm sorry, I wanted to click the number 5, but I clicked the wrong number. WTF | :WTF:
GeneralFile link is incorrectmemberAvis p28 Jul '10 - 0:59 
The source link should be http://www.codeproject.com/KB/openGL/EdgeDetection/EdgeDetection_source.zip[^]
 
Thankes for a great article though!
GeneralRe: File link is incorrectmembersanthosh4gCode28 Jul '10 - 2:31 
Hi Avis,
Corrected it, sorry for this mistake.
Thanks.
GeneralShader Creation Failedmemberkware27 Jul '10 - 4:16 
looks very interesting. this is something I've been looking for, for a while.
 
but I got the error message "Shader Creation Failed". is there a simple explanation of what I might be missing or doing wrong? I'm running on a 64 bit Windows 7 machine, Visual Studio 2008, and I've never used OpenGL before.
 
also, I tried to load a bitmap and saw that I need 24 bit bitmap files. would you know how I can make those or get them?
AnswerRe: Shader Creation Failedmembersanthosh4gCode27 Jul '10 - 19:31 
but I got the error message "Shader Creation Failed".
Possibly this is due to your machine not support opengl shading language. Then EdgeDetecion works in CPU mode.
If shader supports you can check CPU and GPU outputs.

 
is there a simple explanation of what I might be missing or doing wrong?

New class AppError is added to handle this situation. New source will display exact error message on shader creation failed.

 
I tried to load a bitmap and saw that I need 24 bit bitmap files. would you know how I can make those or get them?
Since BMPLoader class handles 24 bit bitmap, we have to create 24 bit bmp to use EdgeDetection.
U can simply use mspaint for saving 24 bit bmp. Select "SaveAs" and choose save as type 24 bit Bitmap.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 19 Aug 2010
Article Copyright 2010 by Santhosh G_
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid