C Language Homework Help, Project Help, C Language Assignment Solution

Hi, I guess you’re looking for assistance, since you’ve come here. Well, this is the place for C homework help. I’ve got over 30 years experience, and can handle almost anything you can throw at me.

I will go through an example project in C, with details of how the code was constructed. The program is supposed to convert a TGA file, to either a grey scale image or a 24 bit color image. It handles a wide variety of sample formats (it was difficult to find some of the obscure tga formats).

enum TGACompressionType

enum TGACompressionType
{
    NO_IMAGE = 0,
    UNCOMPRESSED_COLOR_MAPPED = 1,
    UNCOMPRESSED_TRUE_COLOR = 2,
    UNCOMPRESSED_BLACK_AND_WHITE = 3,   //Or GreyScale
    RLE_COLOR_MAPPED = 9,
    RLE_TRUE_COLOR = 10,
    RLE_BLACK_AND_WHITE = 11,
};

The TGA format supports compressed and uncompressed files. The compression used is run length compression
(you have a count of how many times a value is repeated, or how many unique values follow). It can also use
a color palette, be true color, or gray scale.

enum TGAAttributesType

enum TGAAttributesType
{
    NO_ALPHA = 0,   //Bits 3-0 of image descriptor should be 0 as well
    UNDEFINED_IGNORE = 1,   //Alpha data can be ignored
    UNDEFINED_RETAIN = 2,   //Alpha data should be retained
    ALPHA_PRESENT = 3,      //Alpha data is present
    ALPHA_PREMULTIPLIED = 4,    //Alpha channel is premultiplied
};

The TGA format also supports alpha values, so the different attribute types handle the possible types.

enum TGAReturn

enum TGAReturn
{
    OK = 0,
    UNABLE_TO_LOAD = -1,
    NOT_TGA = -2,
    UNABLE_TO_SAVE = -3,
    FILE_NOT_FOUND = -4,
    OUT_OF_MEMORY = -5,
};

The program can return several errors code, 0 for no error, then negative values for possible error conditions.

#ifdef GCC

#ifdef GCC
#define PACKED __attribute__((__packed__))
#else
#define PACKED
#pragma pack(1) //These structures should be laid out as written without alignment
#endif

This section is to define a macro PACKED that expands to a different value depending on the compiler used. The
purpose of this is to force the structure alignment. If you have

struct type
{
    int a;
    char b;
    int c;
};

Then on most compilers int a will take 4 bytes, char b will take 1 byte, then there will be 3 bytes that are skipped
and finally another 4 bytes for c. When you use PACKED it means that the layout would not have the empty spaces after
b. This is good when you are trying to map a structure to the contents of a file or to memory mapped hardware.

struct TGAHeader_struct

struct TGAHeader_struct
{
    u8 id_length;   //Length of image id field
    u8 color_map_type;  //0 = None, 1 = Present, 2-127 = Reserved, 128-255 = User
    u8 image_type;  //TGACompressionType
    u16 color_map_first_entry;  //Which is the first value stored
    //if you only used colors 128-255, you can just save those colors
    u16 color_map_length;   //Number of color map entries
    u8 color_map_entry_size;    //Number of bits per pixel
    u16 xorigin;    //Absolute coordinates of lower left
    u16 yorigin;    //Absolute coordinates of lower left
    u16 image_width;    //Width in pixels
    u16 image_height;   //Height in pixels
    u8 pixel_depth; //Bits per pixel
    u8 image_descriptor; //Bits 3-0 give the alpha channel depth, Bits 5-4 give direction
} PACKED;

typedef struct TGAHeader_struct TGAHeader;

This is the header format of a TGA file, it gives the palette format, the size of the image in pixels and whether the
image is flipped either vertically or horizontally.

Gray scale routines

static u8 RGB2GrayLuminosity(int r,int g,int b)
{
//  return g * .59 + r * .3 + g * .11;  //The actual code, but we avoid floating point
    int gray = ((g * 150) >> 8) + ((r * 153) >> 9) + ((g * 28) >> 8);
    if (gray < 0) gray = 0;
    if (gray > 255) gray = 255;
    return (u8)gray;
}

static u8 RGB2GrayAverage(int r,int g,int b)
{
    int gray = (r + g + b) / 3;
    if (gray < 0) gray = 0;
    if (gray > 255) gray = 255;
    return (u8)gray;
}

static u8 RGB2GrayLightness(int r,int g,int b)
{
    int min = r < g ? r : g;
    int max = r > g ? r : g;
    int gray;
    min = min < b ? min : b;
    max = max > b ? max : b;
    gray = (max + min) / 2;
    if (gray < 0) gray = 0;
    if (gray > 255) gray = 255;
    return (u8)gray;
}

//http://www.tannerhelland.com/3643/grayscale-image-algorithm-vb6/
static u8 RGB2GrayMin(int r,int g,int b)
{
    int min = r < g ? r : g;
    min = min < b ? min : b;
    return (u8)min;
}

static u8 RGB2GrayMax(int r,int g,int b)
{
    int max = r > g ? r : g;
    max = max > b ? max : b;
    return (u8)max;
}

static u8 RGB2GrayRed(int r,int g,int b)
{
    return (u8)r;
}

static u8 RGB2GrayGreen(int r,int g,int b)
{
    return (u8)g;
}

static u8 RGB2GrayBlue(int r,int g,int b)
{
    return (u8)b;
}

These are the different algorithms that map an rgb value to a grey scale value. RGB2GrayLuminosity returns the value
most like a black and white camera would show, RGB2GrayAverage assumes each rgb value contributes the same amount,
RGB2GrayLightness takes into account the highest and lowest values only, RGB2GrayMin takes into account the minimum
of the 3 rgb components, RGB2GrayMax returns the maximum of the 3 rgb components, and RGB2GrayRed, RGB2GrayGreen,
RGB2GrayBlue just return the corresponding component.

static int WriteGreyPixel(u32 argb,u8 *dst)

static int WriteGreyPixel(u32 argb,u8 *dst)
{
    u8 r,g,b;
    b = (u8)(argb >> 24);
    g = (u8)(argb >> 16);
    r = (u8)(argb >> 8);
    *dst = (*RGBToGray)(r,g,b);
    return 1;
}

The writes out a single rgb value, it calls one of the functions above.

static int Write32BitPixel(u32 argb,u8 *dst)

static int Write32BitPixel(u32 argb,u8 *dst)
{
    u8 a,r,g,b;
    a = (u8)(argb >> 24);
    r = (u8)(argb >> 16);
    g = (u8)(argb >> 8);
    b = (u8)argb;
    *dst++ = b;
    *dst++ = g;
    *dst++ = r;
    *dst++ = a;
    return 4;
}

This writes out a rgb value to 4 bytes.

static u16 TGAReadUShort(u16* val)

//Read a short from an unaligned address in little endian format
static u16 TGAReadUShort(u16* val)
{
    //This is inefficient (but it is safe on all architectures, including endian)
    u8* mem = (u8*)val;
    return mem[0] + (mem[1] << 8);
}

//Read an int from an unaligned address in little endian format
static u32 TGAReadUInt(u32* val)
{
    //This is inefficient (but it is safe on all architectures, including endian)
    u8* mem = (u8*)val;
    return mem[0] + (mem[1] << 8) + (mem[2] << 16) + (mem[3] << 24);
}

On some processors you cannot read an int on a byte boundary, it must be aligned, and this applies to shorts, doubles,
etc. This code works even if the processor is a different endian (this is the order the bytes that make up a word). If
you know the endian of the processor you are coding for then you can just use *addr to read an int (if you knew it was
aligned as well).

