Cloned library of VTK-5.0.0 with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

454 lines
12 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkGESignaReader.cxx,v $
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkGESignaReader.h"
#include "vtkByteSwap.h"
#include "vtkImageData.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
vtkCxxRevisionMacro(vtkGESignaReader, "$Revision: 1.19 $");
vtkStandardNewMacro(vtkGESignaReader);
int vtkGESignaReader::CanReadFile(const char* fname)
{
FILE *fp = fopen(fname, "rb");
if (!fp)
{
return 0;
}
int magic;
fread(&magic, 4, 1, fp);
vtkByteSwap::Swap4BE(&magic);
if (magic != 0x494d4746)
{
fclose(fp);
return 0;
}
return 3;
}
void vtkGESignaReader::ExecuteInformation()
{
this->ComputeInternalFileName(this->DataExtent[4]);
if (this->InternalFileName == NULL)
{
return;
}
FILE *fp = fopen(this->InternalFileName, "rb");
if (!fp)
{
vtkErrorMacro("Unable to open file " << this->InternalFileName);
return;
}
int magic;
fread(&magic, 4, 1, fp);
vtkByteSwap::Swap4BE(&magic);
if (magic != 0x494d4746)
{
vtkErrorMacro(<<"Unknown file type! Not a GE ximg file!");
fclose(fp);
return;
}
// read in the pixel offset from the header
int offset;
fread(&offset, 4, 1, fp);
vtkByteSwap::Swap4BE(&offset);
this->SetHeaderSize(offset);
int width, height, depth;
fread(&width, 4, 1, fp);
vtkByteSwap::Swap4BE(&width);
fread(&height, 4, 1, fp);
vtkByteSwap::Swap4BE(&height);
// depth in bits
fread(&depth, 4, 1, fp);
vtkByteSwap::Swap4BE(&depth);
int compression;
fread(&compression, 4, 1, fp);
vtkByteSwap::Swap4BE(&compression);
// seek to the exam series and image header offsets
fseek(fp, 132, SEEK_SET);
int examHdrOffset;
fread(&examHdrOffset, 4, 1, fp);
vtkByteSwap::Swap4BE(&examHdrOffset);
fseek(fp, 140, SEEK_SET);
int seriesHdrOffset;
fread(&seriesHdrOffset, 4, 1, fp);
vtkByteSwap::Swap4BE(&seriesHdrOffset);
fseek(fp, 148, SEEK_SET);
int imgHdrOffset;
fread(&imgHdrOffset, 4, 1, fp);
vtkByteSwap::Swap4BE(&imgHdrOffset);
// seek to the exam and read some info
fseek(fp, examHdrOffset + 84, SEEK_SET);
char tmpStr[1024];
fread(tmpStr,13,1,fp);
tmpStr[13] = 0;
this->SetPatientID(tmpStr);
fread(tmpStr,25,1,fp);
tmpStr[25] = 0;
this->SetPatientName(tmpStr);
// seek to the series and read some info
fseek(fp, seriesHdrOffset + 10, SEEK_SET);
short series;
fread(&series,2,1,fp);
vtkByteSwap::Swap2BE(&series);
sprintf(tmpStr,"%d",series);
this->SetSeries(tmpStr);
fseek(fp, seriesHdrOffset + 92, SEEK_SET);
fread(tmpStr,25,1,fp);
tmpStr[25] = 0;
this->SetStudy(tmpStr);
// now seek to the image header and read some values
float tmpX, tmpY, tmpZ;
float spacingX, spacingY, spacingZ;
fseek(fp, imgHdrOffset + 50, SEEK_SET);
fread(&spacingX, 4, 1, fp);
vtkByteSwap::Swap4BE(&spacingX);
fread(&spacingY, 4, 1, fp);
vtkByteSwap::Swap4BE(&spacingY);
fseek(fp, imgHdrOffset + 116, SEEK_SET);
fread(&spacingZ, 4, 1, fp);
vtkByteSwap::Swap4BE(&spacingZ);
fseek(fp, imgHdrOffset + 26, SEEK_SET);
fread(&tmpZ, 4, 1, fp);
vtkByteSwap::Swap4BE(&tmpZ);
spacingZ = spacingZ + tmpZ;
float origX, origY, origZ;
fseek(fp, imgHdrOffset + 154, SEEK_SET);
// read TLHC
fread(&origX, 4, 1, fp);
vtkByteSwap::Swap4BE(&origX);
fread(&origY, 4, 1, fp);
vtkByteSwap::Swap4BE(&origY);
fread(&origZ, 4, 1, fp);
vtkByteSwap::Swap4BE(&origZ);
// read TRHC
fread(&tmpX, 4, 1, fp);
vtkByteSwap::Swap4BE(&tmpX);
fread(&tmpY, 4, 1, fp);
vtkByteSwap::Swap4BE(&tmpY);
fread(&tmpZ, 4, 1, fp);
vtkByteSwap::Swap4BE(&tmpZ);
// compute BLHC = TLHC - TRHC + BRHC
origX = origX - tmpX;
origY = origY - tmpY;
origZ = origZ - tmpZ;
// read BRHC
fread(&tmpX, 4, 1, fp);
vtkByteSwap::Swap4BE(&tmpX);
fread(&tmpY, 4, 1, fp);
vtkByteSwap::Swap4BE(&tmpY);
fread(&tmpZ, 4, 1, fp);
vtkByteSwap::Swap4BE(&tmpZ);
// compute BLHC = TLHC - TRHC + BRHC
origX = origX + tmpX;
origY = origY + tmpY;
origZ = origZ + tmpZ;
this->SetDataOrigin(origX, origY, origZ);
this->DataExtent[0] = 0;
this->DataExtent[1] = width - 1;
this->DataExtent[2] = 0;
this->DataExtent[3] = height - 1;
this->SetDataScalarTypeToUnsignedShort();
this->SetNumberOfScalarComponents(1);
this->SetDataSpacing(spacingX, spacingY, spacingZ);
this->vtkImageReader2::ExecuteInformation();
// close the file
fclose(fp);
}
void vtkcopygenesisimage(FILE *infp, int width, int height, int compress,
short *map_left, short *map_wide,
unsigned short *output)
{
unsigned short row;
unsigned short last_pixel=0;
for (row=0; row<height; ++row)
{
unsigned short j;
unsigned short start;
unsigned short end;
if (compress == 2 || compress == 4)
{ // packed/compacked
start=map_left[row];
end=start+map_wide[row];
}
else
{
start=0;
end=width;
}
// Pad the first "empty" part of the line ...
for (j=0; j<start; j++)
{
(*output) = 0;
++output;
}
if (compress == 3 || compress == 4)
{ // compressed/compacked
while (start<end)
{
unsigned char byte;
if (!fread(&byte,1,1,infp))
{
return;
}
if (byte & 0x80)
{
unsigned char byte2;
if (!fread(&byte2,1,1,infp))
{
return;
}
if (byte & 0x40)
{ // next word
if (!fread(&byte,1,1,infp))
{
return;
}
last_pixel=
(((unsigned short)byte2<<8)+byte);
}
else
{ // 14 bit delta
if (byte & 0x20)
{
byte|=0xe0;
}
else
{
byte&=0x1f;
}
last_pixel+=
(((short)byte<<8)+byte2);
}
}
else
{ // 7 bit delta
if (byte & 0x40)
{
byte|=0xc0;
}
last_pixel+=(signed char)byte;
}
(*output) = last_pixel;
++output;
++start;
}
}
else
{
while (start<end)
{
unsigned short u;
if (!fread(&u,2,1,infp))
{
return;
}
vtkByteSwap::Swap2BE(&u);
(*output) = u;
++output;
++start;
}
}
// Pad the last "empty" part of the line ...
for (j=end; j<width; j++)
{
(*output) = 0;
++output;
}
}
}
void vtkGESignaReaderUpdate2(vtkGESignaReader *self, unsigned short *outPtr,
int *outExt, vtkIdType *)
{
FILE *fp = fopen(self->GetInternalFileName(), "rb");
if (!fp)
{
return;
}
int magic;
fread(&magic, 4, 1, fp);
vtkByteSwap::Swap4BE(&magic);
if (magic != 0x494d4746)
{
vtkGenericWarningMacro(<<"Unknown file type! Not a GE ximg file!");
fclose(fp);
return;
}
// read in the pixel offset from the header
int offset;
fread(&offset, 4, 1, fp);
vtkByteSwap::Swap4BE(&offset);
int width, height, depth;
fread(&width, 4, 1, fp);
vtkByteSwap::Swap4BE(&width);
fread(&height, 4, 1, fp);
vtkByteSwap::Swap4BE(&height);
// depth in bits
fread(&depth, 4, 1, fp);
vtkByteSwap::Swap4BE(&depth);
int compression;
fread(&compression, 4, 1, fp);
vtkByteSwap::Swap4BE(&compression);
short *leftMap = 0;
short *widthMap = 0;
if (compression == 2 || compression == 4)
{ // packed/compacked
leftMap = new short [height];
widthMap = new short [height];
fseek(fp, 64, SEEK_SET);
int packHdrOffset;
fread(&packHdrOffset, 4, 1, fp);
vtkByteSwap::Swap4BE(&packHdrOffset);
// now seek to the pack header and read some values
fseek(fp, packHdrOffset, SEEK_SET);
// read in the maps
int i;
for (i = 0; i < height; i++)
{
fread(leftMap+i, 2, 1, fp);
vtkByteSwap::Swap2BE(leftMap+i);
fread(widthMap+i, 2, 1, fp);
vtkByteSwap::Swap2BE(widthMap+i);
}
}
// seek to pixel data
fseek(fp, offset, SEEK_SET);
// read in the pixels
unsigned short *tmp = new unsigned short [width*height];
int *dext = self->GetDataExtent();
vtkcopygenesisimage(fp, dext[1] + 1, dext[3] + 1,
compression, leftMap, widthMap, tmp);
// now copy into desired extent
int yp;
for (yp = outExt[2]; yp <= outExt[3]; ++yp)
{
int ymod = height - yp - 1;
memcpy(outPtr,tmp+ymod*width+outExt[0],2*width);
outPtr = outPtr + width;
}
delete [] tmp;
if (leftMap)
{
delete [] leftMap;
}
if (widthMap)
{
delete [] widthMap;
}
fclose(fp);
}
//----------------------------------------------------------------------------
// This function reads in one data of data.
// templated to handle different data types.
void vtkGESignaReaderUpdate(vtkGESignaReader *self, vtkImageData *data,
unsigned short *outPtr)
{
vtkIdType outIncr[3];
int outExtent[6];
unsigned short *outPtr2;
data->GetExtent(outExtent);
data->GetIncrements(outIncr);
outPtr2 = outPtr;
int idx2;
for (idx2 = outExtent[4]; idx2 <= outExtent[5]; ++idx2)
{
self->ComputeInternalFileName(idx2);
// read in a PNG file
vtkGESignaReaderUpdate2(self, outPtr2, outExtent, outIncr);
self->UpdateProgress((idx2 - outExtent[4])/
(outExtent[5] - outExtent[4] + 1.0));
outPtr2 += outIncr[2];
}
}
//----------------------------------------------------------------------------
// This function reads a data from a file. The datas extent/axes
// are assumed to be the same as the file extent/order.
void vtkGESignaReader::ExecuteData(vtkDataObject *output)
{
vtkImageData *data = this->AllocateOutputData(output);
if (this->InternalFileName == NULL)
{
vtkErrorMacro(<< "Either a FileName or FilePrefix must be specified.");
return;
}
data->GetPointData()->GetScalars()->SetName("GESignalImage");
this->ComputeDataIncrements();
// Call the correct templated function for the output
void *outPtr;
// Call the correct templated function for the input
outPtr = data->GetScalarPointer();
vtkGESignaReaderUpdate(this, data, (unsigned short *)(outPtr));
}
//----------------------------------------------------------------------------
void vtkGESignaReader::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
}