gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > Help! More TGA - UNSOLVED

#135877 - yellowstar - Thu Jul 26, 2007 10:50 pm

I need some help with loading TGA graphics,
with transparency(alpha).

The way I am doing it won't work.

EDIT:
This problem is solved.
But I have more questions.
See this post in this topic for details.

But I am having more problems, this time
with saving TGAs of captures of the screen(s).
See the above link for details.


<EDIT>

When I first posted this,
I forgot to post what my
problem was.

Here is my problem:

The converted TGA image,
looks nothing like
the TGA graphic.

Also,
It is transparent in
the wrong places.

NOTE:
This above is not the problem
I am having right now,
but it is similar.

See my below posts for details.

</EDIT>



<EDIT2>

I now have a image host.
This means I have posted links to these images.
Go to this post for details.

</EDIT2>

Here's how I am doing it:

The last piece of code is the whole thing,
and the ones before that are
important pieces of code.


Here is the function that loads the TGA graphic:
(The function that generates the texture from
the converted data is at the end of this piece of code.)
(The structs are at the top of the main piece of code,
and the code that does the drawing is at the bottom.)
Code:

bool loadTGA(u8 *DATA, TGAimage *tgaimage, int *texID)
{
   int i;
   unsigned int temp;
   BYTE *stream = NULL;

   if(DATA==NULL){Error("Attempted to loaded null data!",-1);}

   stream = DATA;

    tgaimage->texID = texID;



    tgaimage->header.ID_Length = *stream;stream++;
    tgaimage->header.colorMapType = *stream;stream++;
    tgaimage->header.imageType = *stream;stream++;
   
    for(int a = 0; a < 5; a++)
    {
    tgaimage->header.ColorMapSpecification[a] = *stream;stream++;
    }
   
    SCpy(stream,&tgaimage->header.xOrigin);stream+=2;
    SCpy(stream,&tgaimage->header.yOrigin);stream+=2;
    SCpy(stream,&tgaimage->header.imageWidth);stream+=2;
    SCpy(stream,&tgaimage->header.imageHeight);stream+=2;
   
    tgaimage->header.pixelDepth = *stream;stream++;

   if(tgaimage->header.imageType !=2){
      char str[256];
      strcpy(str,"");
      sprintf(str,"%s\nSupported Type: Uncompressed, RGB, with orgin at top-left.(2)\nType: %d","Unsuported TGA type.",(int)tgaimage->header.imageType);
      Error(str,-2);
      
   }

   tgaimage->width = tgaimage->header.imageWidth;
   tgaimage->height = tgaimage->header.imageHeight;
   tgaimage->bpp = tgaimage->header.pixelDepth;

   if (tgaimage->width <= 0 || tgaimage->height <= 0 || (tgaimage->bpp!=24 && tgaimage->bpp!=32)){
      printf("Width: %d\nHeight: %d\n BPP: %d\n",(int)tgaimage->width,(int)tgaimage->height,(int)tgaimage->bpp);
      Error("Wrong file type.",-3);
        }

   unsigned int bytesPerPixel = tgaimage->bpp / 8;
   unsigned int imageSize = ((tgaimage->width * tgaimage->height) * bytesPerPixel);
   
   tgaimage->type = GL_RGBA;

   if(tgaimage->bpp==24)
   {
      tgaimage->type = GL_RGB;printf("RGB\n");
    }
    else
    {
        printf("RGBA\n");
    }

    if(tgaimage->header.colorMapType!=0)
    {
    Error("Color Map Data detected! Stopping...",-4);
    }
   
    tgaimage->imageData = (BYTE*)malloc((size_t)((int)imageSize));
   
    if(tgaimage->imageData==NULL)
    {
   
    Error("Failed to alloc memory for TGA data!",-5);
    }

    for(int I = 0; I < (int)imageSize; I++)
    {
    tgaimage->imageData[I] = *stream;
    stream++;
    }

   printf("Image data\n\n");
   
   //Convert BGR to RGB
   /*for (i =0; i <(int)imageSize; i+=(int)bytesPerPixel)
   {
      
      temp = tgaimage->imageData[i];
      tgaimage->imageData[i] = tgaimage->imageData[i+2];
      tgaimage->imageData[i+2] = temp;
   }*/

   tgaimage->image = (u16*)malloc(sizeof(u16)*(tgaimage->width*tgaimage->height));
int I = 0;
   for(int i=0; i < (int)(tgaimage->width*tgaimage->height); i++)
   {

         tgaimage->image[i] = RGB8((tgaimage->imageData[I + 0]),
            (tgaimage->imageData[I + 1]),
            (tgaimage->imageData[I + 2])) | BIT(15);
   
   I+=bytesPerPixel;

   }

   createTexture(tgaimage);

   printf("Success...\n\n");

   return 1;
}


bool createTexture(TGAimage *tgaimage)
{
   glGenTextures(1,tgaimage->texID);
   glBindTexture(GL_TEXTURE_2D, *tgaimage->texID);

   //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    //GL_UNSIGNED_BYTE
   
   glTexImage2D(*tgaimage->texID, 0, GL_RGB, TEXTURE_SIZE_32, TEXTURE_SIZE_32,0, TEXGEN_TEXCOORD, (uint8*)tgaimage->image);

   return true;
}



The following is the whole thing:
Code:

// include your ndslib
#include <nds.h>
#include <malloc.h>
//needed to load pcx files
#include <nds/arm9/image.h>

#include "Pencil_0_tga.h"
#include "APencil_0_tga.h"
/*#include "Pencil_1_tga.h"
#include "Pencil_2_tga.h"
#include "Pencil_3_tga.h"
#include "Pencil_4_tga.h"
#include "Pencil_5_tga.h"
*/


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define Error(message, code) printf("ERROR: %s\n",message);return code;

typedef unsigned char BYTE;



struct TGA_header
{
   BYTE ID_Length;
   BYTE colorMapType;
   BYTE imageType;
   BYTE ColorMapSpecification[5];
   short xOrigin;
   short yOrigin;
   short imageWidth;
   short imageHeight;
   BYTE pixelDepth;
   BYTE ImageDesc;
};

struct TGAimage
{
TGA_header header;
BYTE *imageData;
unsigned int bpp;
unsigned int width;
unsigned int height;
int *texID;
unsigned int type;
u16 *image;
};

bool createTexture(TGAimage *tgaimage);
bool loadTGA(char *texFileName);

int DrawGLScene();

float   xrot;            // X Rotation
float   yrot;            // Y Rotation
float   zrot;            // Z Rotation

int   texture[1];         // Storage For One Texture
TGAimage image;
int result=0;

void SCpy(BYTE *source, short *target)
{
     for(int i = 0; i < (int)sizeof(short); i++)
     target[i] = source[i];
}

void WaitForKey(KEYPAD_BITS key)
{
     if(key != KEY_TOUCH && key != KEY_LID)
     printf("Press ");
     
     
     
     if(key == KEY_LID)
     printf("Close the ");
     
     
     
     switch(key)
     {
                case KEY_A:printf("A");break;
                case KEY_B:printf("B");break;
                case KEY_SELECT:printf("SELECT");break;
                case KEY_START:printf("START");break;
                case KEY_RIGHT:printf("RIGHT");break;
                case KEY_LEFT:printf("LEFT");break;
                case KEY_UP:printf("UP");break;
                case KEY_DOWN:printf("DOWN");break;
                case KEY_R:printf("R");break;
                case KEY_L:printf("L");break;
                case KEY_X:printf("X");break;
                case KEY_Y:printf("Y");break;
                case KEY_TOUCH:printf("TOUCH");break;
                case KEY_LID:printf("LID");break;
     }
     printf(" To Continue...\n\n");
     swiWaitForVBlank();swiWaitForVBlank();swiWaitForVBlank();
     while(1)
     {
         scanKeys();
             if(keysDown() & key)break;
             
             swiWaitForVBlank();
     }
     
     consoleClear();
}

