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

📄 usrimage.cpp

📁 3D Game Engine Design Source Code非常棒
💻 CPP
字号:
#include <stdio.h>
#include <string.h>
#include "elements.h"
#include "fileform.h"
#include "usrimage.h"

int FT_USRIMAGE;

typedef enum {
	USR_BYTE=1, USR_SHORT=2, USR_LONG=3, USR_REAL=4, USR_GREY=8
} Usr_image_type;

typedef enum {
	aMAXMIN, aHISTO, aTITLE, aPIXFORM, aDIMC, aDIMV, aPIXELS, aINFO, aVERNO
} Usr_image_address;

typedef enum {
	nADDRESS=9, nTITLE=81, nMAXMIN=2, nHISTOGRAM=1024, nDIMV=10, nINFO=100
} Usr_image_count;

typedef struct {
	int Fd;  // file descriptor
	int ElementSize;
	int ElementCnt;

	int Address[nADDRESS];  // offsets of the other fields
	char Title[nTITLE];
	int ValidMaxMin;
	int MaxMin[nMAXMIN];
	int ValidHistogram;
	int Histogram[nHISTOGRAM];
	int ElementFormat;
	int Dimc;
	int Dimv[nDIMV];

	int InfoCnt;  // information fields from file
	char* InfoName[nINFO];
	char* InfoData[nINFO];
} Buffer_header;

//===========================================================================
static Buffer_header* rd_head (FILE* input, int* order)
{
	Buffer_header* header = new Buffer_header;

	fread((char*)header->Address,sizeof(int),nADDRESS,input);

	if ( header->Address[aTITLE] == 0x00000024 )
		*order = mgcElementDBM::ByteOrder();
	else
		*order = 1-mgcElementDBM::ByteOrder();

	if ( *order != mgcElementDBM::ByteOrder() )
		mgcElementDBM::Reverse4(1,&header->Address[aTITLE]);
	fseek(input,header->Address[aTITLE],0);
	fread(header->Title,sizeof(char),nTITLE,input);
		// reverse not need for strings

	if ( *order != mgcElementDBM::ByteOrder() )
		mgcElementDBM::Reverse4(1,&header->Address[aMAXMIN]);
	fseek(input,header->Address[aMAXMIN],0);
	fread((char*)&header->ValidMaxMin,sizeof(int),1,input);
	fread((char*)&header->MaxMin,sizeof(int),nMAXMIN,input);
		// I do not use these fields, so mgcElementDBM::reverse not used

	if ( *order != mgcElementDBM::ByteOrder() )
		mgcElementDBM::Reverse4(1,&header->Address[aHISTO]);
	fseek(input,header->Address[aHISTO],0);
	fread((char*)&header->ValidHistogram,sizeof(int),1,input);
	fread((char*)&header->Histogram,sizeof(int),nHISTOGRAM,input);
		// I do not use these fields, so mgcElementDBM::reverse not used

	if ( *order != mgcElementDBM::ByteOrder() )
		mgcElementDBM::Reverse4(1,&header->Address[aDIMC]);
	fseek(input,header->Address[aDIMC],0);
	fread((char*)&header->Dimc,sizeof(int),1,input);
	if ( *order != mgcElementDBM::ByteOrder() )
		mgcElementDBM::Reverse4(1,&header->Dimc);

	if ( *order != mgcElementDBM::ByteOrder() )
		mgcElementDBM::Reverse4(1,&header->Address[aDIMV]);
	fseek(input,header->Address[aDIMV],0);
	fread((char*)&header->Dimv[0],sizeof(int),nDIMV,input);
	if ( *order != mgcElementDBM::ByteOrder() )
		mgcElementDBM::Reverse4(nDIMV,&header->Dimv[0]);

	if ( *order != mgcElementDBM::ByteOrder() )
		mgcElementDBM::Reverse4(1,&header->Address[aPIXFORM]);
	fseek(input,header->Address[aPIXFORM],0);
	fread((char*)&header->ElementFormat,sizeof(int),1,input);
	if ( *order != mgcElementDBM::ByteOrder() )
		mgcElementDBM::Reverse4(1,&header->ElementFormat);

	return header;
}
//---------------------------------------------------------------------------
static int
USRIMAGE_query (char* name)
{
	FILE* input = fopen(name,"rb");
	if ( !input )
		return -1;

	unsigned char b[28];
	if ( fread((char*)b,sizeof(unsigned char),28,input) != 28 )
		return 0;

	if ( b[0] == 0x75 && b[4] == 0x81 && b[8] == 0x24 && b[12] == 0x81
	&& b[13] == 0x20 && b[16] == 0x85 && b[17] == 0x20 && b[20] == 0x89
	&& b[21] == 0x20 && b[24] == 0xB1 && b[25] == 0x20 ) {
		fclose(input);
		return 1;
	}

	if ( b[3] == 0x75 && b[7] == 0x81 && b[11] == 0x24 && b[14] == 0x20
	&& b[15] == 0x81 && b[18] == 0x20 && b[19] == 0x85 && b[22] == 0x20
	&& b[23] == 0x89 && b[26] == 0x20 && b[27] == 0xB1 ) {
		fclose(input);
		return 1;
	}

	fclose(input);
	return 0;
}
//---------------------------------------------------------------------------
static int
USRIMAGE_gethead (char* name, int* dims, int** dim, char* pixform,
	int* order)
{
	FILE* input = fopen(name,"rb");
	if ( !input )
		return 0;

	// read the header, need to test byte-order here to avoid failure
	Buffer_header* header = rd_head(input,order);

	// number of dimensions
	*dims = header->Dimc;

	// size of each dimension
	*dim = new int[*dims];  // assumes *dim is a valid address
	for (int i = 0; i < *dims; i++)
		(*dim)[i] = header->Dimv[header->Dimc-1-i];

	// element type
	switch ( header->ElementFormat ) {
		case USR_BYTE:
			strcpy(pixform,mgcElementDBM::Description(mgcUchar::type));
			break;
		case USR_GREY:
			strcpy(pixform,mgcElementDBM::Description(mgcShort::type));
			break;
		case USR_SHORT:
			strcpy(pixform,mgcElementDBM::Description(mgcShort::type));
			break;
		case USR_LONG:
			strcpy(pixform,mgcElementDBM::Description(mgcLong::type));
			break;
		case USR_REAL:
			strcpy(pixform,mgcElementDBM::Description(mgcFloat::type));
			break;
		default:  // type not suppored
			delete header;
			fclose(input);
			return 0;
	}

	delete header;
	fclose(input);
	return 1;
}
//---------------------------------------------------------------------------
static int
USRIMAGE_puthead (char* name, int dims, const int* dim,
	const char* pixform, int)
{
	FILE* output = fopen(name,"wb");
	if ( !output )
		return 0;

	// write the header
	Buffer_header *header = new Buffer_header;
	int i;
	for (i = 0; i < sizeof(Buffer_header); i++)
		((char*)header)[i] = 0;

	// element info
	header->ElementCnt = 1;
	for (i = 0; i < dims; i++)
		header->ElementCnt *= dim[i];
	int pixtype = mgcElementDBM::Type(pixform);
	header->ElementSize = mgcElementDBM::PackedSize(pixtype);

	// write offsets of header fields, write fields that are not used
	header->Address[aTITLE]			// 36   = 0x00000024
		= sizeof(int)*nADDRESS;
	header->Address[aMAXMIN]		// 117  = 0x00000075
		= header->Address[aTITLE]+sizeof(char)*nTITLE;
	header->Address[aHISTO]			// 129  = 0x00000081
		= header->Address[aMAXMIN]+sizeof(int)+sizeof(int)*nMAXMIN;
	header->Address[aPIXFORM]		// 8321 = 0x00002081
		= header->Address[aHISTO]+4092+sizeof(int)+sizeof(int)*nHISTOGRAM;
	header->Address[aDIMC]			// 8325 = 0x00002085
		= header->Address[aPIXFORM]+sizeof(int);
	header->Address[aDIMV]			// 8329 = 0x00002089
		= header->Address[aDIMC]+sizeof(int);
	header->Address[aPIXELS]		// 8369 = 0x000020B1
		= header->Address[aDIMV]+sizeof(int)*nDIMV;
	header->Address[aINFO]			// last byte of file
		= header->Address[aPIXELS]+header->ElementSize*header->ElementCnt;
	header->Address[aVERNO] = 1;

	fwrite((char*)&header->Address,sizeof(int),nADDRESS,output);
		// Produces the first 36 bytes of header as shown where 'x' positions
		// are dependent on element count and element size.
		//
		// order = 0 (ibm-pc, dec-mips)
		//   75 00 00 00 81 00 00 00 24 00 00 00 81 20 00 00
		//   85 20 00 00 89 20 00 00 B1 20 00 00 xx xx xx xx
		//   01 00 00 00
		//
		// order = 1 (sparc, hp-pa)
		//   00 00 00 75 00 00 00 81 00 00 00 24 00 00 20 81
		//   00 00 20 85 00 00 20 89 00 00 20 B1 xx xx xx xx
		//   00 00 00 01

	fwrite(header->Title,sizeof(char),nTITLE,output);
	fwrite((char*)&header->ValidMaxMin,sizeof(int),1,output);
	fwrite((char*)&header->MaxMin,sizeof(int),nMAXMIN,output);
	fwrite((char*)&header->ValidHistogram,sizeof(int),1,output);
	fwrite((char*)&header->Histogram,sizeof(int),nHISTOGRAM,output);
	char zero = 0;
	for (i = 0; i < 4092; i++)  // unused bytes in header
		fwrite(&zero,sizeof(char),1,output);

	// element type
	if ( pixtype == mgcUchar::type )
		header->ElementFormat = USR_BYTE;
	else if ( pixtype == mgcShort::type )
		header->ElementFormat = USR_GREY;
	else if ( pixtype == mgcLong::type )
		header->ElementFormat = USR_LONG;
	else if ( pixtype == mgcFloat::type )
		header->ElementFormat = USR_REAL;
	else  {  // type not supported
		delete header;
		fclose(output);
		return 0;
	}
	fwrite((char*)&header->ElementFormat,sizeof(int),1,output);

	// number of dimensions
	header->Dimc = dims;
	fwrite((char*)&header->Dimc,sizeof(int),1,output);

	// size of each dimension
	for (i = 0; i < header->Dimc; i++)
		header->Dimv[i] = dim[header->Dimc-1-i];
	fwrite((char*)&header->Dimv,sizeof(int),nDIMV,output);

	// byte order not used in /usr/image format

	// allocate file space to hold all the elements
	const int buffer_size = 16384;
	char* buffer = new char[buffer_size];
	for (i = 0; i < buffer_size; i++)
		buffer[i] = 0;

	int byte_quantity = header->ElementCnt*header->ElementSize;
	int block_count = byte_quantity / buffer_size;
	int block_remainder = byte_quantity % buffer_size;
	for (i = 0; i < block_count; i++)
		fwrite(buffer,sizeof(char),buffer_size,output);
	if ( block_remainder )
		fwrite(buffer,sizeof(char),block_remainder,output);

	delete[] buffer;

	// write footer (info field is "empty" null terminated string)
	fwrite(&zero,sizeof(char),1,output);

	delete header;
	fclose(output);
	return 1;
}
//---------------------------------------------------------------------------
static int
USRIMAGE_getdata (char* name, long offset, int quantity, char* buffer)
{
	FILE* input = fopen(name,"rb");
	if ( !input )
		return 0;

	// move file pointer to first element of buffer
	long element_start = 8369;

	// ImageFile handles the byte reordering
	fseek(input,element_start+offset,0);
	fread(buffer,sizeof(char),quantity,input);
	fclose(input);

	return 1;
}
//---------------------------------------------------------------------------
static int
USRIMAGE_putdata (char* name, long offset, int quantity, char* buffer)
{
	FILE* output = fopen(name,"rb");
	if ( !output )
		return 0;

	// move file pointer to first element of buffer
	long element_start = 8369;

	// ImageFile handles the byte reordering
	fseek(output,element_start+offset,0);
	fwrite(buffer,sizeof(char),quantity,output);
	fclose(output);

	return 1;
}
//---------------------------------------------------------------------------
static int
USRIMAGE_getmessage (char*, void*)
{
    return 0;
}
//---------------------------------------------------------------------------
static int
USRIMAGE_putmessage (char*, void*)
{
	return 0;
}
//---------------------------------------------------------------------------
int __USRIMAGE_register__()
{
	// automatic registration of USRIMAGE file format
	static int is_registered = 0;

	if ( is_registered == 0 ) {
		FT_USRIMAGE = mgcFileFormat::AddFileFormat(
			USRIMAGE_query,
			USRIMAGE_gethead,
			USRIMAGE_puthead,
			USRIMAGE_getdata,
			USRIMAGE_putdata,
			USRIMAGE_getmessage,
			USRIMAGE_putmessage
		);
		is_registered = 1;
	}
	return is_registered;
}
//===========================================================================

⌨️ 快捷键说明

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