GLProgramming.com

home :: about :: development guides :: irc :: forums :: search :: paste :: links :: contribute :: code dump

-> Click here to learn how to get live help <-


New Paste :: Recent Pastes:: Add Line Numbers


XeX by Paronator
#include <windows.h>
#include <stdio.h>
#include <math.h>

int m_nWidth, m_nHeight;

typedef struct __TGAHeader
{
    unsigned char m_cLength;
    unsigned char m_cType;
    unsigned char m_cImageType;
    unsigned char m_cSize;
    unsigned char m_cDepth;
    unsigned char m_cDesc;
    unsigned short m_wIndex;
    unsigned short m_wCnt;
    unsigned short m_wHoriz;
    unsigned short m_wVert;
    unsigned short m_wWidth;
    unsigned short m_wHeight;
}TGAHeader;

typedef struct __Pixel { unsigned char m_cR,m_cG,m_cB,m_cA; }Pixel;
void WritePixel(Pixel* Image,Pixel* Pix,int x, int y){ *(Image + m_nWidth * y + x)= *Pix;}
void ReadPixel(Pixel* Image,Pixel* Pix,int x, int y){ *Pix = *(Image + m_nWidth * y + x);}
unsigned char PackFloatInUChar(float in){ return (unsigned char) ((in + 1.0f) / 2.0f * 255.0f);}

#define IFileName "Texture.tga"
#define OFileName "TextureDot3.tga"

void Error(const char* msg,...){
    char Buffer[4096];
    va_list ap;
    va_start(ap,msg);
    vsprintf(Buffer,msg,ap);
    va_end(ap);

    MessageBox(HWND_DESKTOP,Buffer,"TgaToNrm",MB_ICONERROR);
}

int main(){
    TGAHeader Header;
    FILE* IFile, *OFile;
    unsigned long dwBytesRead;
    unsigned char* pDescBytes;
    Pixel Pix, *SrcImage, *DstImage;
    float fNX, fNY, fNZ, fDX, fDY, fLN;

    printf("Converts TGA image to normal map\n\n");

    IFile = fopen(IFileName,"rb");
    OFile = fopen(OFileName,"wb");

    if(IFile == NULL){Error("Input file \"%s\" unable to open!",IFileName);  return FALSE; }
    if(OFile == NULL){Error("Output file \"%s\" unable to open!",OFileName); return FALSE; }

    dwBytesRead = (unsigned long)fread(&Header,sizeof(unsigned char),sizeof(Header),IFile);
    dwBytesRead = (unsigned long)fwrite(&Header,sizeof(unsigned char),sizeof(Header),OFile);
    pDescBytes  = (unsigned char*)malloc(sizeof(unsigned char) * Header.m_cLength);
    dwBytesRead = (unsigned long)fread(pDescBytes,sizeof(unsigned char),Header.m_cLength,IFile);
    dwBytesRead = (unsigned long)fwrite(pDescBytes,sizeof(unsigned char),Header.m_cLength,OFile);
    m_nWidth    = Header.m_wWidth;
    m_nHeight   = m_nWidth;
    SrcImage    = (Pixel*)malloc(sizeof(Pixel) * m_nHeight * m_nWidth);
    DstImage    = (Pixel*)malloc(sizeof(Pixel) * m_nHeight * m_nWidth);

    printf("--- Image loaded: %s(%ix%i)\n",IFileName,m_nWidth,m_nHeight);

    for(int y = 0; y < m_nHeight; y ++){
        for(int x = 0; x < m_nWidth; x ++){
            fread(&Pix.m_cB,sizeof(unsigned char),1,IFile);
            fread(&Pix.m_cG,sizeof(unsigned char),1,IFile);
            fread(&Pix.m_cR,sizeof(unsigned char),1,IFile);

            if(Header.m_cDepth == 32)
                fread(&Pix.m_cA,sizeof(unsigned char),1,IFile);
            else
                Pix.m_cA = 0xCC;

            WritePixel(SrcImage,&Pix,x,y);
        }
    }

    for(int y = 0; y < m_nHeight; y ++){
        for(int x = 0; x < m_nWidth; x ++){
            // Y Sobel
            ReadPixel(SrcImage,&Pix,(x - 1 + m_nWidth) % m_nWidth,(y + 1) % m_nHeight);
            fDY = ((float)Pix.m_cR) / 255.0f * (-1.0f);

            ReadPixel(SrcImage,&Pix,x % m_nWidth,(y + 1) % m_nHeight);
            fDY += ((float)Pix.m_cR) / 255.0f * (-2.0f);

            ReadPixel(SrcImage,&Pix,(x + 1) % m_nWidth,(y + 1) % m_nHeight);
            fDY += ((float)Pix.m_cR) / 255.0f * (-1.0f);

            ReadPixel(SrcImage,&Pix,(x - 1 + m_nWidth) % m_nWidth,(y - 1 + m_nHeight) % m_nHeight);
            fDY += ((float)Pix.m_cR) / 255.0f * 1.0f;

            ReadPixel(SrcImage,&Pix,x % m_nWidth,(y - 1 + m_nHeight) % m_nHeight);
            fDY += ((float)Pix.m_cR) / 255.0f * 2.0f;

            ReadPixel(SrcImage,&Pix,(x + 1) % m_nWidth,(y - 1 + m_nHeight) % m_nHeight);
            fDY += ((float)Pix.m_cR) / 255.0f * 1.0f;

            // X Sobel
            ReadPixel(SrcImage,&Pix,(x - 1 + m_nWidth) % m_nWidth,(y - 1 + m_nHeight) % m_nHeight);
            fDX = ((float)Pix.m_cR) / 255.0f * (-1.0f);

            ReadPixel(SrcImage,&Pix,(x - 1 + m_nWidth) % m_nWidth,y % m_nHeight);
            fDX += ((float)Pix.m_cR) / 255.0f * (-2.0f);

            ReadPixel(SrcImage,&Pix,(x - 1 + m_nWidth) % m_nWidth,(y + 1) % m_nHeight);
            fDX += ((float)Pix.m_cR) / 255.0f * (-1.0f);

            ReadPixel(SrcImage,&Pix,(x + 1) % m_nWidth,(y - 1 + m_nHeight) % m_nHeight);
            fDX += ((float)Pix.m_cR) / 255.0f * 1.0f;

            ReadPixel(SrcImage,&Pix,(x + 1) % m_nWidth,y % m_nHeight);
            fDX += ((float)Pix.m_cR) / 255.0f * 2.0f;

            ReadPixel(SrcImage,&Pix,(x + 1) % m_nWidth,(y + 1) % m_nHeight);
            fDX += ((float)Pix.m_cR) / 255.0f * 1.0f;

            fNX = -fDX;
            fNY = -fDY;
            fNZ = 1.0f;
            fLN = 1.0f / (sqrtf(fNX * fNX + fNY * fNY + fNZ * fNZ));
            fNX *= fLN;
            fNY *= fLN;
            fNZ *= fLN;

            Pix.m_cR = PackFloatInUChar(fNX);
            Pix.m_cG = PackFloatInUChar(fNY);
            Pix.m_cB = PackFloatInUChar(fNZ);

            WritePixel(DstImage,&Pix,x,y);
        }
    }

    for(int y = 0; y < m_nHeight; y ++){
        for(int x = 0; x < m_nWidth; x ++){
            ReadPixel(DstImage,&Pix,x,y);

            fwrite(&Pix.m_cB,sizeof(unsigned char),1,OFile);
            fwrite(&Pix.m_cG,sizeof(unsigned char),1,OFile);
            fwrite(&Pix.m_cR,sizeof(unsigned char),1,OFile);

            if(Header.m_cDepth == 32)
                fwrite(&Pix.m_cA,sizeof(unsigned char),1,OFile);
        }
    }
    printf("--- Image saved: %s(%ix%i)\n\n",OFileName,m_nWidth,m_nHeight);

    free(SrcImage);
    free(DstImage);
    free(pDescBytes);

    fclose(IFile);
    fclose(OFile);

    MSG msg;
    ZeroMemory(&msg,sizeof(MSG));

    while(msg.message != WM_QUIT){
        if(PeekMessage(&msg,NULL,0U,0U,PM_NOREMOVE)){
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return TRUE;
}