void WaitForAnyKey()
{
     bool found = false;
     printf("\nPress Any Key to continue...\n\n");
    swiWaitForVBlank();swiWaitForVBlank();swiWaitForVBlank();
     while(1)
     {
    scanKeys();
             for(int i = 0; i <= 12; i++)
             {
                     if(keysDown() & BIT(i)){found = true;break;}
                     
                     
             }
             
             if(found)break;
             
             swiWaitForVBlank();
     }
     
     consoleClear();
}

void DisplayPix(TGAimage *tgaimage, int X, int Y, bool pause)
{

int the_index = ( ( (int)tgaimage->width * (Y - 1) ) + (X - 1)) * (int)tgaimage->bpp;

   printf("Pix %d,%d =\nR = %d\nG = %d\nB = %d\n\n",(int)X,(int)Y,
   (int)tgaimage->imageData[the_index + 0],(int)tgaimage->imageData[the_index + 1],
   (int)tgaimage->imageData[the_index + 2]);

WaitForAnyKey();

}

bool loadTGA(u8 *DATA, TGAimage *tgaimage, int *texID)
{
   int i;
   unsigned int temp;
   BYTE *stream = NULL;

   if(DATA==NULL){Error("Attempted to loaded null data!",-1);}

   stream = DATA;

    tgaimage->texID = texID;



    tgaimage->header.ID_Length = *stream;stream++;
    tgaimage->header.colorMapType = *stream;stream++;
    tgaimage->header.imageType = *stream;stream++;
   
    for(int a = 0; a < 5; a++)
    {
    tgaimage->header.ColorMapSpecification[a] = *stream;stream++;
    }
   
    SCpy(stream,&tgaimage->header.xOrigin);stream+=2;
    SCpy(stream,&tgaimage->header.yOrigin);stream+=2;
    SCpy(stream,&tgaimage->header.imageWidth);stream+=2;
    SCpy(stream,&tgaimage->header.imageHeight);stream+=2;
   
    tgaimage->header.pixelDepth = *stream;stream++;

   if(tgaimage->header.imageType !=2){
      char str[256];
      strcpy(str,"");
      sprintf(str,"%s\nSupported Type: Uncompressed, RGB, with orgin at top-left.(2)\nType: %d","Unsuported TGA type.",(int)tgaimage->header.imageType);
      Error(str,-2);
      
   }

   tgaimage->width = tgaimage->header.imageWidth;
   tgaimage->height = tgaimage->header.imageHeight;
   tgaimage->bpp = tgaimage->header.pixelDepth;

   if (tgaimage->width <= 0 || tgaimage->height <= 0 || (tgaimage->bpp!=24 && tgaimage->bpp!=32)){
      printf("Width: %d\nHeight: %d\n BPP: %d\n",(int)tgaimage->width,(int)tgaimage->height,(int)tgaimage->bpp);
      Error("Wrong file type.",-3);
        }

   unsigned int bytesPerPixel = tgaimage->bpp / 8;
   unsigned int imageSize = ((tgaimage->width * tgaimage->height) * bytesPerPixel);
   
   tgaimage->type = GL_RGBA;

   if(tgaimage->bpp==24)
   {
      tgaimage->type = GL_RGB;printf("RGB\n");
    }
    else
    {
        printf("RGBA\n");
    }

    if(tgaimage->header.colorMapType!=0)
    {
    Error("Color Map Data detected! Stopping...",-4);
    }
   
    tgaimage->imageData = (BYTE*)malloc((size_t)((int)imageSize));
   
    if(tgaimage->imageData==NULL)
    {
   
    Error("Failed to alloc memory for TGA data!",-5);
    }

    for(int I = 0; I < (int)imageSize; I++)
    {
    tgaimage->imageData[I] = *stream;
    stream++;
    }

   printf("Image data\n\n");
   
   //Convert BGR to RGB
   /*for (i =0; i <(int)imageSize; i+=(int)bytesPerPixel)
   {
      
      temp = tgaimage->imageData[i];
      tgaimage->imageData[i] = tgaimage->imageData[i+2];
      tgaimage->imageData[i+2] = temp;
   }*/

   tgaimage->image = (u16*)malloc(sizeof(u16)*(tgaimage->width*tgaimage->height));
int I = 0;
   for(int i=0; i < (int)(tgaimage->width*tgaimage->height); i++)
   {

         tgaimage->image[i] = RGB8((tgaimage->imageData[I + 0]),
            (tgaimage->imageData[I + 1]),
            (tgaimage->imageData[I + 2])) | BIT(15);
   
   I+=bytesPerPixel;

   }

   createTexture(tgaimage);

   printf("Success...\n\n");

   return 1;
}


bool createTexture(TGAimage *tgaimage)
{
   glGenTextures(1,tgaimage->texID);
   glBindTexture(GL_TEXTURE_2D, *tgaimage->texID);

   //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    //GL_UNSIGNED_BYTE
   
   glTexImage2D(*tgaimage->texID, 0, GL_RGB, TEXTURE_SIZE_32, TEXTURE_SIZE_32,0, TEXGEN_TEXCOORD, (uint8*)tgaimage->image);

   return true;
}


int LoadGLTextures()
{
   
   
   int R=loadTGA((u8*)APencil_0_tga,&image,&texture[0]);
   
   
   
   

   return R;
}


int main()
{   
   // Turn on everything
   powerON(POWER_ALL);
   
   /*videoSetMode(MODE_FB0);
   
    vramSetBankA(VRAM_A_LCD);*/
   
   /*consoleDemoInit();
   
    videoSetModeSub(MODE_FB0);
   
    vramSetBankB(VRAM_B_LCD);
   */
   
   videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE);   //sub bg 0 will be used to print text
   vramSetBankC(VRAM_C_SUB_BG);

   //SUB_BG0_CR = BG_MAP_BASE(31);
   
   //consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(31), (u16*)CHAR_BASE_BLOCK_SUB(0), 16);
   consoleDemoInit();
   
   
   // Setup the Main screen for 3D
   videoSetMode(MODE_0_3D);
   vramSetBankA(VRAM_A_TEXTURE);                        //NEW  must set up some memory for textures

   // IRQ basic setup
   irqInit();
   irqSet(IRQ_VBLANK, 0);

   // Set our viewport to be the same size as the screen
   glViewPort(0,0,255,191);
   
   // Specify the Clear Color and Depth
   glClearColor(0,0,0);
   glClearDepth(0x7FFF);
    result=LoadGLTextures();
   
   while(1)
   {
         
      // Reset the screen and setup the view
      glReset();
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      gluPerspective(35, 256.0 / 192.0, 0.1, 100);
      glColor3f(1,1,1);
      
      glLight(0, RGB15(31,31,31) , 0,              floattov10(-1.0),       0);
      glLight(1, RGB15(31,31,31) , 0,              0,   floattov10(-1.0));
      glLight(2, RGB15(31,31,31) , 0,              0,   floattov10(1.0));

      glPushMatrix();
      
      glMatrixMode(GL_TEXTURE);
      glIdentity();
      
      glMatrixMode(GL_MODELVIEW);

      //need to set up some material properties since DS does not have them set by default
      glMaterialf(GL_AMBIENT, RGB15(16,16,16));
      glMaterialf(GL_DIFFUSE, RGB15(16,16,16));
      glMaterialf(GL_SPECULAR, BIT(15) | RGB15(8,8,8));
      glMaterialf(GL_EMISSION, RGB15(16,16,16));

      //ds uses a table for shinyness..this generates a half-ass one
      glMaterialShinyness();
      
      
      //ds specific, several attributes can be set here   
      glPolyFmt(POLY_ALPHA(31) | POLY_CULL_NONE  | POLY_FORMAT_LIGHT0| POLY_FORMAT_LIGHT1| POLY_FORMAT_LIGHT2);
      
      // Set the current matrix to be the model matrix
      glMatrixMode(GL_MODELVIEW);
      
      //Push our original Matrix onto the stack (save state)
      glPushMatrix();   

      DrawGLScene();
      
      // Pop our Matrix from the stack (restore state)
      glPopMatrix(1);

      // flush to screen   
      glFlush();
      
      
      
      
      
       swiWaitForVBlank();
   }
   
   return 0;
}

