⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 image.cpp

📁 体现了lod(level of detail)算法 包括网格细分,空间层次
💻 CPP
字号:
/*
	image.c			Copyright (C) 1998-1999 Damir Sagidullin
*/
#include <stdlib.h>
#include <stdio.h>

#include "unpak.h"
//#include "console.h"
#include "image.h"

//------------------- DEFINITIONS & CONSTANTS -------------------//

#pragma pack (push, 1)
typedef struct
{// targa file header
	byte	id_length;
	byte	colormap_type;
	byte	image_type;
	ushort	colormap_index;
	ushort	colormap_length;
	byte	colormap_size;
	ushort	x_origin, y_origin;
	ushort	width, height;
	byte	pixel_size;
	byte	attributes;
} tga_header_t;


typedef struct
{
	char	*data;
	int		width;
	int		height;
} picinfo_t;

//-------------------------- VARIABLES --------------------------//

static char	*filedata;

//-------------------------- FUNCTIONS --------------------------//

int		jpeg_decompress (char *buf, int size, picinfo_t *pi);

void	CalculateImageColor (bitmap *bm);

int		TargaDecode (bitmap *bm, byte *data, int size, char *name);
int		JpegDecode (bitmap *bm, char *data, int size, char *name);

int		ReadImage (bitmap *bm, char *name, packfile_t *pf)
{
	int		size;
	char	*data, *file_ext;
	int		result;

	bm->data = NULL;
	bm->texturenum = -1;

	if((size = PackFileGet (pf, name, &data)) <=0 )	return FALSE;

	file_ext = strchr (name, '.');
	if (file_ext == NULL)
	{
		MessageBox(NULL, "Unknown image \"%s\" format", "Error", NULL);
		return FALSE;
	}

	if (!strcmp (file_ext, ".tga"))
		result = TargaDecode (bm , (byte *)data, size, name);
	else
	if (!strcmp (file_ext, ".jpg"))
		result = JpegDecode (bm , data, size, name);
	else
	{
		MessageBox(NULL, "Unknown image \"%s\" format", "Error", NULL);
		return FALSE;
	}

	free (data);

	if (result) CalculateImageColor (bm);

	return result;
}

void	CalculateImageColor (bitmap *bm)
{
	int		red, green, blue, gray;
	int		i, numPixels;
	byte	*src;

	if (bm->data == NULL) return;

	red = green = blue = gray = 0;
	i = numPixels = bm->width * bm->height;
	src = (byte *)bm->data;

	if (bm->bpp == 24)
	{
		while ((i--) > 0)
		{
			red += *src++;
			green += *src++;
			blue += *src++;
		}
	} else
	if (bm->bpp == 32)
	{
		while ((i--) > 0)
		{
			red += *src++;
			green += *src++;
			blue += *src++;
			src++;
		}
	} else
	if (bm->bpp == 8)
	{
		while ((i--) > 0)
		{
			gray += *src++;
		}
		red = green = blue = gray;
	}
	bm->r = red / numPixels;
	bm->g = green / numPixels;
	bm->b = blue / numPixels;
}

