Files
create/src/Mod/Image/App/ImageBase.cpp
2017-04-28 18:49:11 +02:00

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;
}