Gå til innhold

Problem med å loade .tga-filer


Anbefalte innlegg

Hei!

 

Nå har det seg sånn at jeg har prøvd meg på å loade .tga-filer i OpenGL. Klassen jeg har brukte skulle ha fungert helt fint, men det gjør den altså ikke...

 

Poster den aktuelle delen av koden her:

 

LoadTarga.h

#ifndef __TARGA_LIB
#define __TARGA_LIB

enum TGAtypes
{
  TGA_NODATA        = 0,
  TGA_INDEXED       = 1,
  TGA_RGB           = 2,
  TGA_GRAYSCALE     = 3,
  TGA_INDEXED_RLE   = 9,
  TGA_RGB_RLE       = 10,
  TGA_GRAYSCALE_RLE = 11
};

// Image Data Formats:
#define IMAGE_RGB       0
#define IMAGE_RGBA      1
#define IMAGE_LUMINANCE 2

// Image Data Types:
#define IMAGE_DATA_UNSIGNED_BYTE 0

// Pixel Data transfer from file to screen:
#define BOTTOM_LEFT  0x00
#define BOTTOM_RIGHT 0x10
#define TOP_LEFT     0x20
#define TOP_RIGHT    0x30

// Class LoadTarga:
struct tgaheader_t
{
  unsigned char  idLength;
  unsigned char  colorMapType;
  unsigned char  imageTypeCode;
  unsigned char  colorMapSpec[5];
  unsigned short xOrigin;
  unsigned short yOrigin;
  unsigned short width;
  unsigned short height;
  unsigned char  bpp;
  unsigned char  imageDesc;
};

struct rgba_t
{
  unsigned char r;
  unsigned char g;
  unsigned char b;
  unsigned char a;
};

struct rgb_t
{
  unsigned char r;
  unsigned char g;
  unsigned char b;
};

class LoadTarga
{
private:
  unsigned char  m_colorDepth;
  unsigned char  m_imageDataType;
  unsigned char  m_imageDataFormat;
  unsigned char *m_pImageData;
  unsigned short m_width;
  unsigned short m_height;
  unsigned long  m_imageSize;

// Change from BGR to RGB: (the *.tga format saves pixel color data as BGR)
  void SwapRedBlue();

public:
// Constructor and destructor:
  LoadTarga();
  virtual ~LoadTarga();

// Loading and unloading:
  bool Load( const char *filename );
  void Release();

// Flip image vertilcally:
  bool FlipVertical();

// Get image width, height, and pixel format:
  unsigned short GetWidth()  { return m_width; }
  unsigned short GetHeight() { return m_height; }
  unsigned char GetImageFormat() { return m_imageDataFormat; }

// Converts RGB to RGBA and vice versa:
  bool ConvertRGBAtoRGB();
  bool ConvertRGBtoRGBA( unsigned char alphaValue );

// Returns the current image data:
  unsigned char *GetImage() { return m_pImageData; }
};

#endif

 

LoadTarga.cpp:

#include <iostream>
#include "LoadTarga.h"

LoadTarga::LoadTarga() : m_pImageData(NULL)
{
}

LoadTarga::~LoadTarga()
{
  Release();
}

void LoadTarga::SwapRedBlue()
{
  switch ( m_colorDepth )
  {
     case 32:
        {
           unsigned char temp;
           rgba_t* source = (rgba_t*)m_pImageData;

           for ( int pixel = 0; pixel < ( m_width * m_height ); ++pixel)
           {
              temp = source[pixel].b;
              source[pixel].b = source[pixel].r;
              source[pixel].r = temp;
           }
        } break;

     case 24:
        {
           unsigned char temp;
           rgb_t* source = (rgb_t*)m_pImageData;

           for ( int pixel = 0; pixel < ( m_width * m_height ); ++pixel )
           {
              temp = source[pixel].b;
              source[pixel].b = source[pixel].r;
              source[pixel].r = temp;
           }
        } break;

     default:
     // Ignore all other color debths:
        break;
  }
}

