Best Way to Store Texture or Image Information in a File

I am looking to store texture information in a database file (Or a file where the user cannot readily edit or open it). I want to save an array of 4 textures to a .dat file, I do not want the program to have to open a bitmap file every time it is run. The file export code is towards the end, is this the proper way to store such information?



   char *image_path = "Gui_bkgd.bmp";
    char *image_path2 = "1.bmp";
    char *image_path3 = "2.bmp";
    char *image_path4 = "3.bmp";

    SDL_Surface *image = IMG_Load (image_path);
        if(!image)
            {
                std::cout << "Error Cannot load image Gui_bkgd.bmp
";
            }
    SDL_Surface *image2 = IMG_Load (image_path2);
        if (!image2)
            {
                std::cout << "Error Cannot load image 1.bmp
";
            }

    SDL_Surface *image3 = IMG_Load (image_path3);
        if (!image3)
            {
                std::cout << "Error Cannot load image 2.bmp
";
            }

    SDL_Surface *image4 = IMG_Load (image_path3);
        if (!image4)
            {
                std::cout << "Error Cannot load image 3.bmp
";
            }

                                             
    glEnable(GL_TEXTURE_2D);

    static GLuint textures[4];
    glGenTextures(4, textures); //Number of textures stored in array name specified
    

    //Background texture
    glBindTexture(GL_TEXTURE_2D, textures[0]);//Texture 0 is the background

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    // Map the surface to the texture in video memory
    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, image->w, image->h, 0, GL_BGR, GL_UNSIGNED_BYTE, image->pixels); //GL_BITMAP

    //Assigning texture pads their data
    //arbitrary textures 1 - 4
    for(int i = 1; i < 4; i++ )
        {

            glBindTexture(GL_TEXTURE_2D, textures[i]);

            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
            glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, image->w, image->h, 0, GL_BGR, GL_UNSIGNED_BYTE, image->pixels); //GL_BITMAP
        }
    SDL_FreeSurface ( image );
    SDL_FreeSurface ( image2 );
    SDL_FreeSurface ( image3 );
    SDL_FreeSurface ( image4 );


                                                    /*Database Export*/
    FILE *file;
    int n = 4;
    file = fopen("Data.dat", "w");
    fprintf(file, "%u
", textures[0]);

    for (int i = 0; i > n; i++)
    {
        fprintf(file, "%u
", textures[i]);
    }




    fclose(file);
    glDisable(GL_TEXTURE_2D);

Or a file where the user cannot readily edit or open it

That’s pretty much not going to happen. Even databases are easy to open if they know what kind of DB it is.

Really, if you’re interested in defeating casual examination of your data, just stick it in a zip file. And then rename the extension.

The file export code is towards the end, is this the proper way to store such information?

No.

fprintf(file, "%u
", textures[0]);

fprintf writes text, not binary data. Furthermore, that just writes the texture name, not useful information about it.

If you want to save image data, then use an image library that has saving capacity.

I see, thanks. I guess my dilemma is finding a way to export a texture pack. That way the program loads one file, and I don’t have to have a bunch of bmp images in the program folder. It’s mainly a way to consolidate, I’m not as concerned about users cracking it and viewing contents.

The problem with custom DIY texture and archive formats is that you will have to develop custom tools for dealing with it.

If you simply want to stick a bunch of files into a single archive file, you might consider using the ZIP format or
something similar, for simplicity (Or even AR if you just want to glue uncompressed files together in the simplest possible way).

If you are looking for an image file format actually designed for storing textures, you might want to look at the following:

[ul]
[li] KTX [/li][li] DDS [/li][li] VTF [/li][/ul]

If you want to stop people from viewing/editing your files, inventing your own [i]obscure file format[/i] won’t do much for you.
You will most likely need something based on encryption. The problem is, that your application still has to be able to read it.
I won’t help you here for ethical reasons.

There is no “proper” way, but as Agent D points out, writing texture names to a file is meaningless; you have to write the data.

The main considerations for a file format are size versus speed. If you want to minimise file size, you would use some form of compression (whether lossy or lossless). If you want to maximise loading speed, you might want to store the data uncompressed (and more specifically, in the exact format required by glTexImage or similar, including any alignment constraints, so that you can simply map the file and pass pointers within the mapped region).

The other common consideration is compatibility. The asset-creation workflow may be better if the software can read whatever formats the texture artists can easily create without requiring any time-consuming conversion steps or even needing to restart the program.

Could I use SDL_RWFromFile(const char* file, “w”) and save multiple surfaces to a dat file? Not sure of how to get multiple images into one file. I am not as concerned with compression or users being able to see the information as this is a project for school.

Edit: Someone on another forum recommended I save the image data into a file, then write code that specifies that a new image is beginning, save image 2, and so on and so forth. They’re advice was not too clear though, but that is the direction I’d need to head.

Edit2: Update - I can just put the images together in a row, then rename the bmp file as .dat, and use SDL.rect structures and blitting to section the images I need.

[QUOTE=amorag59;1264233]Could I use SDL_RWFromFile(const char* file, “w”) and save multiple surfaces to a dat file? Not sure of how to get multiple images into one file.


Edit2: Update - I can just put the images together in a row, then rename the bmp file as .dat, and use SDL.rect structures and blitting to section the images I need.
[/QUOTE]
There are functions related to SDL_RWFromFile that can write to a file pointer. Also, the “w” mode would only overwrite the file anyway, so you end up having a file
that contains the last image. There is an “a” mode that appends to the file, and you should theoretically be able to get it out again the same way.
Maybe you want to take a look at this.

Or maybe, you store a lookup table at some fixed location (like the beginning of the file) that tells you what image files you would find at what offset. That way,
you don’t have to sift through the entrie file when you only want a specific image, or find out what images there are.

Files that can have other files stuffed into them are usually called “archives”. Some time and research has been invested into the topic in the last ~50 years, so
it might be more convenient to look at something existing rather than reinventing the wheel in a very inefficient way.

You can store a binary image as a blob in an SQLite database. I created a GL renderer and scene builder which does this (obj2sqlite) available at GitHub - chrisliebert/sdlgl3c-sqlite: A 3D OpenGL 3 renderer written in C with bindings for Java and LuaJIT which is capable of loading 3D models from an SQLite database..

     
    const char *zSql = "SELECT image FROM texture WHERE name = ?";
    sqlite3_stmt *pStmt;
    int rc;

    do
    {
        rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
        sqlite3_bind_text(pStmt, 1, textureFileName, -1, SQLITE_STATIC);
        rc = sqlite3_step(pStmt);
        if( rc==SQLITE_ROW )
        {
            unsigned char* buffer = 0;
            buffer = malloc(sizeof(unsigned char) * sqlite3_column_bytes(pStmt, 0));
            memcpy(buffer, sqlite3_column_blob(pStmt, 0), sqlite3_column_bytes(pStmt, 0));

            SDL_RWops *rw = 0;
            rw = SDL_RWFromMem( buffer, (sizeof(unsigned char) * sqlite3_column_bytes(pStmt, 0)) );
            SDL_Surface* image = SDL_LoadBMP_RW(rw, 1);

            if (image == NULL)
            {
                printf("Unable to load bitmap: %s
", SDL_GetError());
                exit(1);
            }

            glGenTextures(1, textureId);
            glBindTexture(GL_TEXTURE_2D, *textureId);
            int mode = GL_RGB;
            if (image->format->BytesPerPixel == 4)
            {
                mode = GL_RGBA;
            }
            glTexImage2D(GL_TEXTURE_2D, 0, mode, image->w, image->h, 0, mode,
                         GL_UNSIGNED_BYTE, image->pixels);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

            //Free the temporary surface
            SDL_FreeSurface(image);
        }
        rc = sqlite3_finalize(pStmt);
    }
    while( rc==SQLITE_SCHEMA );