📄 usrimage.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 + -