bool LoadTarga::Load( const char *filename )
{
  FILE *pFile = fopen( filename, "rb" );

  if (!pFile)
     return false;

  tgaheader_t tgaHeader;

// Read the TGA header:
  fread( &tgaHeader, 1, sizeof(tgaheader_t), pFile );

// Check if the image type is supported: ( RGB, RGB RLE, GRAYSCALE, and GRAYSCALE RLE )
  if ( (( tgaHeader.imageTypeCode != TGA_RGB ) && ( tgaHeader.imageTypeCode != TGA_GRAYSCALE ) && ( tgaHeader.imageTypeCode != TGA_RGB_RLE ) && ( tgaHeader.imageTypeCode != TGA_GRAYSCALE_RLE )) || tgaHeader.colorMapType != 0 )
  {
     fclose(pFile);
     return false;
  }

// Get the width and height of the image:
  m_width = tgaHeader.width;
  m_height = tgaHeader.width;

/* colorMode = 3 = BGR  (RGB)
              4 = BGRA (RGBA) */
  int colorMode = tgaHeader.bpp / 8;

// Program won't load less than 24 bit:
  if ( colorMode < 3 )
  {
     fclose(pFile);
     return false;
  }

  m_imageSize = m_width * m_height * colorMode;

// Allocate memory for the image data:
  m_pImageData = new unsigned char[m_imageSize];

// Skip past image ID: ( if there is one )
  if ( tgaHeader.idLength < 0 )
     fseek ( pFile, SEEK_CUR, tgaHeader.idLength );

// Read image data:
  if ( tgaHeader.imageTypeCode == TGA_RGB || tgaHeader.imageTypeCode == TGA_GRAYSCALE )
  {
     fread ( m_pImageData, 1, m_imageSize,pFile);
  }

  else
  {
  // This is an RLE compressed image:
     unsigned char id;
     unsigned char length;
     rgba_t color = { 0, 0, 0, 0 };
     unsigned int i = 0;

     while ( i < m_imageSize )
     {
        id = fgetc(pFile);

     // See if this is run length data:
        if ( id >= 128 )
        {
        // Find the run length:
           length = (unsigned char)(id - 127);

        // Next 3 bytes are repeated values: ( 4 bytes if it is 32 bit TGA )
           color.b = (unsigned char)fgetc(pFile);
           color.g = (unsigned char)fgetc(pFile);
           color.r = (unsigned char)fgetc(pFile);

           if ( colorMode == 4 )
              color.a = (unsigned char)fgetc(pFile);

        // Save everything in this run:
           while ( length > 0 )
           {
              m_pImageData[i++] = color.b;
              m_pImageData[i++] = color.g;
              m_pImageData[i++] = color.r;

              if ( colorMode == 4 )
                 m_pImageData[i++] = color.a;

              --length;
           }
        }

        else
        {
        // the number of non RLE pixels:
           length = (unsigned char)(id + 1);

           while ( length > 0 )
           {
              color.b = (unsigned char)fgetc(pFile);
              color.g = (unsigned char)fgetc(pFile);
              color.r = (unsigned char)fgetc(pFile);

              if ( colorMode == 4 )
                 color.a = (unsigned char)fgetc(pFile);

              m_pImageData[i++] = color.b;
              m_pImageData[i++] = color.g;
              m_pImageData[i++] = color.r;

              if ( colorMode == 4 )
                 m_pImageData[i++] = color.a;

              --length;
           }
        }
     }
  }


  fclose(pFile);

  switch ( tgaHeader.imageTypeCode )
  {
     case TGA_RGB:
     case TGA_RGB_RLE:
        if ( 3 == colorMode )
        {
           m_imageDataFormat = IMAGE_RGB;
           m_imageDataType = IMAGE_DATA_UNSIGNED_BYTE;
           m_colorDepth = 24;
        }

        else
        {
           m_imageDataFormat = IMAGE_RGBA;
           m_imageDataType = IMAGE_DATA_UNSIGNED_BYTE;
           m_colorDepth = 32;
        }
        break;

     case TGA_GRAYSCALE:
     case TGA_GRAYSCALE_RLE:
        m_imageDataFormat = IMAGE_LUMINANCE;
        m_imageDataType = IMAGE_DATA_UNSIGNED_BYTE;
        m_colorDepth = 8;
        break;
  }

  if ( (tgaHeader.imageDesc & TOP_LEFT) == TOP_LEFT )
     FlipVertical();

// Swap the red and blue components of the image:
  SwapRedBlue();

  return ( m_pImageData != NULL );
}