int		TargaDecode (bitmap *bm, byte *data, int size, char *name)
{
	int		width, height, numPixels;
	int		row, column;
	byte	red, green, blue, alpha;
	byte	packetHeader, packetSize, j;
	byte	bytesPerPixel;
	byte	*rgba, *dest;
	tga_header_t	*header;

	header = (tga_header_t *)data;
	data += sizeof(tga_header_t);

	// Only types 2 and 10 are supported
	if (header->image_type!=2 && header->image_type!=10)
	{;
		MessageBox(NULL, "Unsupported tga image \"%s\" type (type=%d)", "Error", NULL);
		return FALSE;
	}

	// Only 24bit or 32bit pixels are supported
	if ((header->colormap_type!=0)
	||	(header->pixel_size!=32 && header->pixel_size!=24))
	{
		MessageBox(NULL, "Unsupported tga image \"%s\" pixel size (size=%d)", "Error", NULL);
		return FALSE;
	}

	bm->width = width = header->width;
	bm->height = height = header->height;
	bm->bpp = header->pixel_size;

	numPixels = width * height;
	bytesPerPixel = (header->pixel_size == 32) ? 4 : 3;

	// Allocate memory for decoded image
	rgba = (byte *)malloc(numPixels * bytesPerPixel);
	if (!rgba)
	{
		MessageBox(NULL, "Can't allocate memory (size=%d)", "Error", NULL);
		return FALSE;
	}

	if (header->image_type == 2)
	{// Uncompressed RGB image
		row = height;
		while ((row--) > 0)
		{
			if (header->attributes & 0x20)
				dest = rgba + (height - row - 1)*width*bytesPerPixel;
			else
				dest = rgba + row*width*bytesPerPixel;
			for (column=0; column<width; column++)
			{
				if (header->pixel_size == 24)
				{
					blue = *data++;
					green = *data++;
					red = *data++;
					*dest++ = red;
					*dest++ = green;
					*dest++ = blue;
				} else
				if (header->pixel_size == 32)
				{
					blue = *data++;
					green = *data++;
					red = *data++;
					alpha = *data++;
					*dest++ = red;
					*dest++ = green;
					*dest++ = blue;
					*dest++ = alpha;
				}
			}
		}
	} else
	if (header->image_type==10)
	{// RLE RGB image
		row = height;
		while ((row--) > 0)
		{
			if (header->attributes & 0x20)
				dest = rgba + (height - row - 1)*width*bytesPerPixel;
			else
				dest = rgba + row*width*bytesPerPixel;
			for (column=0; column<width; )
			{
				packetHeader = *data++;
				packetSize = 1 + (packetHeader & 0x7f);
				// RLE packet
				if (packetHeader & 0x80)
				{
					if (header->pixel_size==24)
					{
						blue = *data++;
						green = *data++;
						red = *data++;
					} else
					if (header->pixel_size==32)
					{
						blue = *data++;
						green = *data++;
						red = *data++;
						alpha = *data++;
					}
					for (j=0; j<packetSize; j++)
					{
						*dest++ = red;
						*dest++ = green;
						*dest++ = blue;
						if(header->pixel_size==32) *dest++ = alpha;
						column++;
						if (column == width)
						{
							column = 0;
							if (row > 0) row--;
							else goto end_decode;
							if (header->attributes & 0x20)
								dest = rgba + (height - row - 1)*width*bytesPerPixel;
							else
								dest = rgba + row*width*bytesPerPixel;
						}
					}
				} else
				{// Non-RLE packet
					for (j=0; j<packetSize; j++)
					{
						if (header->pixel_size == 24)
						{
							blue = *data++;
							green = *data++;
							red = *data++;
							*dest++ = red;
							*dest++ = green;
							*dest++ = blue;
						} else
						{
							blue = *data++;
							green = *data++;
							red = *data++;
							alpha = *data++;
							*dest++ = red;
							*dest++ = green;
							*dest++ = blue;
							*dest++ = alpha;
						}
						column++;
						if (column == width)
						{
							column = 0;
							if (row > 0) row--;
							else goto end_decode;
							if (header->attributes & 0x20)
								dest = rgba + (height - row - 1)*width*bytesPerPixel;
							else
								dest = rgba + row*width*bytesPerPixel;
						}						
					}
				}
			}
			end_decode:;
		}
	}

	bm->data = (byte *)rgba;
	return TRUE;
}

int		JpegDecode (bitmap *bm, char *data, int size, char *name)
{
	picinfo_t	pi;

	if (jpeg_decompress (data, size, &pi))
	{
		MessageBox(NULL, "Can't decompress jpeg image \"%s\"", "Error", NULL);
		return FALSE;
	}

	bm->data = (byte *)pi.data;
	bm->width = pi.width;
	bm->height = pi.height;
	bm->bpp = 24;

	return TRUE;;
}

void	ConvertImageToGrayscale (bitmap *bm)
{
	int		i, numPixels;
	byte	*dest, *src;
	bitmap	src_bm = *bm;

	if (src_bm.data == NULL) return;

	i = numPixels = src_bm.width * src_bm.height;

	dest = (byte *)malloc (numPixels);
	src = (byte *)src_bm.data;

	bm->data = (byte *)dest;

	if (bm->bpp == 24)
		while ((i--)>0)
		{
			*dest++ = (*(src) + *(src+1) + *(src+2))/3;
			src += 3;
		}
	else
	if (bm->bpp == 32)
		while ((i--)>0)
		{
			*dest++ = (*(src) + *(src+1) + *(src+2))/3;
			src += 4;
		}

	bm->r = bm->g = bm->b = (bm->r + bm->g + bm->b)/3;
	bm->bpp = 8;

	free (src_bm.data);
}

void	ResizeImage (bitmap *bm, int width, int height)
{
	int		i, j, k, x, y, offset_y, offset_x, bytesPerPixel;
	byte	*dest, *src;
	bitmap	src_bm = *bm;

	if (!width || !height) return;
	if (src_bm.data == NULL)	return;

	bytesPerPixel = (src_bm.bpp + 1) >> 3;

	dest = (byte *)malloc (width * height * bytesPerPixel);
	src = (byte *)src_bm.data;

	bm->data = (byte *)dest;
	bm->width = width;
	bm->height = height;

	for (j=0; j<height; j++)
	{
		y = (j * src_bm.height) / height;
		offset_y = y * src_bm.width;
		for (i=0; i<width; i++)
		{
			x = (i * src_bm.width) / width;
			offset_x = (offset_y + x) * bytesPerPixel;

			for (k=0; k<bytesPerPixel; k++)
				*dest++ = src[offset_x++];
		}
	}
	free (src_bm.data);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -