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

📄 sprite.c

📁 一个曾经热门的网络游戏RO查看GRF工具的源码
💻 C
字号:
/*  libsprite - Library for reading Ragnarok Online sprite files. *  Copyright (C) 2004  Hongli Lai <h.lai@chello.nl> * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include <stdio.h>#include <stdlib.h>#include <string.h>#include "sprite.h"#ifdef __cplusplus	extern "C" {#endif /* __cplusplus *//*********************** * UTILITY FUNCTIONS ***********************//* StrBuf implements a string buffer that can dynamically grow. */typedef struct {	unsigned char *str;	int len;} StrBuf;static StrBuf *strbuf_new (){	StrBuf *buf;	buf = (StrBuf *) calloc (sizeof (StrBuf), 1);	buf->str = (unsigned char *) strdup ("");	return buf;}static voidstrbuf_append (StrBuf *buf, unsigned char *data, int len){	int offset;	if (len <= -1)		len = strlen ((char *) data);	offset = buf->len;	buf->len += len;	buf->str = (unsigned char *) realloc (buf->str, buf->len + 1);	memcpy (buf->str + offset, data, len);	buf->str[buf->len] = '\0';}static voidstrbuf_prepend (StrBuf *buf, unsigned char *data, int len){	unsigned char *str;	if (len <= -1)		len = strlen ((char *) data);	str = (unsigned char *) calloc (1, buf->len + len + 1);	memcpy (str, data, len);	memcpy (str + len, buf->str, buf->len);	free (buf->str);	buf->str = str;	buf->len += len;}static voidstrbuf_free (StrBuf *buf, int free_str){	if (buf) {		if (free_str && buf->str)			free (buf->str);		free (buf);	}}/* Repeat the string str num times.   Example: strrepeat("A", strlen("A"), 3) -> "AAA" */static char *strrepeat (char *str, int len, int num){	char *ret;	int i;	if (len <= -1)		len = strlen (str);	ret = (char *) calloc (1, len * num + 1);	for (i = 0; i < num; i++) {		memcpy (ret + len * num, str, len);	}	return ret;}static unsigned char *rle_decode(unsigned char *data, int datalen, int width, int *decoded_size){	StrBuf *buf, *retbuf;	unsigned char *ret, *tmp;	int extra, x;	buf = strbuf_new ();	retbuf = strbuf_new ();	extra = 4 - (width % 4);	if (extra == 4) extra = 0;	for (x = 0; x < datalen; x++) {		if (data[x] == 0) {			x++;			tmp = (unsigned char *) strrepeat ("", 1, (int) data[x]);			strbuf_append (buf, tmp, data[x]);			free (tmp);		} else			strbuf_append (buf, &(data[x]), 1);	}	for (x = 0; x < buf->len; x += width) {		if (extra > 0) {			tmp = (unsigned char *) strrepeat ("", 1, extra);			strbuf_prepend (retbuf, tmp, extra);			free (tmp);		}		strbuf_prepend (retbuf, buf->str + x, width);	}	ret = retbuf->str;	if (decoded_size) *decoded_size = retbuf->len;	strbuf_free (retbuf, 0);	strbuf_free (buf, 1);	return ret;}static unsigned char *reverse_palette (unsigned char *palette, int palettelen, int *returnsize){	StrBuf *retbuf;	unsigned char *ret;	int x;	retbuf = strbuf_new ();	for (x = 0; x < palettelen; x += 4) {		unsigned char tmp[4];		tmp[0] = palette[x + 2];		tmp[1] = palette[x + 1];		tmp[2] = palette[x];		tmp[3] = '\0';		strbuf_append (retbuf, tmp, 4);	}	ret = retbuf->str;	if (returnsize) *returnsize = retbuf->len;	strbuf_free (retbuf, 0);	return ret;}/********************** * PUBLIC FUNCTIONS **********************/SPREXPORT Sprite *sprite_open (const char *fname, SpriteError *error){	Sprite *sprite;	FILE *f;	unsigned char palette[1024], magic[5], buf[4];	int i, size;	if (!fname) {		if (error) *error = SE_BADARGS;		return NULL;	}	f = fopen ("4_deviruchi.spr", "rb");	if (!f) {		if (error) *error = SE_CANTOPEN;		return NULL;	}	/* Check file's "magic header" */	magic[4] = '\0';	fread (magic, 4, 1, f);	if (strcmp ((char *) magic, "SP\001\002") != 0) {		if (error) *error = SE_INVALID;		fclose (f);		return NULL;	}	/* Read the number of sprites */	fread (buf, 2, 1, f);	sprite = (Sprite *) calloc (sizeof (Sprite), 1);	sprite->nimages = (buf[1] << 8) + buf[0];	/* Read palette */	memset (&palette, 0, sizeof (palette));	fseek (f, -1024, SEEK_END);	fread (&palette, 1, 1024, f);	sprite->palette = (SpritePalette *) reverse_palette (palette, 1024, &size);	sprite->palette_size = size;	/* Now read the actual sprite data */	sprite->images = (SpriteImage *) calloc (sizeof (SpriteImage), sprite->nimages);	fseek (f, 8, SEEK_SET);	for (i = 0; i < sprite->nimages; i++) {		int width, height, compressed_len;		unsigned char *data, *ddata;		fread (buf, 2, 1, f);		width = (buf[1] << 8) + buf[0];		fread (buf, 2, 1, f);		height = (buf[1] << 8) + buf[0];		fread (buf, 2, 1, f);		compressed_len = (buf[1] << 8) + buf[0];		data = (unsigned char *) calloc (compressed_len, 1);		fread (data, compressed_len, 1, f);		ddata = rle_decode (data, compressed_len, width, &size);		free (data);		sprite->images[i].data = ddata;		sprite->images[i].len = size;		sprite->images[i].width = width;		sprite->images[i].height = height;	}	sprite->filename = strdup (fname);	return sprite;}SPREXPORT voidsprite_free (Sprite *sprite){	if (sprite) {		int i;		if (sprite->filename)			free (sprite->filename);		if (sprite->images)		{			for (i = 0; i < sprite->nimages; i++)				if (sprite->images[i].data)					free (sprite->images[i].data);			free (sprite->images);		}		if (sprite->palette)			free (sprite->palette);		free (sprite);	}}SPREXPORT void *sprite_to_bmp (Sprite *sprite, int i, int *size, SpriteError *error){	StrBuf *buf;	unsigned long file_size, offset, tmp;	unsigned short tmp2;	void *data;	/* Sanity check arguments */	if (!sprite || i < 0) {		if (error) *error = SE_BADARGS;		return NULL;	}	if (i >= sprite->nimages) {		if (error) *error = SE_INDEX;		return NULL;	}	buf = strbuf_new ();	/* Bitmap file header */	offset = 54 + sprite->palette_size;	file_size = offset + sprite->images[i].len;	strbuf_append (buf, (unsigned char *) "BM", 2);		/* Magic */	strbuf_append (buf, (unsigned char *) &file_size, 4);	/* File size */	strbuf_append (buf, (unsigned char *) "\0\0\0\0", 4);	/* Reserved */	strbuf_append (buf, (unsigned char *) &offset, 4);	/* Offset to image data */	/* Bitmap info header */	tmp = 40;	strbuf_append (buf, (unsigned char *) &tmp, 4);				/* Size of the info header */	strbuf_append (buf, (unsigned char *) &(sprite->images[i].width), 4);	/* Width */	strbuf_append (buf, (unsigned char *) &(sprite->images[i].height), 4);	/* Height */	tmp2 = 1;	strbuf_append (buf, (unsigned char *) &tmp2, 2);	/* Planes */	tmp2 = 8;	strbuf_append (buf, (unsigned char *) &tmp2, 2);	/* Bit count */	tmp = 0;	strbuf_append (buf, (unsigned char *) &tmp, 4);		/* Compression type */	tmp = sprite->images[i].len;	strbuf_append (buf, (unsigned char *) &tmp, 4);		/* Pixel data size */	tmp = 0;	strbuf_append (buf, (unsigned char *) &tmp, 4);		/* X pixels per meter */	strbuf_append (buf, (unsigned char *) &tmp, 4);		/* Y pixels per meter */	tmp = 256;	strbuf_append (buf, (unsigned char *) &tmp, 4);		/* Number of colors */	tmp = 0;	strbuf_append (buf, (unsigned char *) &tmp, 4);		/* Number of important colors */	/* Palette */	strbuf_append (buf, (unsigned char *) sprite->palette, sprite->palette_size);	/* Pixel data */	strbuf_append (buf, sprite->images[i].data, sprite->images[i].len);	data = buf->str;	if (size) *size = buf->len;	strbuf_free (buf, 0);	return data;}SPREXPORT intsprite_to_bmp_file (Sprite *sprite, int i, const char *writeToFile, SpriteError *error){	void *buf;	int bufsize;	FILE *f;	if (!writeToFile) {		if (error) *error = SE_BADARGS;		return 0;	}	buf = sprite_to_bmp (sprite, i, &bufsize, error);	if (!buf) return 0;	f = fopen (writeToFile, "wb");	if (!f) {		if (error) *error = SE_CANTWRITE;		return 0;	}	fwrite (buf, 1, bufsize, f);	fclose (f);	return 1;}SPREXPORT void *sprite_to_rgb (Sprite *sprite, int i, int *size, SpriteError *error){	unsigned char *pixels;	int rowstride, x, y, j;	if (!sprite || i < 0) {		if (error) *error = SE_BADARGS;		return NULL;	}	if (i >= sprite->nimages) {		if (error) *error = SE_INDEX;		return NULL;	}	rowstride = sprite->images[i].len / sprite->images[i].height;	pixels = (unsigned char *) calloc (3, sprite->images[i].height * rowstride);	if (size) *size = sprite->images[i].height * rowstride * 3;	j = 0;	for (y = 0; y < sprite->images[i].height; y++) {		for (x = 0; x < sprite->images[i].width; x++) {			int d;	/* Raw bitmap data index */			int p;	/* Palette index */			d = (sprite->images[i].height - y - 1) * rowstride + x;			p = sprite->images[i].data[d];			pixels[j]	= sprite->palette[p].r;			pixels[j + 1]	= sprite->palette[p].g;			pixels[j + 2]	= sprite->palette[p].b;			j += 3;		}	}	return pixels;}#ifdef __cplusplus	}#endif /* __cplusplus */

⌨️ 快捷键说明

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