bool LoadTarga::FlipVertical()
{
  if (!m_pImageData)
     return false;

  if (m_colorDepth == 32)
  {
     rgba_t* tmpBits = new rgba_t[m_width];
     if (!tmpBits)
        return false;

     int lineWidth = m_width * 4;

     rgba_t* top = (rgba_t*)m_pImageData;
     rgba_t* bottom = (rgba_t*)(m_pImageData + lineWidth*(m_height-1));

     for ( int i = 0; 1 < (m_height / 2 ); ++i )
     {
        memcpy ( tmpBits, top, lineWidth );
        memcpy ( top, bottom, lineWidth );
        memcpy ( bottom, tmpBits, lineWidth );

        top = (rgba_t*)((unsigned char*)top + lineWidth);
        bottom = (rgba_t*)((unsigned char*)bottom - lineWidth);
     }

     delete [] tmpBits;
     tmpBits = 0;
  }

  else if ( m_colorDepth == 24 )
  {
     rgb_t* tmpBits = new rgb_t[m_width];
     if (!tmpBits)
        return false;

     int lineWidth = m_width * 3;

     rgb_t* top = (rgb_t*)m_pImageData;
     rgb_t* bottom = (rgb_t*)(m_pImageData + lineWidth*(m_height-1));

     for ( int i = 0; 1 < (m_height / 2 ); ++i )
     {
        memcpy ( tmpBits, top, lineWidth );
        memcpy ( top, bottom, lineWidth );
        memcpy ( bottom, tmpBits, lineWidth );

        top = (rgb_t*)((unsigned char*)top + lineWidth);
        bottom  = (rgb_t*)((unsigned char*)bottom - lineWidth);
     }

     delete [] tmpBits;
     tmpBits = 0;
  }

  return true;
}

void LoadTarga::Release()
{
  delete [] m_pImageData;
  m_pImageData = NULL;
}

bool LoadTarga::ConvertRGBtoRGBA( unsigned char alphaValue )
{
  if ( (m_colorDepth == 24) && (m_imageDataFormat == IMAGE_RGB) )
  {
     rgba_t *newImage = new rgba_t[m_width * m_height];

     if (!newImage)
        return false;

     rgba_t *dest = newImage;
     rgb_t *src = (rgb_t*)m_pImageData;

     for ( int x = 0; x < m_height; x++ )
     {
        for ( int y = 0; y < m_width; y++ )
        {
           dest->r = src->r;
           dest->g = src->g;
           dest->b = src->b;
           dest->a = alphaValue;

           ++src;
           ++dest;
        }
     }

     delete [] m_pImageData;
     m_pImageData = (unsigned char*)newImage;

     m_colorDepth = 32;
     m_imageDataType = IMAGE_DATA_UNSIGNED_BYTE;
     m_imageDataFormat = IMAGE_RGBA;

     return true;
  }

  return false;
}

bool LoadTarga::ConvertRGBAtoRGB()
{
  if ( (m_colorDepth == 32) && (m_imageDataFormat == IMAGE_RGBA) )
  {
     rgb_t *newImage = new rgb_t[m_width * m_height];

     if (!newImage)
        return false;

     rgb_t *dest = newImage;
     rgba_t *src = (rgba_t*)m_pImageData;

     for ( int x = 0; x < m_height; x++ )
     {
        for ( int y = 0; y < m_width; y++ )
        {
           dest->r = src->r;
           dest->g = src->g;
           dest->b = src->b;

           ++src;
           ++dest;
        }
     }

     delete [] m_pImageData;
     m_pImageData = (unsigned char*)newImage;

     m_colorDepth = 24;
     m_imageDataType = IMAGE_DATA_UNSIGNED_BYTE;
     m_imageDataFormat = IMAGE_RGB;

     return true;
  }

  return false;
}

 

Render.h:

#include <iostream>
#include <windows.h>

#include "LoadTarga.h"

// Class 'Graphics':
class Graphics
{
  private:
     LoadTarga *m_tga;

  public:
     bool Init();
     bool Shutdown();
     void Render();
};

bool Graphics::Init()
{
  m_tga = new LoadTarga;

  if ( !m_tga->Load("picture.tga") )
     return false;

  return true;
}

bool Graphics::Shutdown()
{
  m_tga->Release();
  delete m_tga;

  return true;
}

void Graphics::Render()
{
  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  glMatrixMode( GL_MODELVIEW )
  glLoadIdentity;

  glRasterPos2i( 100, 100 );
  glDrawPixels( (int)(m_tga->GetWidth()), (int)(m_tga->GetHeight()), GL_RGB, GL_UNSIGNED_BYTE, m_tga->GetImage() );
}

 

Det meste (om ikke alt) i LoadTarga.h og LoadTarga.cpp kommer fra boken 'Beginning OpenGL Game Programming', og burde som sagt ha fungert. Hadde blitt riktig takknemlig hvis noen kunne sett gjennom koden min og funnet ut hva som kan være feil.

 

P.S: Programmet kjører helt fint, problemet er at bildet jeg loader ikke vises på skjermen...

 

Miromurr

Lenke til kommentar
Videoannonse
Annonse

Vel, tar jeg ikke helt feil, så vil glRasterPos oppføre seg som en vanlig vertex.

 

Skal du tegne, burde du passe på at koordinatene vil dukke opp innenfor tegnevinduet ditt.

 

Prøv å kall glRasterPos2i(0, 0) eventuelt sett opp en projection matrix som inneholder (100, 100) ved å bruke glOrtho funksjonen.

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...