static void TGAWriteUShort(u16 val,u16 *address)

//Write a short to an unaligned address in little endian format
static void TGAWriteUShort(u16 val,u16 *address)
{
    //This is inefficient (but it is safe on all architectures, including endian)
    u8* mem = (u8*)address;
    mem[0] = (u8)val;
    mem[1] = (u8)(val >> 8);
}

//Write an int to an unaligned address in little endian format
static void TGAWriteUInt(u32 val,u32 *address)
{
    //This is inefficient (but it is safe on all architectures, including endian)
    u8* mem = (u8*)address;
    mem[0] = (u8)val;
    mem[1] = (u8)(val >> 8);
    mem[2] = (u8)(val >> 16);
    mem[3] = (u8)(val >> 24);
}

These 2 routines are the write equivalents of the read routines, they work across endian and handle unaligned access as
well.

static u32 grey(int col,int alpha)

//Convert value to grey (duplicate in RGB)
static u32 grey(int col,int alpha)
{
    return col + (col << 8) + (col << 16) + (alpha << 24);
}

When loading the file, we want to convert it to ARGB format, so for grey we just repeat the same value across R,G,B.

static u32 color(u8 *data,int bitsPerPixel,u8 alpha)

//Read a color value, with 15, 16, 24, or 32 bits per pixel
static u32 color(u8 *data,int bitsPerPixel,u8 alpha)
{
    int rgba = TGAReadUInt((u32*)data); //only true for 32 bit, but the others can be extracted
    //and this makes the code, endian independant
    u8 r,g,b;

    assert(bitsPerPixel == 15 || bitsPerPixel == 16 || bitsPerPixel == 24 || bitsPerPixel == 32);

    switch (bitsPerPixel)
    {
    case 15:
    case 16:
        r = (u8)((rgba >> 10)<<3);
        g = (u8)((rgba >> 5)<<3);
        b = (u8)(rgba<<3);
        break;
    case 24:
        r = (u8)(rgba >> 16);
        g = (u8)(rgba >> 8);
        b = (u8)rgba;
        break;
    case 32:
        alpha = (u8)(rgba >> 24);
        r = (u8)(rgba >> 16);
        g = (u8)(rgba >> 8);
        b = (u8)rgba;
        break;
    }

    return (alpha << 24) + (r << 16) + (g << 8) + b;
}

We use the code to read an unaligned int, and then process the value according to the actual number of bits (so a 15/16
bit format only uses 5 bits for each component).

u32* TGARead(int *width,int *height,u8 *memory,int size,int *error)

//Reads a TGA file from memory, and returns pointer to ARGB data
u32* TGARead(int *width,int *height,u8 *memory,int size,int *error)
{
    TGAHeader* header;
    u8* colorMap = NULL;    //For paletted files
    int bytesPerColor = 0;  //How many bytes per pixel in color map table
    u8* imageData;  //The raw pixel data
    u32* image;     //The output ARGB buffer
    u32* writeImage;    //Used to write to the ARGB buffer
    u8 alpha = 255; //Alpha value to put into ARGB buffer if none present in file
//  u8 readAlpha;   //How many bytes will we be reading from file
    int rle;    //Are we processing RLE file
    u32 rleVal; //Last RLE value
    int rleCount;   //How many instances of RLE value left
    int rleUnique;  //How many unique values do we need to read
    int colorMapped;
    int greyScale;
    int bitsPerPixel;

    //Can't be valid if too small, this check also stops accesses to memory that was not allocated
    if (size < sizeof(TGAFooter))
    {
        *error = NOT_TGA;
        return NULL;
    }
    header = (TGAHeader*)memory;    //Provide easy access to the header

    if (header->color_map_type > 1 ||
        header->image_type > RLE_BLACK_AND_WHITE ||
        header->pixel_depth > 32 ||
        header->image_descriptor > 63)  //Check for invalid values (no signature on TGA 1 files)
    {
        *error = NOT_TGA;
        return NULL;    //Doesn't appear to be a TGA file
    }

    rle = header->image_type >= RLE_COLOR_MAPPED;   //Compressed files are stored in RLE format
    colorMapped = (header->image_type & 3) == UNCOMPRESSED_COLOR_MAPPED;
    greyScale = (header->image_type & 3) == UNCOMPRESSED_BLACK_AND_WHITE;
//  readAlpha = ((header->image_descriptor & 15) + 7) >> 3; //How many bytes of alpha are present

    *width = TGAReadUShort(&header->image_width);   //Stored as little endian
    *height = TGAReadUShort(&header->image_height);

    bitsPerPixel = header->pixel_depth; //Is this set, on true color images? Specs imply it isn't but the information does not occur elsewhere

    size = *width * *height;    //Total number of pixels

    if (size <= 0)  //If width or height is 0 (or too large > 46000 pixels in x & y)
    {
        *error = NOT_TGA;
        return NULL;    //Not a TGA file
    }

    if (colorMapped)    //If we have color
    {
        bytesPerColor = (header->color_map_entry_size + 7) >> 3;
        colorMap = memory + sizeof(TGAHeader) + header->id_length;  //colorMap starts here
        imageData = colorMap + (TGAReadUShort(&header->color_map_length) * bytesPerColor);  //And ends with image data
//      imageData = colorMap + TGAReadUShort(&header->color_map_length);    //And ends with image data
        colorMap -= bytesPerColor * TGAReadUShort(&header->color_map_first_entry);  //Colors below color_map_first_entry are invalid
        bitsPerPixel = header->color_map_entry_size;
    }
    else
    {
        bytesPerColor = (bitsPerPixel + 7) >> 3;    //1 byte for grayscale, 2 bytes for 15/16 bits, 3 bytes for 24 bits, 4 bytes for 32 bits
        imageData = memory + sizeof(TGAHeader) + header->id_length; //Image data starts here
    }

    image = (u32*)malloc(size * 4); //4 bytes per pixel (ARGB)

    if (!image)
    {
        *error = OUT_OF_MEMORY;
        return NULL;    //say the malloc files due to lack of memory
    }

    writeImage = image; //We will write ARGB here, but we need to return the start

    rleCount = 0;
    rleUnique = 0;
    if (!rle) rleUnique = size; //Treat the entire image as rle unique

    while (size)    //If there are pixels left, keep processing
    {
        if (rleUnique)  //If were are processing unique then we read data
        {
            size--;
            rleUnique--;
            if (colorMapped)
            {
                u8* colorTable = colorMap + *imageData++ * bytesPerColor;
//              if (readAlpha) alpha = *imageData++;
                rleVal = color(colorTable,bitsPerPixel,alpha);
            }
            else if (greyScale)
            {
                int greyVal = *imageData++;
//              if (readAlpha) alpha = *imageData++;
                rleVal = grey(greyVal,alpha);
            }
            else //RGB, or RGBA (16 bit, 24 bit, 32 bit)
            {
                rleVal = color(imageData,bitsPerPixel,alpha);
                imageData += bytesPerColor;
            }
            write(rleVal,writeImage++);
        }
        else if (rleCount)
        {
            size--;
            rleCount--;
            write(rleVal,writeImage++);
        }
        else
        {
            if (*imageData >= 128)
            {
                rleCount = *imageData++ & 0x7f;
                rleUnique = 1;  //Just so we read the rleVal (we rleCount 1 less than actual)
            }
            else
            {
                rleUnique = *imageData++ + 1;
            }
        }
    }

    return image;
}

This is a long routine that reads in a buffer and returns the raw ARGB data or an error code.