int DrawGLScene()                                 // Here's Where We Do All The Drawing
{
   glLoadIdentity();                           // Reset The View
   glTranslatef(0.0f,0.0f,-5.0f);

   glRotatef(xrot,1.0f,0.0f,0.0f);
   glRotatef(yrot,0.0f,1.0f,0.0f);
   glRotatef(zrot,0.0f,0.0f,1.0f);

   glBindTexture(GL_TEXTURE_2D, texture[0]);

   glBegin(GL_QUADS);
      // Front Face
      glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
      glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
      glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
      glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
      // Back Face
      glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
      glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
      glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
      glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
      // Top Face
      glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
      glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
      glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
      glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
      // Bottom Face
      glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
      glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
      glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
      glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
      // Right face
      glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
      glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
      glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
      glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
      // Left Face
      glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
      glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
      glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
      glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
   glEnd();

   xrot+=0.3f;
   yrot+=0.2f;
   zrot+=0.4f;
   return TRUE;         
}


Last edited by yellowstar on Sat Aug 04, 2007 12:10 am; edited 9 times in total

#135909 - silent_code - Fri Jul 27, 2007 10:50 am

you better post *what* problem you have and what works so far. then someone will be able to help you. often, it's a good idea to post "the whole thing". it's much better to post specific parts of the code that is causing problems.
me, e.g., i don't have the time to check your whole code. i imagine others feel the same.
please refine your post and i'm sure someone will help you!

ps: i've written an nds .tga loader myself (i think i had it in my stencil shadow demo), but without transparency. now that i'll have some spare time (uni is over for this semester, yay!) that's a thing i'd like to implement myself. i've found 5+3 bit texture mode pretty useful for what i need. ;D

#135940 - yellowstar - Fri Jul 27, 2007 6:13 pm

When I posted this topic,
I forgot to post what my problem is.

See my first post for details
on what my problem is.

#135945 - silent_code - Fri Jul 27, 2007 7:11 pm

there's still not enough information to help you. (you're being very generic - no details at all... any pics of the problem? i guess there are a *lot* of possible texture related bugs.)
well, i can still give you some hints (i didn't read your code... it's too much):

i remember i had problems with endianes (is that the correct term?). that's why i'm reading and shifting stuff.
convert your 24 colors to 15 bit colors (don't gorget to set bit 15 in the 16 bit value). make sure stuff is in R-B-G format. else you'll see garbage.
if that works, head for transparency: convert the 8 bit alpha value into 3 bit, the regular colors still need to be 15 bit, but in a 32 color palette.

here you can check out my code: www.robs-basement.de
just download the sources and look for the .tga stuff (source/tgaloader.cpp, source/initialize.cpp for the conversion). you should be able to modify that to work with transparencies. well, at least there're some hints and the conversion code, plus it works. ;^D
NOTE: oh, don't forget that i used gbfs, so you'll have to adjust it for use with libfat, in case that's what you're working with.

good luck.

ps: you don't need all those data structures, just skip the stuff you don't need and return width, height and image data (bpp is straight forward, so leave it out). [i should have written a better function for that, but i was kinda lazy... ;^D ]
_________________
July 5th 08: "Volumetric Shadow Demo" 1.6.0 (final) source released
June 5th 08: "Zombie NDS" WIP released!
It's all on my page, just click WWW below.


Last edited by silent_code on Sat Jun 14, 2008 3:07 pm; edited 1 time in total

#135951 - yellowstar - Fri Jul 27, 2007 8:38 pm

I don't have a file/image host for
hosting files/images.

So I can't post links to images,
untill I find one.

I can't look for one right now.

EDIT:
I now have a image host.
This means I have posted links to these images.
Go to this post for details.

I guess I'll try that later,
when I have the time.(Converting the 24 bit
colors to 16.)


Last edited by yellowstar on Sun Jul 29, 2007 4:12 am; edited 2 times in total

#135974 - yellowstar - Sat Jul 28, 2007 2:41 am

I have posted the important pieces of code
in my first post.

#135978 - yellowstar - Sat Jul 28, 2007 4:01 am

I have tried the above,(converting the colors to 16 bit)
but that didn't work.

Now it looks differen't,
but it still won't work right.

I have updated the loadTGA and createTexture functions.


Last edited by yellowstar on Sun Jul 29, 2007 4:08 am; edited 1 time in total

#136006 - Cearn - Sat Jul 28, 2007 1:41 pm

Leaving the printf statements and failed attempts in the posted code does not help us figure out what's going on. The non-essential extras makes it difficult to read the code, and due to the commented out parts it is hard to see what is and isn't part of the current function. For example

yellowstar wrote:
Code:
   //if(tgaimage->header.colorMapType!=0)
   //{
    for(int I = 0; I < 5; I++)
    {
    tgaimage->header.ColorMapSpecification[I] = *stream.GetStreamCur();stream.Move(1);
    printf("ColorMapSpecification[%d] = %d\n",I,(int)tgaimage->header.ColorMapSpecification[I]);
    }
    WaitForAnyKey();
    //}
   /*else
   {
   printf("No ColorMap Spec, there is no color map.\n");
   }*/
   //tgaimage->header.xOrigin = (short)stream.GetStreamCur();stream.Move(sizeof(short));
    //tgaimage->header.yOrigin = (short)stream.GetStreamCur();stream.Move(sizeof(short));
    //tgaimage->he
ader.imageWidth = (short)stream.GetStreamCur();stream.Move(sizeof(short));
    //tgaimage->header.imageHeight = (short)stream.GetStreamCur();stream.Move(sizeof(short));
   
    MemCpy(stream.GetStreamCur(),&tgaimage->header.xOrigin);stream.Move(sizeof(short));
    MemCpy(stream.GetStreamCur(),&tgaimage->header.yOrigin);stream.Move(sizeof(short));

This is nearly impossible to parse without the benefit of color highlighting, which this forum doesn't have. All this code really says is:

Code:
    for(int I = 0; I < 5; I++)
    {
        tgaimage->header.ColorMapSpecification[I] = *stream.GetStreamCur();
        stream.Move(1);
    }

    MemCpy(stream.GetStreamCur(),&tgaimage->header.xOrigin);
    stream.Move(sizeof(short));
    MemCpy(stream.GetStreamCur(),&tgaimage->header.yOrigin);
    stream.Move(sizeof(short));

In other words: Remove irrelevant and non-functional parts before posting.

Using identifiers that differ only by case (i and I, and position and POSITION members of the stream class) is a not a good idea. All-caps is generally reserved for constants, and using them for something else creates some mental friction. There letters besides i that are used for indices, and stream.position isn't a position but merely a pointer, so don't call it that.
As a sidenote: using I (and l and O) are particularly bad choices for identifiers because they look very similar to 1 and 0 in many fonts.

The current implementation of the stream class is incredibly unwieldy. All it really does is keep track of a pointer and an offset, but in a way that could be done just as well with, well, a pointer and an offset. Or just a single pointer for that matter. Accessing the stuff with GetStreamCur() and Move() just makes it harder to read because of the horizontal space they take up. Either make your class complete and useful, or lose it.

At the very least, create byte/halfword/word/anysize readers/writers that also update the position automatically; that's how (AFAIK) streams work anyway. Above all, test on the PC first, where you have better debug options.

yellowstar wrote:
Code:
void MemCpy(BYTE *source, short *target)
{
     for(int i = 0; i < (int)sizeof(short); i++)
     target[i] = source[i];
}

This function has no relation to the standard memcpy() at all in both appearance and functionality, so don't imply that by naming it MemCpy(). What it really does expands 2 bytes into 2 halfwords: 01 02 -> 0001, 0002. This is probably the source of a few of the problems.

For reading a halfword from 2 bytes, either cast the source and read or, if alignment may be a problem, use something like this:
Code:
u16 read16(const u8 *src)
{   return src[0] | src[1]<<8;   }


yellowstar wrote:
Code:
   if(tgaimage->header.imageType !=2){
      //printf("Unsuported TGA type.\n");
      //return -2;
      char str[8];
      strcpy(str,"");
      sprintf(str,"%s\nSupported Type: Uncompressed, RGB, with orgin at top-left.(2)\nType: %d","Unsuported TGA type.",(int)tgaimage->header.imageType);
      Error(str,-2);
     
   }

You are trying to dump a string that spans two lines into 8 characters. That never ends well.

yellowstar wrote:
Code:
   for(int i=0; i < (int)(tgaimage->width*tgaimage->height); i+=2)
   {

         tgaimage->IMAGE[i] = RGB15((tgaimage->imageData[I + 0] / 8) & 0x1F,
            (tgaimage->imageData[I + 1] / 8) & 0x1F,
            (tgaimage->imageData[I + 2] / 8) & 0x1F) | BIT(15);
   
   I+=4;

   }

If the image was 24bpp, incrementing by 4 would be bad; use bytesPerPixel like before. libnds also has an RGB8() function that takes 8bit color components as its arguments so you don't have to do the 8->5bit conversion yourself.

yellowstar wrote:
Code:
  tgaimage->imageData = (BYTE*)malloc((size_t)((int)imageSize));
 ...
   for (i =0; i <(int)imageSize; i+=(int)bytesPerPixel)
... and many more

If you find yourself adding casts all the time, it might be better use the correct type in the first place. Often, casts for integers aren't necessary anyway.

yellowstar wrote:
Code:
int in=0;
int r;

Don't ever use global variables with names this short. They would be impossible to find in larger projects and could give rise to naming conflicts. For an example of this, see here and search for "alpha". Ensure your global vars are distinguishable from your locals vars.

I can't really tell if the TGA reader works or not from here, but it'd be best to test that on the PC first as well. Once you're sure that one works, port to NDS and try to display it in a frame buffer. After that, use a pre-converted image to see if you know how to work with NDS textures. Then, and only then, try to combine all these things. This procedure will give you a better idea of where the problem is. Do not try to do things all at once. A step-by-step approach works better.

A picture of both would be helpful. I never used the services, but photobucket and imageshack are still free, right? You could try uploading the image there. Even a failed image can tell you a lot about what's going on, by the way. Use a simple, geometric shapes. If the colors change, you will know that you're mis-reading R,G,B values; ditto for swapped color and alpha values. If the image is skewed, you'll know that the width/pitch is wrong and if it's cut off, the height is wrong. Horizontal gaps often mean a bitdepth problem and if the image makes no sense at all, well, then it could be anything :\.

#136026 - yellowstar - Sat Jul 28, 2007 4:46 pm

I did most of your suggestions.

The ones I did not do,(right now anyway)
is testing on PC, and posting a link to an image.(no image host.)

EDIT:
I now have a image host.
This means I have posted links to these images.
Go to this post for details.

I am drawing the texture
on a cube.

I have made some major progress!

I have taken out the code
that handles the alpha.

It still works with transparent
TGAs,
it just makes it solid,
non-transparent.

I have found out,
that the major problem
is a mistake in the code
that converts the
image to 16 bit:
Code:

tgaimage->image = (u16*)malloc(sizeof(u16)*(tgaimage->width*tgaimage->height));
int I = 0;
   for(int i=0; i < (int)(tgaimage->width*tgaimage->height);i+=2)
//The amount it is being incremented by is the problem!
//Simply changing that amount to 1, or to i++,
//fixes the major problem!
   {

         tgaimage->image[i] = RGB8((tgaimage->imageData[I + 0]),
            (tgaimage->imageData[I + 1]),
            (tgaimage->imageData[I + 2])) | BIT(15);
   
   I+=bytesPerPixel;

   }


Now,
the converted image looks like
the original TGA,
but almost every
part of the image is
the wrong color.

And in two parts
of the image,
two colors are
in the part that
the other color should be.

Also,
the background color is wrong.

When I leave the code
in which flips the Blue
and Red colors,
the image dosen't look right,
but the shape is the same
as the original TGA.

But when I take out that code,
it looks like the above.(the section after the piece of code.)


For the image host:

I know about Image Shack.

I don't have access to my
email account right now,(won't have access
to it for a week.)
and to register for an account I
must check my email,
which I can't do right now.

Any other image hosting
web sites?

I have updated my source code.


Last edited by yellowstar on Sun Jul 29, 2007 4:13 am; edited 2 times in total

#136094 - M3d10n - Sun Jul 29, 2007 1:28 am

Use this to host images:
http://freeshare.us/

No need to register whatsoever (but you can do it if you want to keep track of your images). Just upload the image and it it gives you links for it.

#136099 - yellowstar - Sun Jul 29, 2007 3:50 am

I have uploaded two images on freespace.

WARNING:
These links are only temporary.
I am going to move these images to Image Shack
in about a week.(When I can access my email account.)

Note: In the capture, it(the texture) is on a 3D square,
instead of the cube, which I have
it render on normally.(the cube)
This is because the emulator I used
for this screenshot won't render the cube correctly.

The first is a capture of the top screen.(With the texture
on a 3D square.)

The second is the texture.

The third is the original, in BMP format.

The fourth is the texture.
This one's colors is swapped.(green and blue)

Note:
For some reason,
my image host messed up the Capture image
on there host.
But the Texture image is fine.

If you want to view the images without
the free space stuff,
do the following:

1.Right click the image, and click properties.

2.Select the address, and copy it.

3.Past the address into the address bar.

4.Go to that address!

Capture

Texture

Original

Manually Swapped
Texture



I have a question related to screenshots.

How do I take a screenshot(in my DS program)
of one of the screens,(The top, 3D screen.)
and save it to a file using FAT?


Last edited by yellowstar on Thu Aug 02, 2007 6:06 pm; edited 3 times in total

#136122 - Cearn - Sun Jul 29, 2007 2:11 pm

The screenshot looks ok to me. The reason some pixels seem 'off' is because the square is rotated and scaled -- you always get a little distortion then.

There is no transparency because all bits have their alpha-bit set. You'd need to only set it for other colors than the background color to make the borders transparent. Or, instead of doing all the work yourself, you can use a converter like grit or texmex (which unfortunately seems down right now >_>) to prepare the textures for you.

yellowstar wrote:
How do I take a screenshot(in my DS program) of one of the screens,(The top, 3D screen.) and save it to a file using FAT?
GBATek : capture. With this you can get a 16bpp screenshot, which you can then convert to an image format of your choice and then save. (I think)

#136126 - yellowstar - Sun Jul 29, 2007 3:16 pm

I removed the transparency handling.
It still works with RGBA and RGB,
the texture would just be solid.

I'am going to keep it that way untill
I get the colors to work right.
But if transparency works
when I try to put it back in,(before the colors work right)
I'll update the source and images.

#136183 - yellowstar - Sun Jul 29, 2007 10:34 pm

I tried putting the code which
handles the transparency back in,
but it won't work.

It won't let any pixel be transparent.

Can this only be done with palettes?(TGA color maps)

I did not update the source code in my first post.

My code basicly loops through the image,
and when its alpha is at least 50,
it makes that pixel solid,
otherwise it will make it transparent.

#136238 - silent_code - Mon Jul 30, 2007 2:14 pm

i suggest you look up the ds' texture transparency modes. looks like you didn't read my post carefully.
first of all, the ds' colors are 15bit (yes, there is the opaque bit 15, but this is about colors)! lighting calculations are done in 24 bit, but stuff is displayed in 18bit (the displays bit depth).

multiple alpha textures can only be done either with 5 (bit color) + 3 (bit alpha) or 3 + 5 and of cause that're palette modes.

also, i guess, you haven't looked at my code (which is working in emulators and on hw). that could've given you valuable hints. well, it's up to you - either take the offered help or leave it.

last thing: having a *correct* version of the texture to compare the faulty output your code creates to, would help as well. i also had problems with .tga loading, basically the component orders and the infamous swapped s/t texture coordinate problem. i made a simple texture which contained four basic color squares (r, g, b, black) and their complements (which is not necessarily required), as well as the letters R, G, B, A. using that texture i was able to correct everything in a matter of minutes. ok, my .tga loader has been migrated from working pc code, but well. ;D

all in all i think you need to try a little bit harder on your side and take advices seriously. like: don't post code that noone wants to read and always describe your problems, if possible with images! ;D

#136289 - yellowstar - Tue Jul 31, 2007 12:04 am

I have uploaded an image of the original image.(Bmp version.)
See my above post which has the links to the images.

#136415 - yellowstar - Wed Aug 01, 2007 2:24 pm

silent_code wrote:

also, i guess, you haven't looked at my code (which is working in emulators and on hw). that could've given you valuable hints. well, it's up to you - either take the offered help or leave it.


I did when you first posted the link to it.

I tried adding the S/T texture stuff like yours does,
but that didn't do anything.


Last edited by yellowstar on Thu Aug 02, 2007 5:23 pm; edited 1 time in total

#136421 - yellowstar - Wed Aug 01, 2007 4:03 pm

I tried implementing transparency via palettes.

But the way am doing it dosen't work.

See below for code.

Does anybody know of any viewers/converters for
bin/raw files?
The converter would need to convert from bin/raw to a
differen't format, like BMP.
This is for captures of the DS screen(s).


Here's the loadTGA function:(original source code
in first post was not updated)(For the createTexture function,
the format is GL_RGB256)
Code:


struct TGAimage
{
...
u16 *palette;
int Pal;
};

bool loadTGA(u8 *DATA, TGAimage *tgaimage, int *texID)
{
   int i;
   unsigned int temp;
   BYTE *stream = NULL;

   if(DATA==NULL){Error("Attempted to loaded null data!",-1);}

   stream = DATA;

    tgaimage->texID = texID;



    tgaimage->header.ID_Length = *stream;stream++;
    tgaimage->header.colorMapType = *stream;stream++;
    tgaimage->header.imageType = *stream;stream++;
   
    for(int a = 0; a < 5; a++)
    {
    tgaimage->header.ColorMapSpecification[a] = *stream;stream++;
    }
   
    SCpy(stream,&tgaimage->header.xOrigin);stream+=2;
    SCpy(stream,&tgaimage->header.yOrigin);stream+=2;
    SCpy(stream,&tgaimage->header.imageWidth);stream+=2;
    SCpy(stream,&tgaimage->header.imageHeight);stream+=2;
   
    tgaimage->header.pixelDepth = *stream;stream++;

   if(tgaimage->header.imageType !=2){
      char str[256];
      strcpy(str,"");
      sprintf(str,"%s\nSupported Type: Uncompressed, RGB, with orgin at top-left.(2)\nType: %d","Unsuported TGA type.",(int)tgaimage->header.imageType);
      Error(str,-2);
      
   }

   tgaimage->width = tgaimage->header.imageWidth;
   tgaimage->height = tgaimage->header.imageHeight;
   tgaimage->bpp = tgaimage->header.pixelDepth;

   if (tgaimage->width <= 0 || tgaimage->height <= 0 || (tgaimage->bpp!=24 && tgaimage->bpp!=32)){
      printf("Width: %d\nHeight: %d\n BPP: %d\n",(int)tgaimage->width,(int)tgaimage->height,(int)tgaimage->bpp);
      Error("Wrong file type.",-3);
        }

   unsigned int bytesPerPixel = tgaimage->bpp / 8;
   unsigned int imageSize = ((tgaimage->width * tgaimage->height) * bytesPerPixel);
   
   tgaimage->type = GL_RGBA;

   if(tgaimage->bpp==24)
   {
      tgaimage->type = GL_RGB;printf("RGB\n");
    }
    else
    {
        printf("RGBA\n");
    }

    if(tgaimage->header.colorMapType!=0)
    {
    Error("Color Map Data detected! Stopping...",-4);
    }
   
    tgaimage->imageData = (BYTE*)malloc((size_t)((int)imageSize));
   
    if(tgaimage->imageData==NULL)
    {
   
    Error("Failed to alloc memory for TGA data!",-5);
    }

    for(int I = 0; I < (int)imageSize; I++)
    {
    tgaimage->imageData[I] = *stream;
    stream++;
    }

   printf("Image data\n\n");
   
   //Convert BGR to RGB
   /*for (i =0; i <(int)imageSize; i+=(int)bytesPerPixel)
   {
      
      temp = tgaimage->imageData[i];
      tgaimage->imageData[i] = tgaimage->imageData[i+2];
      tgaimage->imageData[i+2] = temp;
   }*/

   tgaimage->image = (u16*)malloc(sizeof(u16)*(tgaimage->width*tgaimage->height));
int I = 0;
int w = 0;
int H = 0;
bool found = false;
u16 Temp;
u16 pal[50];
   for(int i=0; i < (int)(tgaimage->width*tgaimage->height); i++)
   {

         Temp = RGB8((tgaimage->imageData[I + 0]),
            (tgaimage->imageData[I + 1]),
            (tgaimage->imageData[I + 2]));

         if(bytesPerPixel==4)
         {

         if(tgaimage->imageData[I + 3]>=175)
            Temp |= BIT(15);

         if(tgaimage->imageData[I + 3]<175)
            Temp &= ~BIT(15);

         }

         

         
   
   I+=bytesPerPixel;


   found = false;

   for(int h=0; h<w; h++)
   {
     if(pal[h]==Temp)
     {
     found=true;
     H = h;
     break;
     }
   }

   if(found==true)
   {

   Temp = (u16)H;

   }

   if(found==false)
   {
      w++;

      pal[w-1] = Temp;

      found = true;

      H = w;

      Temp = (u16)H;
   }

   if(!(pal[(int)Temp] & BIT(15)))
      Temp = 0;

   tgaimage->image[i] = Temp;


   }

   tgaimage->palette = (u16*)malloc(2 * 256);

   memset(tgaimage->palette,2 + 2 * ((size_t)w),0);

   memcpy(tgaimage->palette,&pal[1],2 * ((size_t)w));

   gluTexLoadPal(tgaimage->palette,(u16)w,GL_RGBA);

   

   createTexture(tgaimage);

   printf("Success...\n\n");

   return 1;
}

