347 lines
10 KiB
C++
347 lines
10 KiB
C++
/***************************************************************************
|
|
* *
|
|
* This is a class for holding and handling basic image data *
|
|
* *
|
|
* Author: Graeme van der Vlugt *
|
|
* Copyright: Imetric 3D GmbH *
|
|
* Year: 2004 *
|
|
* *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU Library General Public License as *
|
|
* published by the Free Software Foundation; either version 2 of the *
|
|
* License, or (at your option) any later version. *
|
|
* for detail see the LICENCE text file. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "PreCompiled.h"
|
|
#ifndef _PreComp_
|
|
# include <cmath>
|
|
# include <cstring>
|
|
#endif
|
|
|
|
#include "ImageBase.h"
|
|
#include <Base/Exception.h>
|
|
|
|
using namespace Image;
|
|
|
|
// Constructor (constructs an empty image)
|
|
ImageBase::ImageBase()
|
|
{
|
|
_pPixelData = NULL;
|
|
_owner = true;
|
|
_width = 0;
|
|
_height = 0;
|
|
_setColorFormat(IB_CF_GREY8, 8);
|
|
}
|
|
|
|
// Destructor
|
|
ImageBase::~ImageBase()
|
|
{
|
|
try
|
|
{
|
|
clear();
|
|
}
|
|
catch(...) {}
|
|
}
|
|
|
|
// Copy constructor
|
|
ImageBase::ImageBase(const ImageBase &rhs)
|
|
{
|
|
// Do the copy
|
|
if (rhs._owner == true)
|
|
{
|
|
// rhs is the owner - do a deep copy
|
|
_pPixelData = NULL;
|
|
_owner = false; // avoids a superfluous delete
|
|
if (createCopy((void *)(rhs._pPixelData), rhs._width, rhs._height, rhs._format, rhs._numSigBitsPerSample) != 0)
|
|
throw Base::RuntimeError("ImageBase::ImageBase. Error creating copy of image");
|
|
}
|
|
else
|
|
{
|
|
// rhs is not the owner - do a shallow copy
|
|
_pPixelData = rhs._pPixelData;
|
|
_owner = rhs._owner;
|
|
_width = rhs._width;
|
|
_height = rhs._height;
|
|
_setColorFormat(rhs._format, rhs._numSigBitsPerSample);
|
|
}
|
|
}
|
|
|
|
// = operator
|
|
ImageBase & ImageBase::operator=(const ImageBase &rhs)
|
|
{
|
|
if (this == &rhs)
|
|
return *this;
|
|
|
|
// Implement any deletion necessary
|
|
clear();
|
|
|
|
// Do the copy
|
|
if (rhs._owner == true)
|
|
{
|
|
// rhs is the owner - do a deep copy
|
|
_owner = false; // avoids a superfluous delete
|
|
if (createCopy((void *)(rhs._pPixelData), rhs._width, rhs._height, rhs._format, rhs._numSigBitsPerSample) != 0)
|
|
throw Base::RuntimeError("ImageBase::operator=. Error creating copy of image");
|
|
}
|
|
else
|
|
{
|
|
// rhs is not the owner - do a shallow copy
|
|
_pPixelData = rhs._pPixelData;
|
|
_owner = rhs._owner;
|
|
_width = rhs._width;
|
|
_height = rhs._height;
|
|
_setColorFormat(rhs._format, rhs._numSigBitsPerSample);
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
// Clears the image data
|
|
// It only deletes the pixel data if this object is the owner of the data
|
|
void ImageBase::clear()
|
|
{
|
|
// If object is the owner of the data then delete the allocated memory
|
|
if (_owner == true)
|
|
{
|
|
delete [] _pPixelData;
|
|
_pPixelData = NULL;
|
|
}
|
|
// Else just reset the pointer (the owner of the pixel data must be responsible for deleting it)
|
|
else
|
|
{
|
|
_pPixelData = NULL;
|
|
}
|
|
|
|
// Re-initialise the other variables
|
|
_owner = true;
|
|
_width = 0;
|
|
_height = 0;
|
|
_setColorFormat(IB_CF_GREY8, 8);
|
|
}
|
|
|
|
// Sets the color format and the dependent parameters
|
|
// Returns 0 for OK, -1 for invalid color format
|
|
int ImageBase::_setColorFormat(int format, unsigned short numSigBitsPerSample)
|
|
{
|
|
switch (format)
|
|
{
|
|
case IB_CF_GREY8:
|
|
_numSamples = 1;
|
|
_numBitsPerSample = 8;
|
|
_numBytesPerPixel = 1;
|
|
break;
|
|
case IB_CF_GREY16:
|
|
_numSamples = 1;
|
|
_numBitsPerSample = 16;
|
|
_numBytesPerPixel = 2;
|
|
break;
|
|
case IB_CF_GREY32:
|
|
_numSamples = 1;
|
|
_numBitsPerSample = 32;
|
|
_numBytesPerPixel = 4;
|
|
break;
|
|
case IB_CF_RGB24:
|
|
_numSamples = 3;
|
|
_numBitsPerSample = 8;
|
|
_numBytesPerPixel = 3;
|
|
break;
|
|
case IB_CF_RGB48:
|
|
_numSamples = 3;
|
|
_numBitsPerSample = 16;
|
|
_numBytesPerPixel = 6;
|
|
break;
|
|
case IB_CF_BGR24:
|
|
_numSamples = 3;
|
|
_numBitsPerSample = 8;
|
|
_numBytesPerPixel = 3;
|
|
break;
|
|
case IB_CF_BGR48:
|
|
_numSamples = 3;
|
|
_numBitsPerSample = 16;
|
|
_numBytesPerPixel = 6;
|
|
break;
|
|
case IB_CF_RGBA32:
|
|
_numSamples = 4;
|
|
_numBitsPerSample = 8;
|
|
_numBytesPerPixel = 4;
|
|
break;
|
|
case IB_CF_RGBA64:
|
|
_numSamples = 4;
|
|
_numBitsPerSample = 16;
|
|
_numBytesPerPixel = 8;
|
|
break;
|
|
case IB_CF_BGRA32:
|
|
_numSamples = 4;
|
|
_numBitsPerSample = 8;
|
|
_numBytesPerPixel = 4;
|
|
break;
|
|
case IB_CF_BGRA64:
|
|
_numSamples = 4;
|
|
_numBitsPerSample = 16;
|
|
_numBytesPerPixel = 8;
|
|
break;
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
if ((numSigBitsPerSample == 0) || (numSigBitsPerSample > _numBitsPerSample))
|
|
_numSigBitsPerSample = _numBitsPerSample;
|
|
else
|
|
_numSigBitsPerSample = numSigBitsPerSample;
|
|
|
|
_format = format;
|
|
return 0;
|
|
}
|
|
|
|
// Allocate own space for an image based on the current color space and image size parameters
|
|
// Returns:
|
|
// 0 for OK
|
|
// -1 for error
|
|
int ImageBase::_allocate()
|
|
{
|
|
// Check that pixel data pointer is null
|
|
if (_pPixelData != NULL)
|
|
return -1;
|
|
|
|
// Allocate the space needed to store the pixel data
|
|
_owner = true;
|
|
try
|
|
{
|
|
_pPixelData = new unsigned char [_width * _height * _numBytesPerPixel];
|
|
}
|
|
catch(...)
|
|
{
|
|
// memory allocation error
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Load an image by copying the pixel data
|
|
// This object will take ownership of the copied pixel data
|
|
// (the source image is still controlled by the caller)
|
|
// If numSigBitsPerSample = 0 then the full range is assumed to be significant
|
|
// Returns:
|
|
// 0 for OK
|
|
// -1 for invalid color format
|
|
// -2 for memory allocation error
|
|
int ImageBase::createCopy(void* pSrcPixelData, unsigned long width, unsigned long height, int format, unsigned short numSigBitsPerSample)
|
|
{
|
|
// Clear any existing data
|
|
clear();
|
|
|
|
// Set the color format and the dependent parameters
|
|
if (_setColorFormat(format, numSigBitsPerSample) != 0)
|
|
return -1;
|
|
|
|
// Set the image size
|
|
_width = width;
|
|
_height = height;
|
|
|
|
// Allocate our own memory for the pixel data
|
|
if (_allocate() != 0)
|
|
{
|
|
clear();
|
|
return -2;
|
|
}
|
|
|
|
// Copy the pixel data
|
|
memcpy((void *)_pPixelData, pSrcPixelData, _width * _height * _numBytesPerPixel);
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Make this object point to another image source
|
|
// If takeOwnership is false then:
|
|
// This object will not own (control) or copy the pixel data
|
|
// (the source image is still controlled by the caller)
|
|
// Else if takeOwnership is true then:
|
|
// This object will take ownership (control) of the pixel data
|
|
// (the source image is not (should not be) controlled by the caller anymore)
|
|
// In this case the memory must have been allocated with the new operator (because this class will use the delete operator)
|
|
// If numSigBitsPerSample = 0 then the full range is assumed to be significant
|
|
// Returns:
|
|
// 0 for OK
|
|
// -1 for invalid color format
|
|
int ImageBase::pointTo(void* pSrcPixelData, unsigned long width, unsigned long height, int format, unsigned short numSigBitsPerSample, bool takeOwnership)
|
|
{
|
|
// Clear any existing data
|
|
clear();
|
|
|
|
// Set the color format and the dependent parameters
|
|
if (_setColorFormat(format, numSigBitsPerSample) != 0)
|
|
return -1;
|
|
|
|
// Set the image size
|
|
_width = width;
|
|
_height = height;
|
|
|
|
// Point to the source pixel data
|
|
_owner = false;
|
|
_pPixelData = (unsigned char *)pSrcPixelData;
|
|
|
|
// Flag ownership
|
|
if (takeOwnership == true)
|
|
_owner = true;
|
|
else
|
|
_owner = false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Gets the value of a sample at the given pixel position
|
|
// Returns 0 for valid value or -1 if coordinates or sample index are out of range or
|
|
// if there is no image data
|
|
int ImageBase::getSample(int x, int y, unsigned short sampleIndex, double &value)
|
|
{
|
|
if ((_pPixelData == NULL) ||
|
|
(sampleIndex >= _numSamples) ||
|
|
(x < 0) || (x >= (int)_width) ||
|
|
(y < 0) || (y >= (int)_height))
|
|
return -1;
|
|
|
|
// Get pointer to sample
|
|
switch (_format)
|
|
{
|
|
case IB_CF_GREY8:
|
|
case IB_CF_RGB24:
|
|
case IB_CF_BGR24:
|
|
case IB_CF_RGBA32:
|
|
case IB_CF_BGRA32:
|
|
{
|
|
unsigned char* pSample = _pPixelData + _numSamples * (y * _width + x) + sampleIndex;
|
|
value = (double)(*pSample);
|
|
}
|
|
break;
|
|
case IB_CF_GREY16:
|
|
case IB_CF_RGB48:
|
|
case IB_CF_BGR48:
|
|
case IB_CF_RGBA64:
|
|
case IB_CF_BGRA64:
|
|
{
|
|
uint16_t* pPix16 = (uint16_t *)_pPixelData;
|
|
uint16_t* pSample = pPix16 + _numSamples * (y * _width + x) + sampleIndex;
|
|
value = (double)(*pSample);
|
|
}
|
|
break;
|
|
case IB_CF_GREY32:
|
|
{
|
|
uint32_t* pPix32 = (uint32_t *)_pPixelData;
|
|
uint32_t* pSample = pPix32 + y * _width + x;
|
|
value = (double)(*pSample);
|
|
}
|
|
break;
|
|
default:
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|