Need urgent help: TGA file read write and then Smoothing



  • I want to create command line application that can read TGA image file in C++ and want to output it to another TGA image file. The another TGA image file must be smoothed or faded. The TGA files must support for both 24 and 32 bit. How can I implement this logic? Need help on this as am newbie to TGA image file format.



  • @tampere2021 Do I need to use filter? Any sample code would help here.Need a way to parse and write this without using any 3rd party libraries. Which algorithm is best suited for fading an image, thereby reducing the sharpness of the image to a certain level than the original raw image? To fade image, I thought of taking each pixel value and take average of it and considering its nearby pixels.

    Below code I tried using C. But something is wrong with this approach I feel as I am not able to get a readable image of the new file which is faded. I need a C++ code which does this functionality. Please help me on this.

    [code]
    #include <stdio.h>
    #include <stdlib.h>

    int main()
    {
    FILE *fin, *fout;
    char pathin[64], pathout[64];
    char **rev, px;
    int sum, width, height, read, i, j;

    printf("Infile name is: ");
    scanf("%s", pathin);
    printf("Outfile name is: ");
    scanf("%s", pathout);
    
    printf("Width of image (in pixels): ");
    scanf("%d", &width);
    printf("Height of image (in pixels): ");
    scanf("%d", &height);
    
    fin = fopen(path_in, "rb");
    fout = fopen(path_out, "wb");
    
    rev = (unsigned char **)malloc(height * sizeof(unsigned char *));
    for(i = 0; i < height; i++)
    	rev[i] = (unsigned char *)malloc(width * sizeof(unsigned char));
    //Store pixel values from image in a width x height unsigned char matrix
    for(i = 0; i < height; i++)
    {
    	for(j = 0; j < width; j++)
    	{
    		read = fread(&px, sizeof(unsigned char), 1, fin);
    		rev[i][j] = px;
    	}
    }
    //Fade the image using average of nearby pixels
    sum = 0;
    for(i = 0; i < height; i++)
    {
    	for(j = 0; j < width; j++)
    	{
    		//Top row of image
    		if(i == 0)
    		{
    			if(j == 0)
    				sum = (rev[i][j] + rev[i][j + 1] + 
    						rev[i + 1][j] + rev[i + 1][j + 1]) / 4;
    			else if(j == width - 1)
    				sum = (rev[i][j] + rev[i][j - 1] +
    						rev[i + 1][j] + rev[i + 1][j - 1]) / 4;
    			else
    				sum = (rev[i][j] + rev[i][j - 1] + rev[i][j + 1] +
    						rev[i + 1][j] + rev[i + 1][j - 1] + rev[i + 1][j + 1]) / 6;
    		}
    		//Bottom row of image
    		else if(i == height - 1)
    		{
    			if(j == 0)
    				sum = (rev[i][j] + rev[i][j + 1] + 
    						rev[i - 1][j] + rev[i - 1][j + 1]) / 4;
    			else if(j == width - 1)
    				sum = (rev[i][j] + rev[i][j - 1] +
    						rev[i - 1][j] + rev[i - 1][j - 1]) / 4;
    			else
    				sum = (rev[i][j] + rev[i][j - 1] + rev[i][j + 1] +
    						rev[i - 1][j] + rev[i - 1][j - 1] + rev[i - 1][j + 1]) / 6;
    		}
    		//Left side of image 
    		else if(j == 0)
    			sum = (rev[i][j] + rev[i - 1][j] + rev[i + 1][j] +
    					rev[i][j + 1] + rev[i - 1][j + 1] + rev[i + 1][j + 1]) / 6;
    		//Right side of image 
    		else if(j == width - 1)
    			sum = (rev[i][j] + rev[i - 1][j] + rev[i + 1][j] + 
    					rev[i][j - 1] + rev[i - 1][j - 1] + rev[i + 1][j - 1]) / 6;
    		//Pixels without border image
    		else
    			sum = (rev[i][j] + rev[i][j - 1] + rev[i][j + 1] + rev[i - 1][j] + rev[i + 1][j] + 
    					rev[i - 1][j - 1] + rev[i - 1][j + 1] + rev[i + 1][j - 1] + rev[i + 1][j + 1]) / 9;
    		rev[i][j] = (unsigned char)sum;
    	}
    }
    //Write each pixel to new file
    for(i = 0; i < height; i++)
    {
    	for(j = 0; j < width; j++)
    	{
    		if(j < width && i < height)
    			fwrite(&rev[i][j], sizeof(unsigned char), 1, fout);
    	}
    }
    //Close both files
    fclose(fout);
    fclose(fin);
    
    return 0;
    

    }
    [/code]


  • Mod

    @tampere2021 sagte in Need urgent help: TGA file read write and then Smoothing:

    Need a way to parse and write this without using any 3rd party libraries.

    What? Why? Why would anyone do this to themselves? How would a 3rd party library be different from using C-Standarlibrary?



  • @SeppJ I am trying to read TGA file and write to another TGA file using only std library functions. Any suggestions on how smoothing of the TGA IMAGE FILE can be done?


  • Mod

    I understand what you want to do. But why not use 3rd party library?



  • @SeppJ I need to write it from scratch using standard libraries only and not with any other 3rd party libraries. Do you have any idea how this can be done?



  • @tampere2021 It looks like you assume that the file starts with the pixel data. I'm not familiar with the tga format, but Wikipedia says it contains a lot more data which needs to be parsed (https://en.wikipedia.org/wiki/Truevision_TGA)

    I would suggest that you have allok at open source TGA libraries to get an idea how to implement such a library by yourself. (e.g. https://github.com/ColumbusUtrigas/TGA )



  • @Schlangenmensch Thanks for the link. I need to use std library functions only as this is CPU intensive and not to be used on GPU where we use OpenGL/CUDA. Any idea how to write from scratch?



  • Ok, so you don't want to answer the "why" question. I guess then you will have to study the specification: http://www.dca.fee.unicamp.br/~martino/disciplinas/ea978/tgaffs.pdf

    You could also look at libraries, for example here: https://github.com/aseprite/tga/blob/main/decoder.cpp - but that would be "using" a 3rd party lib for help. (no idea if this lib is any good)



  • @tampere2021 This link has only read TGA .How about write TGA? I need to handle uncompressed TGA image file first for both 24 and 32bit cases.



  • @wob Hi Wob, I had mentioned here already that this is CPU intensive application and so want to stick onto to using only c++ std libraries and not use any 3rd party tools or libraries.



  • @tampere2021

    Hi Wob, I had mentioned here already that this is CPU intensive application and so want to stick onto to using only c++ std libraries and not use any 3rd party tools or libraries.

    Ah, the explanation arrived was the same minute I wrote my reply. Didn't see it, sorry.

    However, I don't understand the connection here - do you think all existing libraries are slow? So your real question is "What is the best (i.e. fastest) library to read tga files?" - benchmark a few libraries, select the fastest, maybe even try to optimize an existing library, done. That will very likely be much faster than starting from scratch.

    This link has only read TGA .How about write TGA?

    No idea who you did reply to. The link I gave also has an encoder...



  • @tampere2021 So, you've no idea how to implement it by yourself but you think you can still do better than a 3rd party lib. That's ambitious.
    My link has no further dependencies, but, yes it's just reading. You'd to implement the writing part by yourself. But my link was more thought as inspiration how you could start from scratch.



  • @Schlangenmensch Ok. I will take it as a reference.



  • @wob Hi Wob, I am not doing any benchmarking for libraries here, rather want to just do a read TGA image file,then write the same TGA image file to another file by applying smoothing with the help of filters. This is to identify how well we can do smoothing of TGA image files. Hope you understood what I am trying to do here.



  • @Schlangenmensch Hi Contortionist, I tried to read targa file, fetch some header values by check them, but none of the values gets changed and I then write to another targa file, but it doesnt seem to work. any idea what is wrong here?

    [code]
    struct TARGAFILE {
    char idLength;
    char colourMapType;
    char imageType;
    short colourMapStart;
    short colourMapNumEntries;
    char bitsPerEntry;
    short xOrigin;
    short yOrigin;
    short width;
    short height;
    char bitsPerPixel;
    char* pixelData;
    };

    TARGAFILE fetchImage(const std::string& pathToImage) {
    std::ifstream image(pathToImage, std::ios::binary);
    if (!image.is_open()) {
    throw FileNotFound();
    }
    TARGAFILE targaFile;
    image.read(&targaFile.idLength, sizeof(targaFile.idLength));
    image.read(&targaFile.colourMapType, sizeof(targaFile.colourMapType));
    image.read(&targaFile.imageType, sizeof(targaFile.imageType));
    image.read((char*)(&targaFile.colourMapStart), sizeof(targaFile.colourMapStart));
    image.read((char*)(&targaFile.colourMapNumEntries), sizeof(targaFile.colourMapNumEntries));
    image.read(&targaFile.bitsPerEntry, sizeof(targaFile.bitsPerEntry));
    image.read((char*)(&targaFile.xOrigin), sizeof(targaFile.xOrigin));
    image.read((char*)(&targaFile.yOrigin), sizeof(targaFile.yOrigin));
    image.read((char*)(&targaFile.width), sizeof(targaFile.width));
    image.read((char*)(&targaFile.height), sizeof(targaFile.height));
    image.read(&targaFile.bitsPerPixel, sizeof(targaFile.bitsPerPixel));

    int imageDataSize = targaFile.width * targaFile.height * (targaFile.bitsPerPixel / 8);
    
    targaFile.pixelData = new char[imageDataSize];
    
    int originalPosition = (int)image.tellg();
    image.read(targaFile.pixelData, imageDataSize);
    return targaFile;
    

    }

    void CheckHdrImage(TARGAFILE targaFile){
    std::ofstream output("test.tga", std::ios::binary);
    output.write(&targaFile.idLength, sizeof(targaFile.idLength));
    output.write(&targaFile.colourMapType, sizeof(targaFile.colourMapType));
    output.write(&targaFile.imageType, sizeof(targaFile.imageType));
    output.write(reinterpret_cast<const char*>(&targaFile.colourMapStart), sizeof(targaFile.colourMapStart));
    output.write(reinterpret_cast<const char*>(&targaFile.colourMapNumEntries), sizeof(targaFile.colourMapNumEntries));
    output.write(&targaFile.bitsPerEntry, sizeof(targaFile.bitsPerEntry));
    output.write(reinterpret_cast<const char*>(&targaFile.xOrigin), sizeof(targaFile.xOrigin));
    output.write(reinterpret_cast<const char*>(&targaFile.yOrigin), sizeof(targaFile.yOrigin));
    output.write(reinterpret_cast<const char*>(&targaFile.width), sizeof(targaFile.width));
    output.write(reinterpret_cast<const char*>(&targaFile.height), sizeof(targaFile.height));
    output.write(&targaFile.bitsPerPixel, sizeof(targaFile.bitsPerPixel));
    output.write(reinterpret_cast<const char*>(&targaFile.pixelData), sizeof(targaFile.pixelData));
    output.close();
    }
    [/code]



  • The example code from my link reads some "image descriptor" data and some "color map" data depending on color map type. This is missing in your code, but as I wrote earlier, I'm not very familiar with the TGA file format, so I'm not sure about it.
    I would suggest to write some unit tests, so you can verify that you read the data you assume to read.





  • @tampere2021: @wob gave you a link to a PDF describing the format and a decoder implementation. So read the PDF and start writing your own TGA parser/reader/decoder/however you like to call it. If something isn't 100% clear from the PDF, look it up in the decoder.

    The code you posted is not nearly enough to read a TGA, so I'd suggest you drop it and start from scratch.

    Or you might want to start with writing a TGA. Since you probably only have to support one format, this will be much easier. And in case your application only needs to be able to read TGA files that were created by it, then the reader/parser code will also be easy. I'd still recommend you start with the writer, because you can test the writer on its own - just use any standard image viewer/editor to test whether the files your program writes are OK.



  • @hustbaer Sure will go through the PDF. I am trying to read .tga file, then write another .tga file by applying smoothing using filters,so that the newly created .tga file will have the smoothing effects


Log in to reply