#136500 - a128 - Thu Aug 02, 2007 11:17 am

Code:



//---------------------------------------------------------------------------------
//should work?!!!!!!!!!!!!
//converts 32bit RGBA to NDS RGBalpha 16bit image with alpha=0 or 1

void image32to16(sImage* img) {
//---------------------------------------------------------------------------------

   int x;
   int y;

   int colormode=4;

   u16* temp = (u16*)malloc(img->height*img->width*2);

   unsigned int imageSize = img->height*img->width * colormode;

   int n=0;
   
   for(int i=0;i<imageSize;n++,i+=colormode)
   {
               
         unsigned char r,g,b,a;

         r=img->image.data8[i]>>3;
         g=img->image.data8[i+1]>>3;
         b=img->image.data8[i+2]>>3;
         a=img->image.data8[i+3]&0x1;//only one bit

         temp[n]=   (a<<15)|RGB15(r,g,b);
   }

   free(img->image.data8);

   img->bpp=16;
   img->image.data16 = temp;
}





loading TGA from linux/windows is done via

Code:


bool tga_alpha=false;
//---------------------------------------------------------------------------------
bool loadTGA(const char *filename, sImage* tgaFile)
{
    FILE *file;
    unsigned char      badChar;
    short int      badInt;
    long           imageSize;
    int         colorMode;

    file = fopen(filename, "rb");

    if (!file)
        return false;

    fread(&badChar, sizeof(unsigned char), 1, file);
    fread(&badChar, sizeof(unsigned char), 1, file);

    unsigned char imageTypeCode;
    fread(&imageTypeCode, sizeof(unsigned char), 1, file);

    //13 bytes of useless data
    fread(&badInt, sizeof(short int), 1, file);
    fread(&badInt, sizeof(short int), 1, file);
    fread(&badChar, sizeof(unsigned char), 1, file);
    fread(&badInt, sizeof(short int), 1, file);
    fread(&badInt, sizeof(short int), 1, file);


    //image dimensions

    short int w;
    short int h;
   
    fread(&w, sizeof(short int), 1, file);
    fread(&h, sizeof(short int), 1, file);

    tgaFile->width=(int)w;
    tgaFile->height=(int)h;

    //image bit depth
    unsigned char bitCount;
    fread(&bitCount, sizeof(unsigned char), 1, file);

    //1 byte of garbage data
    fread(&badChar, sizeof(unsigned char), 1, file);

    //colorMode -> 3 = BGR, 4 = BGRA
    colorMode = bitCount / 8;
    imageSize = tgaFile->width * tgaFile->height * colorMode;

//fprintf(stderr,"\nTGA has colorMode %d\n",colorMode);
    if(colorMode==4) fprintf(stderr,"\nTGA has RGBalpha map\n");
   
    tga_alpha=colorMode==4;

    /*else
        if(colorMode==3) fprintf(stderr,"\nTGA has RGB map\n");
*/
    //allocate memory for image data
    tgaFile->image.data8 = (u8*)malloc(imageSize);

    //read in image data
    fread(tgaFile->image.data8, sizeof(unsigned char), imageSize, file);

    //change BGR to RGB (especially for OpenGL later on)

    int i;
    //3 = BGR to RGB and 4=BGRA to RGBA
    for ( i = 0; i < imageSize; i += colorMode)
    {
        //swap blue and red colour value
        tgaFile->image.data8[i] ^= tgaFile->image.data8[i+2] ^=
                                     tgaFile->image.data8[i] ^= tgaFile->image.data8[i+2];
   
   
    }

    //close file
    fclose(file);

    return true;
}
//TGA stuff end



Here I load the TGA file and convert it to NDS image!!

finaly I dump the NDS image to a inlcude file and I am done

Code:


int ok= loadTGA(name, &ob->texture_image);
//set by loadTGA, ugly code
if(tga_alpha)
{
   ob->texture_alpha=1;
   image32to16(&ob->texture_image);
}
   else{
   ob->texture_alpha=0;
      image24to16(&ob->texture_image);
   }

#136520 - silent_code - Thu Aug 02, 2007 2:50 pm

ok, now from the corrupt/original texture comparsion i can tell, that your byte order is broken!

AGAIN:

ARE YOU *SURE* YOU ARE WRITING COLORS IN R-B-G, NOT R-G-B?

are you using shorts (u16)?
are you writing 32 or 16 bits?

if your code was technically the same as mine, it would work!

i guess that you're getting wrong transparency, because of the same fault you get screwed colors. e.g. you get 0xFFFF00 (yellow in r-g-b) instead of 0xFF00FF (magenta ion r-g-b). shifting that into r-b-g the colors seem totally valid... think about it! instead of green you get *blue* (that's because it's r-b-G, but you seem to be writing r-G-b) and the red part of the texture is still RED, because it's R-g-b and R-b-g. white is still white, from what i can tell. that raises suspicion!

CHECK that! (hint: if i remember correctly, i made a comment for that in my code.)

btw: yes, i didn't read the code, that's because i don't have a lot of time to spend on the inet. at least i'm trying to help. ;p

good luck!

ps: the broken texture seems shifted, that looks like there's also something else wrong. try to swap the blue and green channel in an image editor and see if the resulting image looks like the original texture. that's kind of the hard way, though. you better just swap blue and green in your code. ;D

#136530 - yellowstar - Thu Aug 02, 2007 5:19 pm

silent_code wrote:

are you using shorts (u16)?
are you writing 32 or 16 bits?


I am using shorts.

silent_code wrote:

if your code was technically the same as mine, it would work!


I removed that comment in my above post.

silent_code wrote:

ps: the broken texture seems shifted, that looks like there's also something else wrong. try to swap the blue and green channel in an image editor and see if the resulting image looks like the original texture. that's kind of the hard way, though. you better just swap blue and green in your code. ;D


The shifted image was due to a mistake by
me, when I took the screenshot
of the texture in an emulator.
I have uploaded the fixed version.
See my above post which has the links to the images.

I tried swapping the colors manually.
See my above post which has the links to the images
for the result.
The result almost looks right,
but it still isn't correct.

I also tried swapping the colors in code,
but it won't work.
Here's how I am doing it:(This is after the
image is read in, before it is
converted to 16 bit colors.)
(I tried the way you do it
in your code,
bu that won't work either.)

Code:

unsigned char temp;
...

//Convert BGR to RGB
   for (i =0; i <(int)imageSize; i+=(int)bytesPerPixel)
   {
      
      temp = tgaimage->imageData[i];
      tgaimage->imageData[i] = tgaimage->imageData[i + 2];
      tgaimage->imageData[i + 2] = temp;

      temp = tgaimage->imageData[i + 1];
      tgaimage->imageData[i + 1] = tgaimage->imageData[i + 2];
      tgaimage->imageData[i + 2] = temp;
   }


Last edited by yellowstar on Thu Aug 02, 2007 6:17 pm; edited 3 times in total

#136531 - Cearn - Thu Aug 02, 2007 5:21 pm

silent_code wrote:
ok, now from the corrupt/original texture comparsion i can tell, that your byte order is broken!

AGAIN:

ARE YOU *SURE* YOU ARE WRITING COLORS IN R-B-G, NOT R-G-B?

Uhm, I'm sorry, but Targa's are BGR, not RBG. In your reader, the image seems to start at byte 17, while it should start at byte 18 (at least in the absence of an Image Identification Field or a Color Map). This is why it would seem to be RBG according to your loader (see specs for details).
The "pFile += 8;" in your loader should have been "pFile += 9;". This is why the you're using *++pFile instead of the more conventional *pFile++ : at the time you need to read the width-field, you're still at byte 11 instead of byte 12.

I agree that yellowstar's problem is related to a frame-shift, though. But it's hard to see what goes on without the details of the original tga file. The posted original is converted to an 8-bit bmp, which makes analysis difficult.


@ yellowstar:

Take a look at a128's code. It's nicely blocked out, indented, clearly commented (i.e., not to the extend that it hides the actual code) and written clearly (well, apart minor issues like the swap-by-xor, I guess :P ). If he had a problem with his loader, people would be more willing to debug his code than yours because it's more readable. Consider it an example.

As silent_code said comparing your texture (with the blue BG) and the original (green BG), it seems the image is read at an offset. If you want to find the offset yourself, use a clearly defined boundary for the image and open it in a hex editor.

#136547 - yellowstar - Thu Aug 02, 2007 6:41 pm

I have finally got it to work!!!!

I made it move 1 byte forward before reading in
the image.
I then put in the above code in my above post
for swapping colors.(I had to swap twice because,
for some reason the image still wasn't correct.(It was
similar to the way it was, without the red pixels.))

