GLUSboolean GLUSAPIENTRY glusLoadTgaImage(const GLUSchar* filename, GLUStgaimage* tgaimage)
{
    FILE* file;
    GLUSubyte type;
    GLUSubyte bitsPerPixel;
	size_t elementsRead;

    // check, if we have a valid pointer
    if (!filename || !tgaimage)
    {
        return GLUS_FALSE;
    }

    tgaimage->width = 0;
    tgaimage->height = 0;
    tgaimage->depth = 0;
    tgaimage->data = 0;
    tgaimage->format = 0;
		
    // open filename in "read binary" mode
    file = fopen(filename, "rb");

    if (!file)
    {
        return GLUS_FALSE;
    }

    // seek through the tga header, up to the type:
    if(fseek(file, 2, SEEK_CUR))
	{
        fclose(file);

        return GLUS_FALSE;
	}

    // read the type
    elementsRead = fread(&type, 1, 1, file);

    if (!glusCheckFileRead(file, elementsRead, 1))
    {
        return GLUS_FALSE;
    }
		
    // check the type
    if (type != 2 && type != 10 && type != 11)
    {
        fclose(file);

        return GLUS_FALSE;
    }

    // seek through the tga header, up to the width/height:
    if(fseek(file, 9, SEEK_CUR))
	{
        fclose(file);

        return GLUS_FALSE;
	}

    // read the width
    elementsRead = fread(&tgaimage->width, 2, 1, file);

    if (!glusCheckFileRead(file, elementsRead, 1))
    {
        glusDestroyTgaImage(tgaimage);

        return GLUS_FALSE;
    }

    if (tgaimage->width > GLUS_MAX_DIMENSION)
    {
        glusDestroyTgaImage(tgaimage);

        return GLUS_FALSE;
    }
		
    // read the height
    elementsRead = fread(&tgaimage->height, 2, 1, file);

    if (!glusCheckFileRead(file, elementsRead, 1))
    {
        glusDestroyTgaImage(tgaimage);

        return GLUS_FALSE;
    }

    if (tgaimage->height > GLUS_MAX_DIMENSION)
    {
        glusDestroyTgaImage(tgaimage);

        return GLUS_FALSE;
    }

    tgaimage->depth = 1;

    // read the bits per pixel
    elementsRead = fread(&bitsPerPixel, 1, 1, file);

    if (!glusCheckFileRead(file, elementsRead, 1))
    {
        glusDestroyTgaImage(tgaimage);

        return GLUS_FALSE;
    }
	
    // check the pixel depth
    if (bitsPerPixel != 8 && bitsPerPixel != 24 && bitsPerPixel != 32)
    {
        fclose(file);
        return GLUS_FALSE;
    }
    else
    {
        tgaimage->format = GLUS_LUMINANCE;
        if (bitsPerPixel == 24)
        {
            tgaimage->format = GLUS_RGB;
        }
        else if (bitsPerPixel == 32)
        {
            tgaimage->format = GLUS_RGBA;
        }
    }

    // move file pointer to beginning of targa data
    if(fseek(file, 1, SEEK_CUR))
	{
		fclose(file);
	
        glusDestroyTgaImage(tgaimage);

        return GLUS_FALSE;
	}

    // allocate enough memory for the targa  data
    tgaimage->data = (GLUSubyte*) malloc((size_t)tgaimage->width * tgaimage->height * bitsPerPixel / 8);

    // verify memory allocation
    if (!tgaimage->data)
    {
        fclose(file);
		
		glusDestroyTgaImage(tgaimage);
		
        return GLUS_FALSE;
    }

    if (type == 2)
    {
        // read in the raw data
        elementsRead = fread(tgaimage->data, 1, (size_t)tgaimage->width * tgaimage->height * bitsPerPixel / 8, file);

        if (!glusCheckFileRead(file, elementsRead, (size_t)tgaimage->width * tgaimage->height * bitsPerPixel / 8))
        {
            glusDestroyTgaImage(tgaimage);

            return GLUS_FALSE;
        }
    }
    else
    {
        // RLE encoded
        GLUSint pixelsRead = 0;

        while (pixelsRead < tgaimage->width * tgaimage->height)
        {
            GLUSubyte amount;

            elementsRead = fread(&amount, 1, 1, file);

            if (!glusCheckFileRead(file, elementsRead, 1))
            {
                glusDestroyTgaImage(tgaimage);

                return GLUS_FALSE;
            }
			
            if (amount & 0x80)
            {
                GLUSint i;
                GLUSint k;

                amount &= 0x7F;

                amount++;

                // read in the rle data
                elementsRead = fread(&tgaimage->data[pixelsRead * bitsPerPixel / 8], 1, bitsPerPixel / 8, file);

                if (!glusCheckFileRead(file, elementsRead, bitsPerPixel / 8))
                {
                    glusDestroyTgaImage(tgaimage);

                    return GLUS_FALSE;
                }
				
                for (i = 1; i < amount; i++)
                {
                    for (k = 0; k < bitsPerPixel / 8; k++)
                    {
                        tgaimage->data[(pixelsRead + i) * bitsPerPixel / 8 + k] = tgaimage->data[pixelsRead * bitsPerPixel / 8 + k];
                    }
                }
            }
            else
            {
                amount &= 0x7F;

                amount++;

                // read in the raw data
                elementsRead = fread(&tgaimage->data[pixelsRead * bitsPerPixel / 8], 1, (size_t) amount * bitsPerPixel / 8, file);
				
                if (!glusCheckFileRead(file, elementsRead, (size_t) amount * bitsPerPixel / 8))
                {
                    glusDestroyTgaImage(tgaimage);

                    return GLUS_FALSE;
                }				
            }

            pixelsRead += amount;
        }
    }

    // swap the color if necessary
    if (bitsPerPixel == 24 || bitsPerPixel == 32)
    {
        glusSwapColorChannel(tgaimage->width, tgaimage->height, tgaimage->format, tgaimage->data);
    }

    // close the file
    fclose(file);

    return GLUS_TRUE;
}
Exemple #2
0
GLUSboolean GLUSAPIENTRY glusSaveTgaImage(const GLUSchar* filename, const GLUStgaimage* tgaimage)
{
	FILE* file;
	GLUSubyte buffer[12];
	GLUSubyte bitsPerPixel;
	size_t elementsWritten;
	GLUSubyte* data;

	// check, if we have a valid pointer
	if (!filename || !tgaimage)
	{
		return GLUS_FALSE;
	}

	// open filename in "write binary" mode
	file = fopen(filename, "wb");

	if (!file)
	{
		return GLUS_FALSE;
	}

	switch (tgaimage->format)
	{
		case GLUS_ALPHA:
		case GLUS_LUMINANCE:
			bitsPerPixel = 8;
		break;
		case GLUS_RGB:
			bitsPerPixel = 24;
		break;
		case GLUS_RGBA:
			bitsPerPixel = 32;
		break;
		default:
			fclose(file);
			return GLUS_FALSE;
	}

	if (bitsPerPixel == 8)
	{
		buffer[2] = 3;
	}
	else
	{
		buffer[2] = 2;
	}

	// TGA header
	buffer[0] = 0;
	buffer[1] = 0;

	buffer[3] = 0;
	buffer[4] = 0;
	buffer[5] = 0;
	buffer[6] = 0;
	buffer[7] = 0;
	buffer[8] = 0;
	buffer[9] = 0;
	buffer[10] = 0;
	buffer[11] = 0;

	elementsWritten = fwrite(buffer, 1, 12, file);

	if (!glusCheckFileWrite(file, elementsWritten, 12))
	{
		return GLUS_FALSE;
	}

	elementsWritten = fwrite(&tgaimage->width, 1, sizeof(tgaimage->width), file);

	if (!glusCheckFileWrite(file, elementsWritten, 2))
	{
		return GLUS_FALSE;
	}

	elementsWritten = fwrite(&tgaimage->height, 1, sizeof(tgaimage->height), file);

	if (!glusCheckFileWrite(file, elementsWritten, 2))
	{
		return GLUS_FALSE;
	}

	elementsWritten = fwrite(&bitsPerPixel, 1, sizeof(bitsPerPixel), file);

	if (!glusCheckFileWrite(file, elementsWritten, 1))
	{
		return GLUS_FALSE;
	}

	buffer[0] = 0;

	elementsWritten = fwrite(buffer, 1, 1, file);

	if (!glusCheckFileWrite(file, elementsWritten, 1))
	{
		return GLUS_FALSE;
	}

	data = malloc(tgaimage->width * tgaimage->height * bitsPerPixel / 8);

	if (!data)
	{
		fclose(file);

		return GLUS_FALSE;
	}

	memcpy(data, tgaimage->data, tgaimage->width * tgaimage->height * bitsPerPixel / 8);

	if (bitsPerPixel >= 24)
	{
		glusSwapColorChannel(tgaimage->width, tgaimage->height, tgaimage->format, data);
	}

	elementsWritten = fwrite(data, 1, tgaimage->width * tgaimage->height * bitsPerPixel / 8, file);

	free(data);

	if (!glusCheckFileWrite(file, elementsWritten, tgaimage->width * tgaimage->height * bitsPerPixel / 8))
	{
		return GLUS_FALSE;
	}

	fclose(file);

	return GLUS_TRUE;
}