Run length decompression loop

    rleCount = 0;
    rleUnique = 0;
    if (!rle) rleUnique = size; //Treat the entire image as rle unique

    while (size)    //If there are pixels left, keep processing
    {
        if (rleUnique)  //If were are processing unique then we read data
        {
            size--;
            rleUnique--;
            if (colorMapped)
            {
                u8* colorTable = colorMap + *imageData++ * bytesPerColor;
//              if (readAlpha) alpha = *imageData++;
                rleVal = color(colorTable,bitsPerPixel,alpha);
            }
            else if (greyScale)
            {
                int greyVal = *imageData++;
//              if (readAlpha) alpha = *imageData++;
                rleVal = grey(greyVal,alpha);
            }
            else //RGB, or RGBA (16 bit, 24 bit, 32 bit)
            {
                rleVal = color(imageData,bitsPerPixel,alpha);
                imageData += bytesPerColor;
            }
            write(rleVal,writeImage++);
        }
        else if (rleCount)
        {
            size--;
            rleCount--;
            write(rleVal,writeImage++);
        }
        else
        {
            if (*imageData >= 128)
            {
                rleCount = *imageData++ & 0x7f;
                rleUnique = 1;  //Just so we read the rleVal (we rleCount 1 less than actual)
            }
            else
            {
                rleUnique = *imageData++ + 1;
            }
        }
    }

This first sets the values for being in a run, or being in a series of unique values to 0, so it will process the first
byte correctly. If the file is not compressed then it sets the number of unique bytes equal to the size of the pixel data.
While there are pixels to process it either is in a sequence of unique values of a series of pixels with the same value.
If it is color mapped, read the byte and then get the palette value, if it is grayscale then get the gray value, otherwise
read the rgb value.

u8* TGAWrite(int width,int height,int *size,int colors,u8 *memory,u32 *data,int *error,int flags)

//Saves a TGA file in memory, colors gives the format (0 = Gray Scale)
//and returns pointer to TGA file, sets size to the size of the data
//Only colors = 0 is supported at the moment
//Returns NULL if unable to write the file
u8* TGAWrite(int width,int height,int *size,int colors,u8 *memory,u32 *data,int *error,int flags)
{
    u8* newTGA;
    TGAHeader* header;
    TGAHeader* newHeader;
    TGAFooter* footer;
    TGAFooter* newFooter;
    TGAExtension* extension = NULL; //Only present in TGA 2.0+ file
    TGAExtension* newExtension;
    u8* newImage;
    int tga2;
    int left;
    int bytesPerPixel;

//  colors = -1;    //Force TRUE COLOR, useful for testing
    assert(colors == 0 || colors == -1);    //So we can add extra support later

    header = (TGAHeader*)memory;    //Provide easy access to the header
    footer = (TGAFooter*)(memory+*size-sizeof(TGAFooter));

    if (header->id_length)
    {
        u8* end = memory + sizeof(TGAHeader)+header->id_length;
        u8 save = *end;
        *end = 0;
        printf("Image Identification:%s\n",memory+sizeof(TGAHeader));
        *end = save;
    }

    bytesPerPixel = (colors + 255) >> 8;    //1,2,3 for Color Indexed, 16 bit, 24 bit
    if (colors < 0) bytesPerPixel = 4;  //Handle the case of 32 bit
    if (!colors) bytesPerPixel = 1; //1 byte per pixel for Gray

    *size = sizeof(TGAHeader) + sizeof(TGAFooter) + width * height * bytesPerPixel + header->id_length;

    tga2 = !strcmp((const char*)footer->signature,"TRUEVISION-XFILE.");
    if (tga2)
    {
        int extension_offset = TGAReadUInt(&footer->extension_offset);
        if (extension_offset)
        {
            extension = (TGAExtension*)(memory + extension_offset);
            printf("Author:%s\n",extension->author);
            printf("Comment:%s\n",extension->comment);
            printf("Job name:%s\n",extension->jobname);
            printf("Software:%s %f%c\n",extension->software,TGAReadUShort(&extension->softwave_version)/100.0,extension->software_letter);
            *size += TGAReadUShort(&extension->extension_size);
        }
    }

    newTGA = (u8*)malloc(*size);
    newHeader = (TGAHeader*)newTGA;
    memcpy(newHeader,header,sizeof(TGAHeader) + header->id_length);
    newHeader->color_map_entry_size = 0;
    newHeader->color_map_first_entry = 0;
    newHeader->color_map_length = 0;
    newHeader->color_map_type = 0;

    if (flags & FLIP_X)
    {
        newHeader->image_descriptor ^= 0x10;
    }
    if (flags & FLIP_Y)
    {
        newHeader->image_descriptor ^= 0x20;
    }

    switch (colors)
    {
    case 0:
        newHeader->pixel_depth = 8;
        newHeader->image_type = UNCOMPRESSED_BLACK_AND_WHITE;
        writePixel = &WriteGreyPixel;
        break;
    case -1:
        newHeader->pixel_depth = 32;
        newHeader->image_type = UNCOMPRESSED_TRUE_COLOR;
        writePixel = &Write32BitPixel;
        break;
    }
    newFooter = (TGAFooter*)(newTGA + *size - sizeof(TGAFooter));
    strcpy(newFooter->signature,"TRUEVISION-XFILE.");
    newFooter->developer_area_offset = 0;
    newFooter->extension_offset = 0;
    if (extension)
    {
        newExtension = (TGAExtension*)((u8*)newFooter - sizeof(TGAExtension));
        memcpy(newExtension,extension,TGAReadUShort(&extension->extension_size));
        newFooter->extension_offset = ((u8*)newExtension - newTGA);
    }

    newImage = newTGA + sizeof(TGAHeader) + header->id_length;

    left = width * height;
    while (left)
    {
        newImage += writePixel(*data++,newImage);
        left--;
    }

    return newTGA;
}

This is a long routine that writes out the file as either a 24 bit tga file or a grey scale version.

Display extra information if present

    tga2 = !strcmp((const char*)footer->signature,"TRUEVISION-XFILE.");
    if (tga2)
    {
        int extension_offset = TGAReadUInt(&footer->extension_offset);
        if (extension_offset)
        {
            extension = (TGAExtension*)(memory + extension_offset);
            printf("Author:%s\n",extension->author);
            printf("Comment:%s\n",extension->comment);
            printf("Job name:%s\n",extension->jobname);
            printf("Software:%s %f%c\n",extension->software,TGAReadUShort(&extension->softwave_version)/100.0,extension->software_letter);
            *size += TGAReadUShort(&extension->extension_size);
        }
    }

There is an extension to the TGA format that includes the author, a comment, the name of the job, and the software involved.
If the extension is included it prints these values to the output.

u8* readFile(const char* src, int* size)

u8* readFile(const char* src, int* size)
{
    FILE *file;
    u8 *buffer;
    unsigned long fileLen;

    //Open file
    file = fopen(src, "rb");
    if (!file)
    {
        fprintf(stderr, "Unable to open file %s", src);
        return NULL;
    }

    //Get file length
    fseek(file, 0, SEEK_END);
    fileLen=ftell(file);
    *size = (int)fileLen;
    fseek(file, 0, SEEK_SET);

    //Allocate memory
    buffer=(u8*)malloc(fileLen+1);
    if (!buffer)
    {
        fprintf(stderr, "Memory error!");
        fclose(file);
        return NULL;
    }

    //Read file contents into buffer
    fread(buffer, fileLen, 1, file);
    fclose(file);

    return buffer;
}