Now it works!!!!

Colors and alpha works!!!
Alpha works without a palette!


I have one last queston:(I asked this before in this topic.)

Does anybody know of any viewers/converters for bin files?
The converter needs to convert an bin file
to a differen't file.(like BMP)
(This is for captures of the screen(s))

EDIT:
Also,
how do I capture the bottom
screen, instead of the top screen?

#136708 - yellowstar - Sat Aug 04, 2007 12:06 am

I am trying to save TGAs of captures of the screen(s).

But the way I am doing it won't work.

Here's my problem:
The image, on the computer,
is only black.

I also have some other questions:(source code is below)

Does anybody know of any basic TGA editors?
They need to be able to enable/disable
RLE encoding, changing the orgin, palette, and ect.
(The one I was using I don't have access to right now,
and it's very big, and I don't want to
download it with my slow internet just for this.)

Also, how do I capture the bottom screen,
instead of the top screen?

Does anybody know of any viewers/converters for bin files?
(For captures of the screens.)
The converters would need to be able to convert bin to
a differen't format.(like BMP.)



Here's how I am doing it:

This is the function which saves the TGA for captures:
(This function is supposed to save a TGA,
using a converted version of the data.)
(The actual function is the function below this one)
Code:



struct TGA_header
{
   BYTE ID_Length;
   BYTE colorMapType;
   BYTE imageType;
   BYTE ColorMapSpecification[5];
   short xOrigin;
   short yOrigin;
   short imageWidth;
   short imageHeight;
   BYTE pixelDepth;
   BYTE ImageDesc;
};


void SaveTGAMACRO(TGAimage *tgaimage, u8 *buff, int index, int startBit)
//This function is supposed to
//grab the Red, Green, and Blue colors from
//a 16 bit color, and convert it to 8-bit.
{


      for(int p=startBit;p<startBit + 5;p++)
      {
         if(tgaimage->image[index] & BIT(p))
         {
         *buff |= BIT(startBit - p);
         }
         else
         {
         *buff &= ~BIT(startBit - p);
         }
      }
      
      *buff = *buff >> 3;
}

void SaveTGA(u16 *data, int size, char *filename)//Saves an TGA image.
//data is the image data. size is image size.(pixels)
{



   TGAimage tgaimage;
   u8 *buff = NULL;
   FILE *f = NULL;

   memset(&tgaimage,sizeof(TGAimage),0);

   tgaimage.header.ID_Length = 0;
   tgaimage.header.colorMapType = 0;
   tgaimage.header.imageType = 2;//RGB, no alpha

   tgaimage.header.imageWidth = 256;
   tgaimage.header.imageHeight = 192;
   tgaimage.header.xOrigin = 0;
   tgaimage.header.yOrigin = 0;
   tgaimage.header.pixelDepth = 24;//8-bit

   tgaimage.header.ImageDesc = 32;

   tgaimage.image = data;

   buff = (u8*)malloc((size_t)size * 3);

   f = fopen(filename,"wb");

   u8 buffer = 0;
   int I = 0;

   for(int i=0; i<size; i++)
   {
   

      SaveTGAMACRO(&tgaimage,&buffer,i,0);buff[I + 0] = buffer;
      SaveTGAMACRO(&tgaimage,&buffer,i,5);buff[I + 1] = buffer;
      SaveTGAMACRO(&tgaimage,&buffer,i,10);buff[I + 2] = buffer;


      I+=3;

   }
   
   
   fwrite(&tgaimage.header.ID_Length,1,1,f);
   fwrite(&tgaimage.header.colorMapType,1,1,f);
   fwrite(&tgaimage.header.imageType,1,1,f);
   
   fwrite(&tgaimage.header.ColorMapSpecification,1,5,f);

   fwrite(&tgaimage.header.xOrigin,2,1,f);
   fwrite(&tgaimage.header.yOrigin,2,1,f);
   fwrite(&tgaimage.header.imageWidth,2,1,f);
   fwrite(&tgaimage.header.imageHeight,2,1,f);
   
   fwrite(&tgaimage.header.pixelDepth,1,1,f);

   fwrite(&tgaimage.header.ImageDesc,1,1,f);


   fwrite(buff,3,(size_t)size,f);

   fclose(f);


   free(buff);



}



Here's the function which takes the screenshot:
(It calls the SaveTGA function in this function.)
Code:

void ScreenShot()
{

int temp = 0;
u8 temp2 = 0;
u16 *buffer = NULL;
FILE *f = NULL;

temp2 = 1;//VRAM block; Set it to target VRAM bank B

for(int i=16;i<=17;i++)
{
   if(temp2 & BIT(i-16))
   {
      temp |= BIT(i-16);
   }
   else
   {
      temp &= ~BIT(i-16);
   }
}

temp2 = 0;//Write offset; set it to 00000h

for(int i=18;i<=19;i++)
{
   if(temp2 & BIT(i-18))
   {
      temp |= BIT(i-18);
   }
   else
   {
      temp &= ~BIT(i-18);
   }
}

temp2 = 3;//Capture Size; set it t0 256x192(Screen size)

for(int i=20;i<=21;i++)
{
   if(temp2 & BIT(i-20))
   {
      temp |= BIT(i-20);
   }
   else
   {
      temp &= ~BIT(i-20);
   }
}

temp |= BIT(24);//Set the source to only 3D

temp &= ~BIT(25);//Set source B to VRAM



temp2 = 0;//VRAM read offset

for(int i=26;i<=27;i++)
{
   if(temp2 & BIT(i-26))
   {
      temp |= BIT(i-26);
   }
   else
   {
      temp &= ~BIT(i-26);
   }
}

temp2 = 0;//VRAM read offset

for(int i=29;i<=30;i++)
{
   if(temp2 & BIT(i-29))
   {
      temp |= BIT(i-29);
   }
   else
   {
      temp &= ~BIT(i-29);
   }
}

temp |= BIT(31);//Enable it;Start capturing!

DISP_CAPTURE = temp;//Copy it to the capture register!Make it start capturing!

while(DISP_CAPTURE & BIT(31));//Wait for it to finish.It will clear this
//bit when done. Then it will exit this loop.

buffer = (u16*)malloc(256*192*2);

dmaCopy(VRAM_B,buffer,256*192*2);

f = fopen("/screenshot.bin","w");
fclose(f);

f = fopen("/screenshot.bin","wb");

fwrite(buffer,2,256*192,f);

fclose(f);

SaveTGA(buffer,256*192*2,"/screenshot.tga");

free(buffer);

}



Here's the functions which calls the Screenshot function:
(Step is called in the main loop.)

Code:


void DoScreenShot()
{

 if(keysDown() & KEY_X)
 {

 printf("Taking screenshot of top 3D screen...\n");

ScreenShot();

printf("Done!\n");
printf("Saved to screenshot.bin\nin the root of your card.\n");

 }

}

#endif

void Step()
{

scanKeys();

#ifdef DEBUG2

if(fat_init_success)
{

DoScreenShot();
}
#endif

}

#136714 - kusma - Sat Aug 04, 2007 12:57 am

yellowstar wrote:

Does anybody know of any basic TGA editors?
They need to be able to enable/disable
RLE encoding, changing the orgin, palette, and ect.
(The one I was using I don't have access to right now,
and it's very big, and I don't want to
download it with my slow internet just for this.)

Why are you putting the complexity on the DS-side, and not just on the pc-side where you can cram in any big already-tested-to-death image-loading library (freeimage, devil, sdlimage or whatever)?

#136715 - yellowstar - Sat Aug 04, 2007 1:05 am

kusma wrote:
yellowstar wrote:

Does anybody know of any basic TGA editors?
They need to be able to enable/disable
RLE encoding, changing the orgin, palette, and ect.
(The one I was using I don't have access to right now,
and it's very big, and I don't want to
download it with my slow internet just for this.)

Why are you putting the complexity on the DS-side, and not just on the pc-side where you can cram in any big already-tested-to-death image-loading library (freeimage, devil, sdlimage or whatever)?


For TGA editors,
I meant on the PC side.

For the bin viewer/converter,
I also meant on the PC side.

#136726 - yellowstar - Sat Aug 04, 2007 3:51 am

The bin version of the screenshot seems fine,
as I checked it in Notepad, and the
characters were not all the same,
like it is supposed to be.

#136740 - kusma - Sat Aug 04, 2007 10:47 am

yellowstar wrote:

For the bin viewer/converter,
I also meant on the PC side.


Oh, I'm sorry. Then I misunderstood. Well, why don't you just use FreeImage or some other library that already went through the complexity of supporting every wicked variation of different file-formats?

#136760 - silent_code - Sat Aug 04, 2007 6:42 pm

Cearn wrote:
Uhm, I'm sorry, but Targa's are BGR, not RBG. In your reader, the image seems to start at byte 17, while it should start at byte 18 (at least in the absence of an Image Identification Field or a Color Map)...

damn, you're right! now i feel dumb!
anyway, also thanks for the code hint, i'll have a look at it asap.

#136783 - M3d10n - Sun Aug 05, 2007 5:24 am

yellowstar:

Are you trying to save screenshots on the DS? If so, you can try loading the images as RAW (uncompressed, headerless) files in Photoshop. Type in the image dimensions and pixel format and it'll try to display it.

#136807 - yellowstar - Sun Aug 05, 2007 4:08 pm

M3d10n wrote:
yellowstar:

Are you trying to save screenshots on the DS? If so, you can try loading the images as RAW (uncompressed, headerless) files in Photoshop. Type in the image dimensions and pixel format and it'll try to display it.


Yes,
I am trying to save screenshots on the DS.
After I do that,
I am trying to convert it to TGA,
but it won't work.

I don't have Photoshop.

I wrote a small program which
displays an bin file on the main screen.
It dosen't look like anything
like it is supposed to.(It loads a preset bin file)

I found out that DSOrganize can
read and display bin files, in Mode 5.
In that it wasn't being displayed right either,
but it was differen't than my small viewer.

#136815 - yellowstar - Sun Aug 05, 2007 5:14 pm

I got the bin version to work right!!!

Now it contains what it is supposed to contain!

It was caused by the "i-(somevalue)"
statements in the pieces of code
which copied the temp2 data into the
temp var.

But the TGA version is still the same.
The TGA version still won't work.

EDIT:
How do I take an screenshot of
the sub screen, instead of the main screen?

I tried adding lcdSwap before the temp
var gets written to the display capture register,(I
also put in swiWaitForVBlank, after this call,
before it gets written)
and after the display capture is done.

Bu that didn't work.

#136829 - tepples - Sun Aug 05, 2007 6:36 pm

yellowstar wrote:
How do I take an screenshot of
the sub screen, instead of the main screen?

"Capture is supported for Display Engine A only."
Copy the sub screen's contents (background registers, OAM, VRAM, palette) to the main screen and capture them from there.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#137075 - yellowstar - Tue Aug 07, 2007 7:53 pm

I am working on adding more features to my TGA loader.
(bottom-left orgin, RLE compression, and color maps(palettes))

Right now I am working on adding the bottom-left orgin feature.

How would I implement RLE decompression
in my loader?

In know what it is.

Right now,
what I want to know is this:
how is the numbers represented?(In the image,
in a RLE compressed TGA)
Bytes, or something else?
(By numbers, I mean the numbers
that say how much data(which is the same) is in a row.)

#137156 - silent_code - Wed Aug 08, 2007 1:27 pm

look for tga specs. there're some on the net, mostly with some code snippets. ;^)

like:

- http://netghost.narod.ru/gff/vendspec/tga/index.htm
- http://dmr.ath.cx/gfx/targa/

#137164 - yellowstar - Wed Aug 08, 2007 2:55 pm

I had a few documents about the TGA spec,
but none of them had a section about the RLE compression.
(And none of them were the official document.)

I have downloaded the spec from one of those links,
and I am going to try to impement RLE decompression.

By the way,
I have finished implementing the bottom-left orgin feature.
It displays the image the right side up.
That is, it displays the image like
you would see it in an image editor/viewer.

EDIT:

I have figured out what do about a
bin viewer for a computer.

I could make a NDS program,
which displays a bin file.

Then in an emulator,
I could look at it,
and if needed,
take a screenshot of
the screen which displays the bin file.(With everything else removed.)


As for my TGA saver for screenshots:
The function which attempts to
convert a color(RGB)
to a 8 bit color,
must be the problem.

#137165 - silent_code - Wed Aug 08, 2007 3:07 pm

yellowstar wrote:
The function which attempts to convert a color(RGB) to a 8 bit color

??? 24bit -> 8bit (why would you do that?) ??? 5bit -> 8bit per component ???

#137168 - yellowstar - Wed Aug 08, 2007 3:15 pm

silent_code wrote:
yellowstar wrote:
The function which attempts to convert a color(RGB) to a 8 bit color

??? 24bit -> 8bit (why would you do that?) ??? 5bit -> 8bit per component ???


I meant the NDS 16 bit colors,
and the RGB values inside them.

#137178 - silent_code - Wed Aug 08, 2007 4:20 pm

ok.

#137296 - yellowstar - Fri Aug 10, 2007 12:01 am

I have finished implementing RLE
decompression in my TGA loader.

Now the only things left I need to implement is black and white,
and color maps.(palettes)
I know black and white wouldn't be used much,
but I am going to implement it anyway.

EDIT:
I have finished implementing grayscale,
in my TGA loader.(black and white)

yellowstar wrote:

I have figured out what do about a
bin viewer for a computer.

I could make a NDS program,
which displays a bin file.

Then in an emulator,
I could look at it,
and if needed,
take a screenshot of
the screen which displays the bin file.(With everything else removed.)


I have wrote this program.
I have the makefile setup so
that screenshot.bin on my card
is copied to the data directory.
This program displays that bin file.

That means to view a bin file on the computer,(256*192*2(u16))
all I have to do is rename/copy the bin file to screenshot.bin
in the root of my card,
and build the program.
Then I would run it in an emulator,
then take the screenshot.