Read the contents of the file into memory, returns the buffer and the size.

void writeFile(const char *dst, u8* memory, int size)

void writeFile(const char *dst, u8* memory, int size)
{
    FILE *file;

    //Open file
    file = fopen(dst, "wb");
    if (!file)
    {
        fprintf(stderr, "Unable to open file %s", dst);
        return;
    }

    //Read file contents into buffer
    fwrite(memory, size, 1, file);
    fclose(file);
}

Writes the memory to a file.

int convert(const char* src, const char* dst,int colors,int flags)

int convert(const char* src, const char* dst,int colors,int flags)
{
    int width, height,size;
    u8* memory;
    u32* image = NULL;
    u8* tga = NULL;
    int returnCode = OK;

//  memory = NULL; size = 0;    //Set these from read file
    memory = readFile(src, &size);

    if (memory)
    {
        image = TGARead(&width,&height,memory,size,&returnCode);
        if (image)
        {
            printf("Converting file %s\n",src);
            tga = TGAWrite(width,height,&size,colors,memory,image,&returnCode,flags);
            if (tga)
            {
                writeFile(dst,tga,size);
            }
            else
            {
                returnCode = UNABLE_TO_SAVE;
            }
        }   
    }
    else
    {
        returnCode = UNABLE_TO_LOAD;    //File not found
    }

    free(memory);
    free(tga);
    free(image);

    switch (returnCode)
    {
    case UNABLE_TO_LOAD:
        fprintf(stderr, "Unable to load %s\n",src);
        break;
    case NOT_TGA:
        fprintf(stderr, "%s is not a TGA file\n",src);
        break;
    case UNABLE_TO_SAVE:
        fprintf(stderr, "Unable to save %s\n",dst);
        break;
    case FILE_NOT_FOUND:
        fprintf(stderr, "File %s not found\n",src);
        break;
    case OUT_OF_MEMORY:
        fprintf(stderr, "Not enough memory\n",src);
        break;
    }
    return returnCode;
}

Converts a file (src) and saves it to (dst), using the provided flags. If there was an error, display the reason to stderr.

void help()

void help()
{
    printf("Welcome to TGA convert.\n");
    printf("Syntax: tga [option] source destination\n");
    printf("Options:");
    printf("-h,-?: These instructions:\n");
    printf("-32: Save as 32 bit color\n");
    printf("-L: Use luminosity (default) to convert to gray\n");
    printf("-a: Use avergage of r,g,b to convert to gray\n");
    printf("-l: Use lightness of r,g,b to convert to gray\n");
    printf("-m: Use minimum of r,g,b to convert to gray\n");
    printf("-M: Use maximum of r,g,b to convert to gray\n");
    printf("-r: Use red component to convert to gray\n");
    printf("-g: Use green component to convert to gray\n");
    printf("-b: Use blue component to convert to gray\n");
    printf("-x: Flip the image in X\n");
    printf("-y: Flip the image in Y\n");
}

Displays the help for the program.

c:\ tga -h
Welcome to TGA convert.
Syntax: tga [option] source destination
Options:
-h,-?: These instructions:
-32: Save as 32 bit color
-L: Use luminosity (default) to convert to gray
-a: Use avergage of r,g,b to convert to gray
-l: Use lightness of r,g,b to convert to gray
-m: Use minimum of r,g,b to convert to gray
-M: Use maximum of r,g,b to convert to gray
-r: Use red component to convert to gray
-g: Use green component to convert to gray
-b: Use blue component to convert to gray
-x: Flip the image in X
-y: Flip the image in Y

int main(int argc, const char* argv[])

int main(int argc, const char* argv[])
{
    int colors = 0;
    int src = 1;
    int dst = 2;
    int flags = 0;
    RGBToGray = RGB2GrayLuminosity;
    //If we have command line parameter
    if (argc > 1)
    {
        if (argv[1][0] == '-')
        {
            src++;
            dst++;
            switch (argv[1][1])
            {
            case '?':
            case 'h':
                help();
                return 0;
            case '3':
                colors = -1;
                break;
            case 'a':
                RGBToGray = RGB2GrayAverage;
                break;
            case 'l':
                RGBToGray = RGB2GrayLightness;
                break;
            case 'm':
                RGBToGray = RGB2GrayMin;
                break;
            case 'M':
                RGBToGray = RGB2GrayMax;
                break;
            case 'r':
                RGBToGray = RGB2GrayRed;
                break;
            case 'g':
                RGBToGray = RGB2GrayGreen;
                break;
            case 'b':
                RGBToGray = RGB2GrayBlue;
                break;
            case 'x':
                flags |= FLIP_X;
                break;
            case 'y':
                flags |= FLIP_Y;
                break;
            }
        }
    }
    else
    {
        help();
        return 0;
    }

    if (argc > dst)
    {
        convert(argv[src],argv[dst],colors,flags);
        return 0;
    }

Process the flags, if file name is not specified then process a built in list of files (for testing purposes).

tga.h

//tga.h
//Load and Save tga files

#ifndef TGA_H
#define TGA_H

typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef short s16;
typedef int s32;

//Read a short from an unaligned address in little endian format
u16 TGAReadUShort(u16* val);
//Read an int from an unaligned address in little endian format
u32 TGAReadUInt(u32* val);
//Write a short to an unaligned address in little endian format
void TGAWriteUShort(u16 val,u16 *address);
//Write an int to an unaligned address in little endian format
void TGAWriteUInt(u32 val,u32 *address);
//Reads a TGA file from memory, and returns pointer to ARGB data
//Returns NULL if not a valid TGA file
u32* TGARead(int *width,int *height,u8 *memory,int size,int *error);
//Saves a TGA file in memory, colors gives the format (0 = Gray Scale)
//and returns pointer to TGA file, sets size to the size of the data
u8* TGAWrite(int width,int height,int *size,int colors,u8 *memory,u32 *data,int *error);

#endif //TGA_H

tga.c

//tga.cpp
//Load and Save tga files

#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <malloc.h>
#include "tga.h"

//image_type in TGAHeader
enum TGACompressionType
{
    NO_IMAGE = 0,
    UNCOMPRESSED_COLOR_MAPPED = 1,
    UNCOMPRESSED_TRUE_COLOR = 2,
    UNCOMPRESSED_BLACK_AND_WHITE = 3,   //Or GreyScale
    RLE_COLOR_MAPPED = 9,
    RLE_TRUE_COLOR = 10,
    RLE_BLACK_AND_WHITE = 11,
};

enum TGAAttributesType
{
    NO_ALPHA = 0,   //Bits 3-0 of image descriptor should be 0 as well
    UNDEFINED_IGNORE = 1,   //Alpha data can be ignored
    UNDEFINED_RETAIN = 2,   //Alpha data should be retained
    ALPHA_PRESENT = 3,      //Alpha data is present
    ALPHA_PREMULTIPLIED = 4,    //Alpha channel is premultiplied
};

enum TGAReturn
{
    OK = 0,
    UNABLE_TO_LOAD = -1,
    NOT_TGA = -2,
    UNABLE_TO_SAVE = -3,
    FILE_NOT_FOUND = -4,
    OUT_OF_MEMORY = -5,
};

enum Flags
{
    FLIP_X = 1,
    FLIP_Y = 2,
};

#ifdef GCC
#define PACKED __attribute__((__packed__))
#else
#define PACKED
#pragma pack(1) //These structures should be laid out as written without alignment
#endif

struct TGAHeader_struct
{
    u8 id_length;   //Length of image id field
    u8 color_map_type;  //0 = None, 1 = Present, 2-127 = Reserved, 128-255 = User
    u8 image_type;  //TGACompressionType
    u16 color_map_first_entry;  //Which is the first value stored
    //if you only used colors 128-255, you can just save those colors
    u16 color_map_length;   //Number of color map entries
    u8 color_map_entry_size;    //Number of bits per pixel
    u16 xorigin;    //Absolute coordinates of lower left
    u16 yorigin;    //Absolute coordinates of lower left
    u16 image_width;    //Width in pixels
    u16 image_height;   //Height in pixels
    u8 pixel_depth; //Bits per pixel
    u8 image_descriptor; //Bits 3-0 give the alpha channel depth, Bits 5-4 give direction
} PACKED;

typedef struct TGAHeader_struct TGAHeader;

struct TGADateTime_struct
{
    u16 month;  //1-12
    u16 day;    //1-31
    u16 year;   //4 digit year
    u16 hour;   //0-23
    u16 minute; //0-59
    u16 second; //0-59
} PACKED;

typedef struct TGADateTime_struct TGADateTime;

struct TGAExtension_struct
{
    u16 extension_size; //Size of the extension area (495 bytes)
    char author[41];    //Author name (0 terminated)
    char comment[324];  //4 lines of 80 characters (0 terminated)
    TGADateTime datetime;   //12 bytes
    char jobname[41];   //Description of job (0 terminated)
    u16 hours;          //Time spent working on image (for billing etc)
    u16 minutes;        //Time spent working on image (for billing etc)
    u16 seconds;        //Time spent working on image (for billing etc)
    char software[41];  //Software the generated file (0 terminated)
    u16 softwave_version;   //Software version times 100, so 3.14 would be 314 (Set to 0 if not used)
    char software_letter;   //And version A (set to space if not used)
    u8 color_key_a;     //Transparent color
    u8 color_key_r;
    u8 color_key_g;
    u8 color_key_b;
    u16 pixel_ratio_numerator;      //For example 4/3 16/9
    u16 pixel_ratio_denominator;    //If denominator is 0, then no ratio specified
    u16 gamma_numerator;        //Should be in the range 0.0-10.0
    u16 gamma_denominator;  //If denominator is 0, then no ratio specified
    u32 color_correction_offset;    //Number of bytes to the color correction data
    u32 postage_stamp_offset;   //Offset to the image thumbnail
    u32 scanline_offset;    //Offset to the scanlines
    u8 attributes_type;     //Specifies the alpha channel
} PACKED;

typedef struct TGAExtension_struct TGAExtension;

struct TGAFooter_struct
{
    u32 extension_offset;   //Offset to the TGAExtension
    u32 developer_area_offset;  //Offset to developer area
    char signature[18];     //"TRUEVISION-XFILE." (0 terminated)
} PACKED;

typedef struct TGAFooter_struct TGAFooter;

#ifdef GCC
#else
#pragma pack()  //Restore default alignment
#endif

u8 (*RGBToGray)(int r,int g,int b); //Function pointer that remaps RGB to Gray
int (*writePixel)(u32 argb,u8 *dst);    //Function pointer that writes a pixel

//http://www.johndcook.com/blog/2009/08/24/algorithms-convert-color-grayscale/

static u8 RGB2GrayLuminosity(int r,int g,int b)
{
//  return g * .59 + r * .3 + g * .11;  //The actual code, but we avoid floating point
    int gray = ((g * 150) >> 8) + ((r * 153) >> 9) + ((g * 28) >> 8);
    if (gray < 0) gray = 0;
    if (gray > 255) gray = 255;
    return (u8)gray;
}

static u8 RGB2GrayAverage(int r,int g,int b)
{
    int gray = (r + g + b) / 3;
    if (gray < 0) gray = 0;
    if (gray > 255) gray = 255;
    return (u8)gray;
}

static u8 RGB2GrayLightness(int r,int g,int b)
{
    int min = r < g ? r : g;
    int max = r > g ? r : g;
    int gray;
    min = min < b ? min : b;
    max = max > b ? max : b;
    gray = (max + min) / 2;
    if (gray < 0) gray = 0;
    if (gray > 255) gray = 255;
    return (u8)gray;
}

//http://www.tannerhelland.com/3643/grayscale-image-algorithm-vb6/
static u8 RGB2GrayMin(int r,int g,int b)
{
    int min = r < g ? r : g;
    min = min < b ? min : b;
    return (u8)min;
}

static u8 RGB2GrayMax(int r,int g,int b)
{
    int max = r > g ? r : g;
    max = max > b ? max : b;
    return (u8)max;
}

static u8 RGB2GrayRed(int r,int g,int b)
{
    return (u8)r;
}

static u8 RGB2GrayGreen(int r,int g,int b)
{
    return (u8)g;
}

static u8 RGB2GrayBlue(int r,int g,int b)
{
    return (u8)b;
}

static int WriteGreyPixel(u32 argb,u8 *dst)
{
    u8 r,g,b;
    b = (u8)(argb >> 24);
    g = (u8)(argb >> 16);
    r = (u8)(argb >> 8);
    *dst = (*RGBToGray)(r,g,b);
    return 1;
}

static int Write32BitPixel(u32 argb,u8 *dst)
{
    u8 a,r,g,b;
    a = (u8)(argb >> 24);
    r = (u8)(argb >> 16);
    g = (u8)(argb >> 8);
    b = (u8)argb;
    *dst++ = b;
    *dst++ = g;
    *dst++ = r;
    *dst++ = a;
    return 4;
}

//Read a short from an unaligned address in little endian format
static u16 TGAReadUShort(u16* val)
{
    //This is inefficient (but it is safe on all architectures, including endian)
    u8* mem = (u8*)val;
    return mem[0] + (mem[1] << 8);
}

//Read an int from an unaligned address in little endian format
static u32 TGAReadUInt(u32* val)
{
    //This is inefficient (but it is safe on all architectures, including endian)
    u8* mem = (u8*)val;
    return mem[0] + (mem[1] << 8) + (mem[2] << 16) + (mem[3] << 24);
}

//Write a short to an unaligned address in little endian format
static void TGAWriteUShort(u16 val,u16 *address)
{
    //This is inefficient (but it is safe on all architectures, including endian)
    u8* mem = (u8*)address;
    mem[0] = (u8)val;
    mem[1] = (u8)(val >> 8);
}

//Write an int to an unaligned address in little endian format
static void TGAWriteUInt(u32 val,u32 *address)
{
    //This is inefficient (but it is safe on all architectures, including endian)
    u8* mem = (u8*)address;
    mem[0] = (u8)val;
    mem[1] = (u8)(val >> 8);
    mem[2] = (u8)(val >> 16);
    mem[3] = (u8)(val >> 24);
}

//Convert value to grey (duplicate in RGB)
static u32 grey(int col,int alpha)
{
    return col + (col << 8) + (col << 16) + (alpha << 24);
}

//Read a color value, with 15, 16, 24, or 32 bits per pixel
static u32 color(u8 *data,int bitsPerPixel,u8 alpha)
{
    int rgba = TGAReadUInt((u32*)data); //only true for 32 bit, but the others can be extracted
    //and this makes the code, endian independant
    u8 r,g,b;

    assert(bitsPerPixel == 15 || bitsPerPixel == 16 || bitsPerPixel == 24 || bitsPerPixel == 32);

    switch (bitsPerPixel)
    {
    case 15:
    case 16:
        r = (u8)((rgba >> 10)<<3);
        g = (u8)((rgba >> 5)<<3);
        b = (u8)(rgba<<3);
        break;
    case 24:
        r = (u8)(rgba >> 16);
        g = (u8)(rgba >> 8);
        b = (u8)rgba;
        break;
    case 32:
        alpha = (u8)(rgba >> 24);
        r = (u8)(rgba >> 16);
        g = (u8)(rgba >> 8);
        b = (u8)rgba;
        break;
    }

    return (alpha << 24) + (r << 16) + (g << 8) + b;
}

//Write a value
void write(int val,u32 *image)
{
    u8* bytes = (u8*)image;
    bytes[0] = (u8)(val & 0xff);
    bytes[1] = (u8)((val >> 8) & 0xff);
    bytes[2] = (u8)((val >> 16) & 0xff);
    bytes[3] = (u8)((val >> 24) & 0xff);
}

//Reads a TGA file from memory, and returns pointer to ARGB data
u32* TGARead(int *width,int *height,u8 *memory,int size,int *error)
{
    TGAHeader* header;
    u8* colorMap = NULL;    //For paletted files
    int bytesPerColor = 0;  //How many bytes per pixel in color map table
    u8* imageData;  //The raw pixel data
    u32* image;     //The output ARGB buffer
    u32* writeImage;    //Used to write to the ARGB buffer
    u8 alpha = 255; //Alpha value to put into ARGB buffer if none present in file
//  u8 readAlpha;   //How many bytes will we be reading from file
    int rle;    //Are we processing RLE file
    u32 rleVal; //Last RLE value
    int rleCount;   //How many instances of RLE value left
    int rleUnique;  //How many unique values do we need to read
    int colorMapped;
    int greyScale;
    int bitsPerPixel;

    //Can't be valid if too small, this check also stops accesses to memory that was not allocated
    if (size < sizeof(TGAFooter))
    {
        *error = NOT_TGA;
        return NULL;
    }
    header = (TGAHeader*)memory;    //Provide easy access to the header

    if (header->color_map_type > 1 ||
        header->image_type > RLE_BLACK_AND_WHITE ||
        header->pixel_depth > 32 ||
        header->image_descriptor > 63)  //Check for invalid values (no signature on TGA 1 files)
    {
        *error = NOT_TGA;
        return NULL;    //Doesn't appear to be a TGA file
    }

    rle = header->image_type >= RLE_COLOR_MAPPED;   //Compressed files are stored in RLE format
    colorMapped = (header->image_type & 3) == UNCOMPRESSED_COLOR_MAPPED;
    greyScale = (header->image_type & 3) == UNCOMPRESSED_BLACK_AND_WHITE;
//  readAlpha = ((header->image_descriptor & 15) + 7) >> 3; //How many bytes of alpha are present

    *width = TGAReadUShort(&header->image_width);   //Stored as little endian
    *height = TGAReadUShort(&header->image_height);

    bitsPerPixel = header->pixel_depth; //Is this set, on true color images? Specs imply it isn't but the information does not occur elsewhere

    size = *width * *height;    //Total number of pixels

    if (size <= 0)  //If width or height is 0 (or too large > 46000 pixels in x & y)
    {
        *error = NOT_TGA;
        return NULL;    //Not a TGA file
    }

    if (colorMapped)    //If we have color
    {
        bytesPerColor = (header->color_map_entry_size + 7) >> 3;
        colorMap = memory + sizeof(TGAHeader) + header->id_length;  //colorMap starts here
        imageData = colorMap + (TGAReadUShort(&header->color_map_length) * bytesPerColor);  //And ends with image data
//      imageData = colorMap + TGAReadUShort(&header->color_map_length);    //And ends with image data
        colorMap -= bytesPerColor * TGAReadUShort(&header->color_map_first_entry);  //Colors below color_map_first_entry are invalid
        bitsPerPixel = header->color_map_entry_size;
    }
    else
    {
        bytesPerColor = (bitsPerPixel + 7) >> 3;    //1 byte for grayscale, 2 bytes for 15/16 bits, 3 bytes for 24 bits, 4 bytes for 32 bits
        imageData = memory + sizeof(TGAHeader) + header->id_length; //Image data starts here
    }

    image = (u32*)malloc(size * 4); //4 bytes per pixel (ARGB)

    if (!image)
    {
        *error = OUT_OF_MEMORY;
        return NULL;    //say the malloc files due to lack of memory
    }

    writeImage = image; //We will write ARGB here, but we need to return the start

    rleCount = 0;
    rleUnique = 0;
    if (!rle) rleUnique = size; //Treat the entire image as rle unique

    while (size)    //If there are pixels left, keep processing
    {
        if (rleUnique)  //If were are processing unique then we read data
        {
            size--;
            rleUnique--;
            if (colorMapped)
            {
                u8* colorTable = colorMap + *imageData++ * bytesPerColor;
//              if (readAlpha) alpha = *imageData++;
                rleVal = color(colorTable,bitsPerPixel,alpha);
            }
            else if (greyScale)
            {
                int greyVal = *imageData++;
//              if (readAlpha) alpha = *imageData++;
                rleVal = grey(greyVal,alpha);
            }
            else //RGB, or RGBA (16 bit, 24 bit, 32 bit)
            {
                rleVal = color(imageData,bitsPerPixel,alpha);
                imageData += bytesPerColor;
            }
            write(rleVal,writeImage++);
        }
        else if (rleCount)
        {
            size--;
            rleCount--;
            write(rleVal,writeImage++);
        }
        else
        {
            if (*imageData >= 128)
            {
                rleCount = *imageData++ & 0x7f;
                rleUnique = 1;  //Just so we read the rleVal (we rleCount 1 less than actual)
            }
            else
            {
                rleUnique = *imageData++ + 1;
            }
        }
    }

    return image;
}

//Saves a TGA file in memory, colors gives the format (0 = Gray Scale)
//and returns pointer to TGA file, sets size to the size of the data
//Only colors = 0 is supported at the moment
//Returns NULL if unable to write the file
u8* TGAWrite(int width,int height,int *size,int colors,u8 *memory,u32 *data,int *error,int flags)
{
    u8* newTGA;
    TGAHeader* header;
    TGAHeader* newHeader;
    TGAFooter* footer;
    TGAFooter* newFooter;
    TGAExtension* extension = NULL; //Only present in TGA 2.0+ file
    TGAExtension* newExtension;
    u8* newImage;
    int tga2;
    int left;
    int bytesPerPixel;

//  colors = -1;    //Force TRUE COLOR, useful for testing
    assert(colors == 0 || colors == -1);    //So we can add extra support later

    header = (TGAHeader*)memory;    //Provide easy access to the header
    footer = (TGAFooter*)(memory+*size-sizeof(TGAFooter));

    if (header->id_length)
    {
        u8* end = memory + sizeof(TGAHeader)+header->id_length;
        u8 save = *end;
        *end = 0;
        printf("Image Identification:%s\n",memory+sizeof(TGAHeader));
        *end = save;
    }

    bytesPerPixel = (colors + 255) >> 8;    //1,2,3 for Color Indexed, 16 bit, 24 bit
    if (colors < 0) bytesPerPixel = 4;  //Handle the case of 32 bit
    if (!colors) bytesPerPixel = 1; //1 byte per pixel for Gray

    *size = sizeof(TGAHeader) + sizeof(TGAFooter) + width * height * bytesPerPixel + header->id_length;

    tga2 = !strcmp((const char*)footer->signature,"TRUEVISION-XFILE.");
    if (tga2)
    {
        int extension_offset = TGAReadUInt(&footer->extension_offset);
        if (extension_offset)
        {
            extension = (TGAExtension*)(memory + extension_offset);
            printf("Author:%s\n",extension->author);
            printf("Comment:%s\n",extension->comment);
            printf("Job name:%s\n",extension->jobname);
            printf("Software:%s %f%c\n",extension->software,TGAReadUShort(&extension->softwave_version)/100.0,extension->software_letter);
            *size += TGAReadUShort(&extension->extension_size);
        }
    }

    newTGA = (u8*)malloc(*size);
    newHeader = (TGAHeader*)newTGA;
    memcpy(newHeader,header,sizeof(TGAHeader) + header->id_length);
    newHeader->color_map_entry_size = 0;
    newHeader->color_map_first_entry = 0;
    newHeader->color_map_length = 0;
    newHeader->color_map_type = 0;

    if (flags & FLIP_X)
    {
        newHeader->image_descriptor ^= 0x10;
    }
    if (flags & FLIP_Y)
    {
        newHeader->image_descriptor ^= 0x20;
    }

    switch (colors)
    {
    case 0:
        newHeader->pixel_depth = 8;
        newHeader->image_type = UNCOMPRESSED_BLACK_AND_WHITE;
        writePixel = &WriteGreyPixel;
        break;
    case -1:
        newHeader->pixel_depth = 32;
        newHeader->image_type = UNCOMPRESSED_TRUE_COLOR;
        writePixel = &Write32BitPixel;
        break;
    }
    newFooter = (TGAFooter*)(newTGA + *size - sizeof(TGAFooter));
    strcpy(newFooter->signature,"TRUEVISION-XFILE.");
    newFooter->developer_area_offset = 0;
    newFooter->extension_offset = 0;
    if (extension)
    {
        newExtension = (TGAExtension*)((u8*)newFooter - sizeof(TGAExtension));
        memcpy(newExtension,extension,TGAReadUShort(&extension->extension_size));
        newFooter->extension_offset = ((u8*)newExtension - newTGA);
    }

    newImage = newTGA + sizeof(TGAHeader) + header->id_length;

    left = width * height;
    while (left)
    {
        newImage += writePixel(*data++,newImage);
        left--;
    }

    return newTGA;
}

u8* readFile(const char* src, int* size)
{
    FILE *file;
    u8 *buffer;
    unsigned long fileLen;

    //Open file
    file = fopen(src, "rb");
    if (!file)
    {
        fprintf(stderr, "Unable to open file %s", src);
        return NULL;
    }

    //Get file length
    fseek(file, 0, SEEK_END);
    fileLen=ftell(file);
    *size = (int)fileLen;
    fseek(file, 0, SEEK_SET);

    //Allocate memory
    buffer=(u8*)malloc(fileLen+1);
    if (!buffer)
    {
        fprintf(stderr, "Memory error!");
        fclose(file);
        return NULL;
    }

    //Read file contents into buffer
    fread(buffer, fileLen, 1, file);
    fclose(file);

    return buffer;
}

void writeFile(const char *dst, u8* memory, int size)
{
    FILE *file;

    //Open file
    file = fopen(dst, "wb");
    if (!file)
    {
        fprintf(stderr, "Unable to open file %s", dst);
        return;
    }

    //Read file contents into buffer
    fwrite(memory, size, 1, file);
    fclose(file);
}

int convert(const char* src, const char* dst,int colors,int flags)
{
    int width, height,size;
    u8* memory;
    u32* image = NULL;
    u8* tga = NULL;
    int returnCode = OK;

//  memory = NULL; size = 0;    //Set these from read file
    memory = readFile(src, &size);

    if (memory)
    {
        image = TGARead(&width,&height,memory,size,&returnCode);
        if (image)
        {
            printf("Converting file %s\n",src);
            tga = TGAWrite(width,height,&size,colors,memory,image,&returnCode,flags);
            if (tga)
            {
                writeFile(dst,tga,size);
            }
            else
            {
                returnCode = UNABLE_TO_SAVE;
            }
        }   
    }
    else
    {
        returnCode = UNABLE_TO_LOAD;    //File not found
    }

    free(memory);
    free(tga);
    free(image);

    switch (returnCode)
    {
    case UNABLE_TO_LOAD:
        fprintf(stderr, "Unable to load %s\n",src);
        break;
    case NOT_TGA:
        fprintf(stderr, "%s is not a TGA file\n",src);
        break;
    case UNABLE_TO_SAVE:
        fprintf(stderr, "Unable to save %s\n",dst);
        break;
    case FILE_NOT_FOUND:
        fprintf(stderr, "File %s not found\n",src);
        break;
    case OUT_OF_MEMORY:
        fprintf(stderr, "Not enough memory\n",src);
        break;
    }
    return returnCode;
}

void help()
{
    printf("Welcome to TGA convert.\n");
    printf("Syntax: tga [option] source destination\n");
    printf("Options:");
    printf("-h,-?: These instructions:\n");
    printf("-32: Save as 32 bit color\n");
    printf("-L: Use luminosity (default) to convert to gray\n");
    printf("-a: Use avergage of r,g,b to convert to gray\n");
    printf("-l: Use lightness of r,g,b to convert to gray\n");
    printf("-m: Use minimum of r,g,b to convert to gray\n");
    printf("-M: Use maximum of r,g,b to convert to gray\n");
    printf("-r: Use red component to convert to gray\n");
    printf("-g: Use green component to convert to gray\n");
    printf("-b: Use blue component to convert to gray\n");
    printf("-x: Flip the image in X\n");
    printf("-y: Flip the image in Y\n");
}

int main(int argc, const char* argv[])
{
    int colors = 0;
    int src = 1;
    int dst = 2;
    int flags = 0;
    RGBToGray = RGB2GrayLuminosity;
    //If we have command line parameter
    if (argc > 1)
    {
        if (argv[1][0] == '-')
        {
            src++;
            dst++;
            switch (argv[1][1])
            {
            case '?':
            case 'h':
                help();
                return 0;
            case '3':
                colors = -1;
                break;
            case 'a':
                RGBToGray = RGB2GrayAverage;
                break;
            case 'l':
                RGBToGray = RGB2GrayLightness;
                break;
            case 'm':
                RGBToGray = RGB2GrayMin;
                break;
            case 'M':
                RGBToGray = RGB2GrayMax;
                break;
            case 'r':
                RGBToGray = RGB2GrayRed;
                break;
            case 'g':
                RGBToGray = RGB2GrayGreen;
                break;
            case 'b':
                RGBToGray = RGB2GrayBlue;
                break;
            case 'x':
                flags |= FLIP_X;
                break;
            case 'y':
                flags |= FLIP_Y;
                break;
            }
        }
    }
    else
    {
        help();
        return 0;
    }

    if (argc > dst)
    {
        convert(argv[src],argv[dst],colors,flags);
        return 0;
    }

    convert("samples\\CBW8.TGA","out\\CBW8.TGA",colors,flags);
    convert("samples\\CCM8.TGA","out\\CCM8.TGA",colors,flags);
    convert("samples\\CTC16.TGA","out\\CTC16.TGA",colors,flags);
    convert("samples\\CTC24.TGA","out\\CTC24.TGA",colors,flags);
    convert("samples\\CTC32.TGA","out\\CTC32.TGA",colors,flags);
    convert("samples\\earth.tga","out\\earth.tga",colors,flags);
    convert("samples\\earth_UTP32.tga","out\\earth_UTP32.tga",colors,flags);
    convert("samples\\FLAG_B16.TGA","out\\FLAG_B16.TGA",colors,flags);
    convert("samples\\FLAG_B24.TGA","out\\FLAG_B24.TGA",colors,flags);
    convert("samples\\FLAG_B32.TGA","out\\FLAG_B32.TGA",colors,flags);
    convert("samples\\FLAG_T16.TGA","out\\FLAG_T16.TGA",colors,flags);
    convert("samples\\FLAG_T32.TGA","out\\FLAG_T32.TGA",colors,flags);
    convert("samples\\MARBLES.TGA","out\\MARBLES.TGA",colors,flags);
    convert("samples\\shuttle.tga","out\\shuttle.tga",colors,flags);
    convert("samples\\UBW8.TGA","out\\UBW8.TGA",colors,flags);
    convert("samples\\UBW8_002.TGA","out\\UBW8_002.TGA",colors,flags);
    convert("samples\\UCM8.TGA","out\\UCM8.TGA",colors,flags);
    convert("samples\\UTC16.TGA","out\\UTC16.TGA",colors,flags);
    convert("samples\\UTC24.TGA","out\\UTC24.TGA",colors,flags);
    convert("samples\\UTC32.TGA","out\\UTC32.TGA",colors,flags);
    convert("samples\\XING_B16.TGA","out\\XING_B16.TGA",colors,flags);
    convert("samples\\XING_B24.TGA","out\\XING_B24.TGA",colors,flags);
    convert("samples\\XING_B32.TGA","out\\XING_B32.TGA",colors,flags);
    convert("samples\\XING_B_UCM8.tga","out\\XING_B_UCM8.tga",colors,flags);
    convert("samples\\XING_T16.TGA","out\\XING_T16.TGA",colors,flags);
    convert("samples\\XING_T24.TGA","out\\XING_T24.TGA",colors,flags);
    convert("samples\\XING_T32.TGA","out\\XING_T32.TGA",colors,flags);
    convert("samples\\XING_T_UCM8.tga","out\\XING_T_UCM8.tga",colors,flags);

    convert("tga8\\25_color.tga","out\\tga8\\25_color.tga",colors,flags);
    convert("tga8\\155_5572_jpg.tga","out\\tga8\\155_5572_jpg.tga",colors,flags);
    convert("tga8\\34445.tga","out\\tga8\\34445.tga",colors,flags);
    convert("tga8\\arctichare.tga","out\\tga8\\arctichare.tga",colors,flags);
    convert("tga8\\balls0_color.tga","out\\tga8\\balls0_color.tga",colors,flags);
    convert("tga8\\butterfly.tga","out\\tga8\\butterfly.tga",colors,flags);
    convert("tga8\\C8TZ7768.tga","out\\tga8\\C8TZ7768.tga",colors,flags);
    convert("tga8\\ColorsPastel.tga","out\\tga8\\ColorsPastel.tga",colors,flags);
    convert("tga8\\ColorWheelEqLum200.tga","out\\tga8\\ColorWheelEqLum200.tga",colors,flags);
    convert("tga8\\DSCN9952.tga","out\\tga8\\DSCN9952.tga",colors,flags);
    convert("tga8\\fruits.tga","out\\tga8\\fruits.tga",colors,flags);
    convert("tga8\\girl.tga","out\\tga8\\girl.tga",colors,flags);
    convert("tga8\\IM2-color.tga","out\\tga8\\IM2-color.tga",colors,flags);
    convert("tga8\\impatient_color.tga","out\\tga8\\impatient_color.tga",colors,flags);
    convert("tga8\\kodim03.tga","out\\tga8\\kodim03.tga",colors,flags);
    convert("tga8\\monarch.tga","out\\tga8\\monarch.tga",colors,flags);
    convert("tga8\\portrait_4v.tga","out\\tga8\\portrait_4v.tga",colors,flags);
    convert("tga8\\ramp.tga","out\\tga8\\ramp.tga",colors,flags);
    convert("tga8\\serrano.tga","out\\tga8\\serrano.tga",colors,flags);
    convert("tga8\\Ski_TC8-03_sRGB.tga","out\\tga8\\Ski_TC8-03_sRGB.tga",colors,flags);
    convert("tga8\\Sunrise312.tga","out\\tga8\\Sunrise312.tga",colors,flags);
    convert("tga8\\text.tga","out\\tga8\\text.tga",colors,flags);
    convert("tga8\\tree_color.tga","out\\tga8\\tree_color.tga",colors,flags);
    convert("tga8\\tulips.tga","out\\tga8\\tulips.tga",colors,flags);
    convert("tga8\\watch.tga","out\\tga8\\watch.tga",colors,flags);

    convert("tga24\\25_color.tga","out\\tga24\\25_color.tga",colors,flags);
    convert("tga24\\155_5572_jpg.tga","out\\tga24\\155_5572_jpg.tga",colors,flags);
    convert("tga24\\34445.tga","out\\tga24\\34445.tga",colors,flags);
    convert("tga24\\arctichare.tga","out\\tga24\\arctichare.tga",colors,flags);
    convert("tga24\\balls0_color.tga","out\\tga24\\balls0_color.tga",colors,flags);
    convert("tga24\\butterfly.tga","out\\tga24\\butterfly.tga",colors,flags);
    convert("tga24\\C8TZ7768.tga","out\\tga24\\C8TZ7768.tga",colors,flags);
    convert("tga24\\ColorsPastel.tga","out\\tga24\\ColorsPastel.tga",colors,flags);
    convert("tga24\\ColorWheelEqLum200.tga","out\\tga24\\ColorWheelEqLum200.tga",colors,flags);
    convert("tga24\\DSCN9952.tga","out\\tga24\\DSCN9952.tga",colors,flags);
    convert("tga24\\fruits.tga","out\\tga24\\fruits.tga",colors,flags);
    convert("tga24\\girl.tga","out\\tga24\\girl.tga",colors,flags);
    convert("tga24\\IM2-color.tga","out\\tga24\\IM2-color.tga",colors,flags);
    convert("tga24\\impatient_color.tga","out\\tga24\\impatient_color.tga",colors,flags);
    convert("tga24\\kodim03.tga","out\\tga24\\kodim03.tga",colors,flags);
    convert("tga24\\monarch.tga","out\\tga24\\monarch.tga",colors,flags);
    convert("tga24\\portrait_4v.tga","out\\tga24\\portrait_4v.tga",colors,flags);
    convert("tga24\\ramp.tga","out\\tga24\\ramp.tga",colors,flags);
    convert("tga24\\serrano.tga","out\\tga24\\serrano.tga",colors,flags);
    convert("tga24\\Ski_TC8-03_sRGB.tga","out\\tga24\\Ski_TC8-03_sRGB.tga",colors,flags);
    convert("tga24\\Sunrise312.tga","out\\tga24\\Sunrise312.tga",colors,flags);
    convert("tga24\\text.tga","out\\tga24\\text.tga",colors,flags);
    convert("tga24\\tree_color.tga","out\\tga24\\tree_color.tga",colors,flags);
    convert("tga24\\tulips.tga","out\\tga24\\tulips.tga",colors,flags);
    convert("tga24\\watch.tga","out\\tga24\\watch.tga",colors,flags);

    return 0;
}

Our C programming homework help is beyond doubt one of the best services being offered in our galaxy of offerings. C programming language can be demonstrated as the high level and general purpose language. Our C programming homework help benefits the students by getting them higher grades in their assignment. The C programming project help gives strong foundations in learning the programming in C language that is  helpful to students. C programming language can maneuver with the low level activities and is responsible for the evolution of efficient codes.