<commit_before>/** @file
 *
 * @ingroup dspLibrary
 *
 * @brief Container object that holds some audio in a chunk of memory.
 *
 * @see TTMatrix, TTAudioSignal
 *
 * @authors Timothy Place & Nathan Wolek
 *
 * @copyright Copyright © 2003-2012, Timothy Place & Nathan Wolek @n
 * This code is licensed under the terms of the "New BSD License" @n
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTSampleMatrix.h"
#include "TTInterpolate.h"

#define thisTTClass			TTSampleMatrix
#define thisTTClassName		"samplematrix"
#define thisTTClassTags		"audio, buffer"

TTObjectPtr TTSampleMatrix::instantiate(TTSymbol& name, TTValue& arguments)
{
	return new TTSampleMatrix(arguments);
}

extern "C" void TTSampleMatrix::registerClass()
{
	TTClassRegister(thisTTClassName, thisTTClassTags, TTSampleMatrix::instantiate);
}

TTSampleMatrix::TTSampleMatrix(TTValue& arguments) :
	TTMatrix(arguments),
	mSampleRate(44100.0)
{
	this->setTypeWithoutResize(kTypeFloat64);
	this->setElementCountWithoutResize(1);
	this->resize();
	this->mUserCount = 0;
	this->mBufferPoolStage = kSM_Idle;

	addAttributeWithGetterAndSetter(NumChannels,		kTypeInt32);
	addAttributeWithGetterAndSetter(Length,				kTypeFloat64);
	addAttributeWithGetterAndSetter(LengthInSamples,	kTypeInt32);
	addAttribute(SampleRate,							kTypeFloat64);
	addAttribute(				UserCount,				kTypeUInt16);
		addAttributeProperty(	UserCount, 				readOnly, kTTBoolYes);

	addMessage(normalize);
	addMessageWithArguments(fill);

	addMessageWithArguments(getValueAtIndex);
	registerMessage("peek", (TTMethod)&TTSampleMatrix::getValueAtIndex);
	registerMessage("peeki", (TTMethod)&TTSampleMatrix::getValueAtIndex);

	addMessageWithArguments(setValueAtIndex);
	registerMessage("poke", (TTMethod)&TTSampleMatrix::setValueAtIndex);

	// TODO: more messages to implement
	//	"readFile"   (requires libsndfile straightening-out)
	//	"writeFile"  (requires libsndfile straightening-out)
	//	a way to query attributes: for example what is the sr and bpm of an AIFF file?
}

TTSampleMatrix::~TTSampleMatrix()
{
	;
}

TTErr TTSampleMatrix::setNumChannels(const TTValue& newNumChannels)
{
	return setColumnCount(newNumChannels);
}

TTErr TTSampleMatrix::getNumChannels(TTValue& returnedChannelCount)
{
	returnedChannelCount = mNumChannels;
	return kTTErrNone;
}

TTErr TTSampleMatrix::setLength(const TTValue& newLength)
{
	TTValue newLengthInSamples = TTFloat64(newLength) * mSampleRate * 0.001;
	return setRowCount(newLengthInSamples);
}

TTErr TTSampleMatrix::getLength(TTValue& returnedLength)
{
	returnedLength = (mLengthInSamples / mSampleRate) * 1000.0;
	return kTTErrNone;
}

TTErr TTSampleMatrix::setLengthInSamples(const TTValue& newLengthInSamples)
{
	return setRowCount(newLengthInSamples);
}

TTErr TTSampleMatrix::getLengthInSamples(TTValue& returnedLengthInSamples)
{
	returnedLengthInSamples = mLengthInSamples;
	return kTTErrNone;
}

TTErr TTSampleMatrix::incrementUserCount()
{
	// could technically exceed 65,535 maximum, but we'll take the chance for now
	this->mUserCount++;
	return kTTErrNone;
}

TTErr TTSampleMatrix::decrementUserCount()
{
	if (this->mUserCount > 0)
	{
		this->mUserCount--;
		return kTTErrNone;
	} else {
		return kTTErrGeneric;
	}

}

TTErr TTSampleMatrix::getValueAtIndex(const TTValue& index, TTValue &output)
{
	TTUInt32		sampleIndex;
	TTUInt16		sampleChannel = 0;
	TTSampleValue	sampleValue;
	TTUInt8			i = 0;
	TTErr			err;

	index.get(i++, sampleIndex);
	if (index.getSize() > 2)		// TODO: sure would be nice to change the name of this method to "size" or something...
		index.get(i++, sampleChannel);

	err = peek(sampleIndex, sampleChannel, sampleValue);
	if (!err)
		output.set(i++, sampleValue);
	return err;
}

TTErr TTSampleMatrix::peek(const TTUInt64 index, const TTUInt16 channel, TTSampleValue& value)
{
	TTRowID p_index = index;
	TTColumnID p_channel = channel;

	TTBoolean weAreNotInBounds = makeInBounds(p_index, p_channel); // out of range values are clipped
	get2d(p_index, p_channel, value);

	if (weAreNotInBounds)
	{
		return kTTErrOutOfBounds;
	} else {
		return kTTErrNone;
	}
}

// a first attempt at interpolation for the SampleMatrix. should be viewed as temporary.
// needs to be fleshed out with different options...
TTErr TTSampleMatrix::peeki(const TTFloat64 index, const TTUInt16 channel, TTSampleValue& value)
{
	// variables needed
    TTColumnID p_channel = channel;
	TTFloat64 indexIntegralPart = 0;
	TTFloat64 indexFractionalPart = modf(index, &indexIntegralPart); // before makeInBounds to get the right value!
	TTRowID indexThisInteger = TTRowID(indexIntegralPart);

	TTBoolean weAreNotInBounds = makeInBounds(indexThisInteger, p_channel);  // out of range values are clipped

	if (weAreNotInBounds)
	{
		// no reason to interpolate, just use the first or last value
		get2d(indexThisInteger, p_channel, value);
		return kTTErrOutOfBounds; // and report an error (is that what we want?)
	} else {
		TTRowID indexNextInteger = indexThisInteger + 1;
		makeRowIDInBounds(indexNextInteger); //does not allow interpolation between first and last sample
			//  (is that what we want? if not, insert outOfBoundsWrap)

		TTSampleValue valueThisInteger, valueNextInteger;

		get2d(indexThisInteger, p_channel, valueThisInteger);
		get2d(indexNextInteger, p_channel, valueNextInteger);

		// simple linear interpolation adapted from TTDelay
		value = TTInterpolateLinear(valueThisInteger, valueNextInteger, indexFractionalPart);

		return kTTErrNone;
	}
}

/**	Set the sample value for a given index.
	The first number passed in the index parameter will be interpreted as the sample index.
	If there are three numbers passed, then the second number, if passed, will designate the channel index (defaults to zero).
	The final value will be used as the sample value that will be copied to the designated index.
*/
TTErr TTSampleMatrix::setValueAtIndex(const TTValue& index, TTValue& unusedOutput)
{
	TTUInt32		sampleIndex;
	TTUInt16		sampleChannel = 0;
	TTSampleValue	sampleValue;
	TTUInt8			i = 0;

	index.get(i++, sampleIndex);
	if (index.getSize() > 2)
		index.get(i++, sampleChannel);
	index.get(i++, sampleValue);

	return poke(sampleIndex, sampleChannel, sampleValue);
}

TTErr TTSampleMatrix::poke(const TTUInt64 index, const TTUInt16 channel, const TTSampleValue value)
{
	TTRowID p_index = index;
	TTColumnID p_channel = channel;

	TTBoolean weAreNotInBounds = makeInBounds(p_index,p_channel);

	if (weAreNotInBounds)
	{
		// don't go poking around out of bounds
		return kTTErrOutOfBounds;
	} else {
		set2d(p_index, p_channel, value);
		return kTTErrNone;
	}
}

TTErr TTSampleMatrix::fill(const TTValue& value, TTValue& unusedOutput)
{
	TTSymbol	fillAlgorithm = value;

	if (fillAlgorithm == kTTSym_sine) {
		for (TTUInt16 channel=0; channel<mNumChannels; channel++) {
			for (TTUInt64 i=0; i<mLengthInSamples; i++)
				set2d(i+1, channel+1, sin(kTTTwoPi * (i / (TTFloat64(mLengthInSamples) - 1.0))));
		}
	}
	else if (fillAlgorithm == kTTSym_sineMod) {							// (modulator version: ranges from 0.0 to 1.0, rather than -1.0 to 1.0)
		for (TTUInt16 channel=0; channel<mNumChannels; channel++) {
			for (TTUInt64 i=0; i<mLengthInSamples; i++)
				set2d(i+1, channel+1, 0.5 + (0.5 * sin(kTTTwoPi * (i / (TTFloat64(mLengthInSamples) - 1.0)))));
		}
	}
	else if (fillAlgorithm == kTTSym_cosine) {
		for (TTUInt16 channel=0; channel<mNumChannels; channel++) {
			for (TTUInt64 i=0; i<mLengthInSamples; i++)
				set2d(i+1, channel+1, cos(kTTTwoPi * (i / (TTFloat64(mLengthInSamples) - 1.0))));
		}
	}
	else if (fillAlgorithm == kTTSym_cosineMod) {
		for (TTUInt16 channel=0; channel<mNumChannels; channel++) {
			for (TTUInt64 i=0; i<mLengthInSamples; i++)
				set2d(i+1, channel+1, 0.5 + (0.5 * cos(kTTTwoPi * (i / (TTFloat64(mLengthInSamples) - 1.0)))));
		}
	}
	else if (fillAlgorithm == kTTSym_ramp) {
		for (TTUInt16 channel=0; channel<mNumChannels; channel++) {
			for (TTUInt64 i=0; i<mLengthInSamples; i++)
				set2d(i+1, channel+1, -1.0 + (2.0 * (float(i) / mLengthInSamples)));
		}
	}
	else if (fillAlgorithm == kTTSym_rampMod) {
		for (TTUInt16 channel=0; channel<mNumChannels; channel++) {
			for (TTUInt64 i=0; i<mLengthInSamples; i++)
				set2d(i+1, channel+1, float(i) / mLengthInSamples);
		}
	}
	else if (fillAlgorithm == kTTSym_sawtooth) {
		for (TTUInt16 channel=0; channel<mNumChannels; channel++) {
			for (TTUInt64 i=0; i<mLengthInSamples; i++)
				set2d(mLengthInSamples-i, channel+1, -1.0 + (2.0 * (float(i) / mLengthInSamples)));
		}
	}
	else if (fillAlgorithm == kTTSym_sawtoothMod) {
		for (TTUInt16 channel=0; channel<mNumChannels; channel++) {
			for (TTUInt64 i=0; i<mLengthInSamples; i++)
				set2d(mLengthInSamples-i, channel+1, float(i) / mLengthInSamples);
		}
	}
	else if (fillAlgorithm == kTTSym_triangle) {
		for (TTUInt16 channel=0; channel<mNumChannels; channel++) {
			for (TTUInt32 i=0; i < mLengthInSamples/2; i++) {
				set2d(i+1, channel+1, -1.0 + (4.0 * (float(i) / mLengthInSamples)));
				set2d(mLengthInSamples-i, channel+1, -1.0 + (4.0 * (float(i) / mLengthInSamples)));
			}
		}
	}
	else if (fillAlgorithm == kTTSym_triangleMod) {
		for (TTUInt16 channel=0; channel<mNumChannels; channel++) {
			for (TTUInt32 i=0; i < mLengthInSamples/2; i++) {
				set2d(i+1, channel+1, -1.0 + (4.0 * (float(i) / mLengthInSamples)));
				set2d(mLengthInSamples-i, channel+1, -1.0 + (4.0 * (float(i) / mLengthInSamples)));
			}
		}
	}

	return kTTErrNone;
}

TTErr TTSampleMatrix::normalize(const TTValue& aValue)
{
	TTFloat64			normalizeTo = 1.0;
	TTRowID				m = mLengthInSamples; // mFrameLength
	TTColumnID			n = mNumChannels; // mNumChannels
	TTSampleValuePtr	samples = (TTSampleValuePtr)getLockedPointer();
	TTFloat64			peakValue = 0.0;
	TTFloat64			scalar;

	if (aValue.getSize() && TTFloat64(aValue) > 0.0)
		normalizeTo = aValue;

	for (int k=0; k<m*n; k++) {
		TTFloat64 magnitude = abs(samples[k]);

		if (magnitude > peakValue)
			peakValue = magnitude;
	}

	scalar = normalizeTo / peakValue;

	for (int k=0; k<m*n; k++)
		samples[k] *= scalar;

	releaseLockedPointer();
	return kTTErrNone;
}
<commit_msg>SampleMatrix:fill() changing phase on triangle algorithm<commit_after>/** @file
 *
 * @ingroup dspLibrary
 *
 * @brief Container object that holds some audio in a chunk of memory.
 *
 * @see TTMatrix, TTAudioSignal
 *
 * @authors Timothy Place & Nathan Wolek
 *
 * @copyright Copyright © 2003-2012, Timothy Place & Nathan Wolek @n
 * This code is licensed under the terms of the "New BSD License" @n
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTSampleMatrix.h"
#include "TTInterpolate.h"

#define thisTTClass			TTSampleMatrix
#define thisTTClassName		"samplematrix"
#define thisTTClassTags		"audio, buffer"

TTObjectPtr TTSampleMatrix::instantiate(TTSymbol& name, TTValue& arguments)
{
	return new TTSampleMatrix(arguments);
}

extern "C" void TTSampleMatrix::registerClass()
{
	TTClassRegister(thisTTClassName, thisTTClassTags, TTSampleMatrix::instantiate);
}

TTSampleMatrix::TTSampleMatrix(TTValue& arguments) :
	TTMatrix(arguments),
	mSampleRate(44100.0)
{
	this->setTypeWithoutResize(kTypeFloat64);
	this->setElementCountWithoutResize(1);
	this->resize();
	this->mUserCount = 0;
	this->mBufferPoolStage = kSM_Idle;

	addAttributeWithGetterAndSetter(NumChannels,		kTypeInt32);
	addAttributeWithGetterAndSetter(Length,				kTypeFloat64);
	addAttributeWithGetterAndSetter(LengthInSamples,	kTypeInt32);
	addAttribute(SampleRate,							kTypeFloat64);
	addAttribute(				UserCount,				kTypeUInt16);
		addAttributeProperty(	UserCount, 				readOnly, kTTBoolYes);

	addMessage(normalize);
	addMessageWithArguments(fill);

	addMessageWithArguments(getValueAtIndex);
	registerMessage("peek", (TTMethod)&TTSampleMatrix::getValueAtIndex);
	registerMessage("peeki", (TTMethod)&TTSampleMatrix::getValueAtIndex);

	addMessageWithArguments(setValueAtIndex);
	registerMessage("poke", (TTMethod)&TTSampleMatrix::setValueAtIndex);

	// TODO: more messages to implement
	//	"readFile"   (requires libsndfile straightening-out)
	//	"writeFile"  (requires libsndfile straightening-out)
	//	a way to query attributes: for example what is the sr and bpm of an AIFF file?
}

TTSampleMatrix::~TTSampleMatrix()
{
	;
}

TTErr TTSampleMatrix::setNumChannels(const TTValue& newNumChannels)
{
	return setColumnCount(newNumChannels);
}

TTErr TTSampleMatrix::getNumChannels(TTValue& returnedChannelCount)
{
	returnedChannelCount = mNumChannels;
	return kTTErrNone;
}

TTErr TTSampleMatrix::setLength(const TTValue& newLength)
{
	TTValue newLengthInSamples = TTFloat64(newLength) * mSampleRate * 0.001;
	return setRowCount(newLengthInSamples);
}

TTErr TTSampleMatrix::getLength(TTValue& returnedLength)
{
	returnedLength = (mLengthInSamples / mSampleRate) * 1000.0;
	return kTTErrNone;
}

TTErr TTSampleMatrix::setLengthInSamples(const TTValue& newLengthInSamples)
{
	return setRowCount(newLengthInSamples);
}

TTErr TTSampleMatrix::getLengthInSamples(TTValue& returnedLengthInSamples)
{
	returnedLengthInSamples = mLengthInSamples;
	return kTTErrNone;
}

TTErr TTSampleMatrix::incrementUserCount()
{
	// could technically exceed 65,535 maximum, but we'll take the chance for now
	this->mUserCount++;
	return kTTErrNone;
}

TTErr TTSampleMatrix::decrementUserCount()
{
	if (this->mUserCount > 0)
	{
		this->mUserCount--;
		return kTTErrNone;
	} else {
		return kTTErrGeneric;
	}

}

TTErr TTSampleMatrix::getValueAtIndex(const TTValue& index, TTValue &output)
{
	TTUInt32		sampleIndex;
	TTUInt16		sampleChannel = 0;
	TTSampleValue	sampleValue;
	TTUInt8			i = 0;
	TTErr			err;

	index.get(i++, sampleIndex);
	if (index.getSize() > 2)		// TODO: sure would be nice to change the name of this method to "size" or something...
		index.get(i++, sampleChannel);

	err = peek(sampleIndex, sampleChannel, sampleValue);
	if (!err)
		output.set(i++, sampleValue);
	return err;
}

TTErr TTSampleMatrix::peek(const TTUInt64 index, const TTUInt16 channel, TTSampleValue& value)
{
	TTRowID p_index = index;
	TTColumnID p_channel = channel;

	TTBoolean weAreNotInBounds = makeInBounds(p_index, p_channel); // out of range values are clipped
	get2d(p_index, p_channel, value);

	if (weAreNotInBounds)
	{
		return kTTErrOutOfBounds;
	} else {
		return kTTErrNone;
	}
}

// a first attempt at interpolation for the SampleMatrix. should be viewed as temporary.
// needs to be fleshed out with different options...
TTErr TTSampleMatrix::peeki(const TTFloat64 index, const TTUInt16 channel, TTSampleValue& value)
{
	// variables needed
    TTColumnID p_channel = channel;
	TTFloat64 indexIntegralPart = 0;
	TTFloat64 indexFractionalPart = modf(index, &indexIntegralPart); // before makeInBounds to get the right value!
	TTRowID indexThisInteger = TTRowID(indexIntegralPart);

	TTBoolean weAreNotInBounds = makeInBounds(indexThisInteger, p_channel);  // out of range values are clipped

	if (weAreNotInBounds)
	{
		// no reason to interpolate, just use the first or last value
		get2d(indexThisInteger, p_channel, value);
		return kTTErrOutOfBounds; // and report an error (is that what we want?)
	} else {
		TTRowID indexNextInteger = indexThisInteger + 1;
		makeRowIDInBounds(indexNextInteger); //does not allow interpolation between first and last sample
			//  (is that what we want? if not, insert outOfBoundsWrap)

		TTSampleValue valueThisInteger, valueNextInteger;

		get2d(indexThisInteger, p_channel, valueThisInteger);
		get2d(indexNextInteger, p_channel, valueNextInteger);

		// simple linear interpolation adapted from TTDelay
		value = TTInterpolateLinear(valueThisInteger, valueNextInteger, indexFractionalPart);

		return kTTErrNone;
	}
}

/**	Set the sample value for a given index.
	The first number passed in the index parameter will be interpreted as the sample index.
	If there are three numbers passed, then the second number, if passed, will designate the channel index (defaults to zero).
	The final value will be used as the sample value that will be copied to the designated index.
*/
TTErr TTSampleMatrix::setValueAtIndex(const TTValue& index, TTValue& unusedOutput)
{
	TTUInt32		sampleIndex;
	TTUInt16		sampleChannel = 0;
	TTSampleValue	sampleValue;
	TTUInt8			i = 0;

	index.get(i++, sampleIndex);
	if (index.getSize() > 2)
		index.get(i++, sampleChannel);
	index.get(i++, sampleValue);

	return poke(sampleIndex, sampleChannel, sampleValue);
}

TTErr TTSampleMatrix::poke(const TTUInt64 index, const TTUInt16 channel, const TTSampleValue value)
{
	TTRowID p_index = index;
	TTColumnID p_channel = channel;

	TTBoolean weAreNotInBounds = makeInBounds(p_index,p_channel);

	if (weAreNotInBounds)
	{
		// don't go poking around out of bounds
		return kTTErrOutOfBounds;
	} else {
		set2d(p_index, p_channel, value);
		return kTTErrNone;
	}
}

TTErr TTSampleMatrix::fill(const TTValue& value, TTValue& unusedOutput)
{
	TTSymbol		fillAlgorithm = value;
	TTSampleValue	tempSample = 0.;
	TTUInt32		tempIndex = 0;

	if (fillAlgorithm == kTTSym_sine) {
		for (TTUInt16 channel=0; channel<mNumChannels; channel++) {
			for (TTUInt64 i=0; i<mLengthInSamples; i++)
				set2d(i+1, channel+1, sin(kTTTwoPi * (i / (TTFloat64(mLengthInSamples) - 1.0))));
		}
	}
	else if (fillAlgorithm == kTTSym_sineMod) {							// (modulator version: ranges from 0.0 to 1.0, rather than -1.0 to 1.0)
		for (TTUInt16 channel=0; channel<mNumChannels; channel++) {
			for (TTUInt64 i=0; i<mLengthInSamples; i++)
				set2d(i+1, channel+1, 0.5 + (0.5 * sin(kTTTwoPi * (i / (TTFloat64(mLengthInSamples) - 1.0)))));
		}
	}
	else if (fillAlgorithm == kTTSym_cosine) {
		for (TTUInt16 channel=0; channel<mNumChannels; channel++) {
			for (TTUInt64 i=0; i<mLengthInSamples; i++)
				set2d(i+1, channel+1, cos(kTTTwoPi * (i / (TTFloat64(mLengthInSamples) - 1.0))));
		}
	}
	else if (fillAlgorithm == kTTSym_cosineMod) {
		for (TTUInt16 channel=0; channel<mNumChannels; channel++) {
			for (TTUInt64 i=0; i<mLengthInSamples; i++)
				set2d(i+1, channel+1, 0.5 + (0.5 * cos(kTTTwoPi * (i / (TTFloat64(mLengthInSamples) - 1.0)))));
		}
	}
	else if (fillAlgorithm == kTTSym_ramp) {
		for (TTUInt16 channel=0; channel<mNumChannels; channel++) {
			for (TTUInt64 i=0; i<mLengthInSamples; i++)
				set2d(i+1, channel+1, -1.0 + (2.0 * (float(i) / mLengthInSamples)));
		}
	}
	else if (fillAlgorithm == kTTSym_rampMod) {
		for (TTUInt16 channel=0; channel<mNumChannels; channel++) {
			for (TTUInt64 i=0; i<mLengthInSamples; i++)
				set2d(i+1, channel+1, float(i) / mLengthInSamples);
		}
	}
	else if (fillAlgorithm == kTTSym_sawtooth) {
		for (TTUInt16 channel=0; channel<mNumChannels; channel++) {
			for (TTUInt64 i=0; i<mLengthInSamples; i++)
				set2d(mLengthInSamples-i, channel+1, -1.0 + (2.0 * (float(i) / mLengthInSamples)));
		}
	}
	else if (fillAlgorithm == kTTSym_sawtoothMod) {
		for (TTUInt16 channel=0; channel<mNumChannels; channel++) {
			for (TTUInt64 i=0; i<mLengthInSamples; i++)
				set2d(mLengthInSamples-i, channel+1, float(i) / mLengthInSamples);
		}
	}
	else if (fillAlgorithm == kTTSym_triangle) {
		for (TTUInt16 channel=0; channel<mNumChannels; channel++) {
			tempIndex = 3*mLengthInSamples/4;
			for (TTUInt32 i=0; i < mLengthInSamples/4; i++) {
				tempSample = -1.0 + (4.0 * (float(i) / mLengthInSamples));
				set2d(i+tempIndex, channel+1, tempSample);
				set2d(tempIndex-i, channel+1, tempSample);
			}
			tempIndex = mLengthInSamples/2;
			for (TTUInt32 i=0; i < mLengthInSamples/4; i++) {
				tempSample = 4.0 * (float(i) / mLengthInSamples);
				set2d(i, channel+1, tempSample);
				set2d(tempIndex-i, channel+1, tempSample);
			}
		}
	}
	else if (fillAlgorithm == kTTSym_triangleMod) {
		for (TTUInt16 channel=0; channel<mNumChannels; channel++) {
			for (TTUInt32 i=0; i < mLengthInSamples/2; i++) {
				set2d(i+1, channel+1, -1.0 + (4.0 * (float(i) / mLengthInSamples)));
				set2d(mLengthInSamples-i, channel+1, -1.0 + (4.0 * (float(i) / mLengthInSamples)));
			}
		}
	}

	return kTTErrNone;
}

TTErr TTSampleMatrix::normalize(const TTValue& aValue)
{
	TTFloat64			normalizeTo = 1.0;
	TTRowID				m = mLengthInSamples; // mFrameLength
	TTColumnID			n = mNumChannels; // mNumChannels
	TTSampleValuePtr	samples = (TTSampleValuePtr)getLockedPointer();
	TTFloat64			peakValue = 0.0;
	TTFloat64			scalar;

	if (aValue.getSize() && TTFloat64(aValue) > 0.0)
		normalizeTo = aValue;

	for (int k=0; k<m*n; k++) {
		TTFloat64 magnitude = abs(samples[k]);

		if (magnitude > peakValue)
			peakValue = magnitude;
	}

	scalar = normalizeTo / peakValue;

	for (int k=0; k<m*n; k++)
		samples[k] *= scalar;

	releaseLockedPointer();
	return kTTErrNone;
}
<|endoftext|>


<commit_before>/**
 *	@file		imgproc_aux.hpp
 *	@brief		Defines the image class and several utility functions
 *	@author		seonho.oh@gmail.com
 *	@date		2013-07-01
 *	@version	1.0
 *
 *	@section	LICENSE
 *
 *		Copyright (c) 2007-2014, Seonho Oh
 *		All rights reserved.
 *
 *		Redistribution and use in source and binary forms, with or without
 *		modification, are permitted provided that the following conditions are
 *		met:
 *
 *		    * Redistributions of source code must retain the above copyright
 *		    notice, this list of conditions and the following disclaimer.
 *		    * Redistributions in binary form must reproduce the above copyright
 *		    notice, this list of conditions and the following disclaimer in the
 *		    documentation and/or other materials provided with the distribution.
 *		    * Neither the name of the <ORGANIZATION> nor the names of its
 *		    contributors may be used to endorse or promote products derived from
 *		    this software without specific prior written permission.
 *
 *		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 *		IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 *		TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 *		PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 *		OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 *		PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 *		PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 *		LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *		NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *		SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#ifdef USE_OPENCV

#ifdef _MSC_VER
#include <mycv.hpp>	// for OpenCV
#pragma comment(lib, OPENCV_LIB_EXPAND("core"))
#pragma comment(lib, OPENCV_LIB_EXPAND("imgproc"))
#pragma comment(lib, OPENCV_LIB_EXPAND("highgui"))
#pragma comment(lib, OPENCV_LIB_EXPAND("video"))
#else
#include <opencv2/opencv.hpp>
#endif

#endif

#include <armadillo>
using namespace arma;

#include "arma_ext.hpp"

namespace auxiliary
{
    /**
	 *	@brief	Template class for size type
	 *	@tparam	T	the type of width and height
	 */
	template <typename T>
	class Size : public arma::Col<T>::template fixed<2>
	{
	public:

		Size(T w = 0, T h = 0)
		{
			this->at(0) = w;
			this->at(1) = h;
		}

		T width() const     { return this->at(0); }
		T height() const    { return this->at(1); }

		T& width()          { return this->at(0); }
		T& height()         { return this->at(1); }
	};

	//!	A template image class.
	template <typename T>
	class Image : public Mat<T>
	{
	public:
		typedef T									elem_type;	///< the type of elements stored in the matrix
		typedef typename get_pod_type<T>::result	pod_type;	///< if eT is non-complex, pod_type is same as eT. otherwise, pod_type is the underlying type used by std::complex

		typedef arma::uword							size_type;

		/// Constructor
		Image(): Mat<T>() {}

		/// Constructor
		Image(const Mat<T>& m): Mat<T>(m) {}

		/// Constructor
		Image(const size_type width, const size_type height) : Mat<T>(height, width) {}

		/// Constructor
		template <typename DT>
		Image(const Mat<DT>& m): Mat<T>(m.n_rows, m.n_cols)
		{
			T* ptr = this->memptr();
			// type conversion
#if defined(USE_PPL)
			concurrency::parallel_for(size_type(0), m.n_elem, [&](size_type i) {
#elif defined(USE_OPENMP)
	#pragma omp parallel for
            for (int si = 0 ; si < (int)m.n_elem ; si++) {
				size_type i = (size_type)si;
#else
            for (size_type i = 0 ; i < m.n_elem ; i++)
#endif
				ptr[i] = arma_ext::saturate_cast<T>(m(i));
#if defined(USE_PPL)
			});
#elif defined(USE_OPENMP)
			}
#endif
		}

		/// Dummy function
		void release() {}

		/// Get image width
		inline size_type width() const { return this->n_cols; }

		/// Get image height
		inline size_type height() const { return this->n_rows; }

		/// Resize image
		inline void resize(size_type width, size_type height)
		{
			this->set_size(height, width);
		}

		// Operator overloading
		operator Mat<T>&()
		{
			return static_cast<Mat<T> >(*this);
		}
	};

	/**
	 *	@brief	Retrieves a pixel rectangle from an image with sub-pixel accuracy.
	 *	@param img source image
	 *	@param patchsize	The size of the extracted patch.
	 *	@param center		The coordinate of the center of the extracted rectangle within the source image.
	 *						The center must be inside of image.
	 *	@return	Extracted patch that has the size @c patchsize and the same format as @c img.
	 *			This function extracts pixels from src:
	 *			\f[
	 *				dst(x, y) = src(x + center.x - (dst.cols - 1) * 0.5, y + center.y - (dst.rows - 1) * 0.5)
	 *			\f]
	 *			where the values of the pixels at non-integer coordinates are retrieved using bilinear interpolation.
	 *			While the center of the rectangle must be inside the image, parts of the rectangle may be outside.
	 *			In this case, extrapolate the pixel values by replication border condition.
	 */
	template <typename pixel_type, typename vec_type>
	static arma::Mat<pixel_type> getRectSubPix(const Image<pixel_type>& img, Size<arma_ext::uword> patchsize, const vec_type center)
	{
		typedef typename vec_type::elem_type elem_type;
		typedef typename arma_ext::size_type size_type;
		arma::Mat<pixel_type> out(patchsize.height(), patchsize.width());

#ifdef __VXWORKS__
		typename arma::Col<elem_type>::template fixed<2> center_;
		center_[0] = center[0];
		center_[1] = center[1];
#else
        typename arma::Col<elem_type>::template fixed<2> center_ = center;
#endif

		center_[0] -= (elem_type)(patchsize.width() - 1) * (elem_type)0.5;
		center_[1] -= (elem_type)(patchsize.height() - 1) * (elem_type)0.5;

		int ipx = (int)std::floor(center_[0]);
		int ipy = (int)std::floor(center_[1]);

		elem_type ox = center_[0] - (elem_type)ipx;
		elem_type oy = center_[1] - (elem_type)ipy;

		elem_type a11 = (1 - ox) * (1 - oy),
				  a12 =      ox  * (1 - oy),
				  a21 = (1 - ox) * oy,
				  a22 =      ox  * oy;

		if (0 <= ipx && ipx + patchsize.width() < img.n_cols &&
			0 <= ipy && ipy + patchsize.height() < img.n_rows) {
			// extracted rectangle is totally inside the image
#ifdef USE_PPL
			concurrency::parallel_for(arma_ext::size_type(0), out.n_cols, [&](arma_ext::size_type j) {
#elif defined(USE_OPENMP)
	#pragma omp parallel for
			for (int sj = 0 ; sj < (int)out.n_cols ; sj++) {
				size_type j = (size_type)sj;
#else
            for (size_type j = 0 ; j < out.n_cols ; j++) {
#endif
				pixel_type* ptr = out.colptr(j);
				const pixel_type* src = img.colptr(ipx + j) + ipy;
				size_type i;
				for (i = 0 ; i < out.n_rows ; i++) {
					// bilinear interpolation
					ptr[i] = arma_ext::saturate_cast<pixel_type>((elem_type)src[i                 ] * a11 +
							(elem_type)src[i + 1             ] * a21 +
							(elem_type)src[i + img.n_rows    ] * a12 +
							(elem_type)src[i + img.n_rows + 1] * a22);
				}
#ifdef USE_PPL
			});
#else
			}
#endif
		} else {
			arma::ivec4 r;

			// adjust rectangle
			int sox = 0, soy = 0;

			// -------- begin --------
			if (ipx >= 0) {
				sox += ipx;	// + ipx
				r[0] = 0;
			} else {
				r[0] = -ipx;
				if (r[0] > (int)patchsize.width())
					r[0] = patchsize.width();
			}

			if (ipx + (int)patchsize.width() < (int)img.n_cols)
				r[2] = patchsize.width();
			else {
				r[2] = (int)img.n_cols - ipx - 1;
				if (r[2] < 0) {
					sox += r(2);	// + width
					r[2] = 0;
				}
			}

			if (ipy >= 0) {
				soy += ipy;	// + ipy
				r[1] = 0;
			} else {
				r[1] = -ipy;
				if (r[1] > (int)patchsize.height())
					r[1] = patchsize.height();
			}

			if (ipy + (int)patchsize.height() < (int)img.n_rows)
				r[3] = patchsize.height();
			else {
				r[3] = (int)img.n_rows - ipy - 1;
				if (r[3] < 0) {
					soy += r[3];	// + height
					r[3] = 0;
				}
			}
			// --------- end ---------

			//soy -= r(1);

			elem_type b1 = (elem_type)1.0 - ox,
					  b2 = ox;

			const pixel_type* src1 = img.colptr(sox) + soy;
			for (size_type j = 0 ; j < out.n_cols ; j++) {
				pixel_type* ptr = out.colptr(j);
				const pixel_type* src2 = src1 + img.n_rows;

				if ((int)j < r[0] || (int)j >= r[2])
					src2 -= img.n_rows;

				size_type i = 0;
				for (; i < (size_type)r(1) ; i++)
					ptr[i] = arma_ext::saturate_cast<pixel_type>((elem_type)src1[r[1]] * b1 + (elem_type)src2[r[1]] * b2);

				for ( ; i < (size_type)r(3) ; i++) {
					// bilinear interpolation
					ptr[i] = arma_ext::saturate_cast<pixel_type>((elem_type)src1[i    ] * a11 +
							(elem_type)src1[i + 1] * a21 +
							(elem_type)src2[i    ] * a12 +
							(elem_type)src2[i + 1] * a22);
				}

				for ( ; i < out.n_rows ; i++)
					ptr[i] = arma_ext::saturate_cast<pixel_type>((elem_type)src1[r[3]] * b1 + (elem_type)src2[r[3]] * b2);

				if ((int)j < r[2])
					src1 = src2;
			}
		}

		return out;
	}

	/**
	 *	@brief	Gaussian blur using 12x12 with given sigma.
	 *	@param	img		An input image.
	 *	@param	h		The blur kernel.
	 *	@return	The blurred image.
	 */
    template <typename pixel_type>
	Image<pixel_type> blur(const Image<pixel_type>& img, const mat& h)
	{
		typedef typename Image<pixel_type>::size_type size_type;

		size_type kernel_size = h.n_rows;

		uword shift = (uword)std::ceil((kernel_size - 1) / 2.0);

		// convolution
		mat C = arma_ext::conv2(conv_to<mat>::from(img), h);
		C = C(span(shift, C.n_rows - shift), span(shift, C. n_cols - shift));

		return Image<pixel_type>(C);
	}

#ifdef USE_OPENCV
	//!	Convert Image type to the cv::Mat type.
    template <typename pixel_type>
	cv::Mat tocvMat(const Image<pixel_type>& img)
	{
		cv::Mat out(img.n_rows, img.n_cols, cv::DataType<pixel_type>::type); //!
        Image<pixel_type> t = img.t().eval();
		memcpy(out.data, t.memptr(), sizeof(pixel_type) * t.n_elem);

		//cv::imshow(name, out);
		return out;
	}

	/**
	 *	@brief	Convert BGR image or colormap to grayscale.
	 *	@param img	the truecolor BGR image to be converted into grayscale
	 *	@return	grayscale intensity image
	 *	@see	http://www.mathworks.co.kr/kr/help/images/ref/rgb2gray.html
	 */
    template <typename pixel_type>
	Image<pixel_type>	bgr2gray(const cv::Mat& img)
	{
		arma::Mat<pixel_type> gray(img.cols, img.rows);
		pixel_type* ptr = gray.memptr();
#if 0
		concurrency::parallel_for(0, img.rows, [&](int r) {
		//for (int r = 0 ; r < img.rows ; r++) {
			const uchar* src = img.ptr(r);
			uchar* dst = ptr + gray.n_rows * r;
			for (int c = 0 ; c < img.cols ; c++, src += 3)
				dst[c] = arma_ext::round<uchar>(src[2] * 0.298936021293776 + src[1] * 0.587043074451121 + src[0] * 0.114020904255103);
		//}
		});
#else
		cv::Mat bw;
		cv::cvtColor(img, bw, CV_BGR2GRAY);
		memcpy(ptr, bw.data, sizeof(pixel_type) * bw.total());
#endif

		return Image<pixel_type>(gray.t());
	}
#endif
}
<commit_msg>Fix Image size mismatch problem for blur fuction.<commit_after>/**
 *	@file		imgproc_aux.hpp
 *	@brief		Defines the image class and several utility functions
 *	@author		seonho.oh@gmail.com
 *	@date		2013-07-01
 *	@version	1.0
 *
 *	@section	LICENSE
 *
 *		Copyright (c) 2007-2014, Seonho Oh
 *		All rights reserved.
 *
 *		Redistribution and use in source and binary forms, with or without
 *		modification, are permitted provided that the following conditions are
 *		met:
 *
 *		    * Redistributions of source code must retain the above copyright
 *		    notice, this list of conditions and the following disclaimer.
 *		    * Redistributions in binary form must reproduce the above copyright
 *		    notice, this list of conditions and the following disclaimer in the
 *		    documentation and/or other materials provided with the distribution.
 *		    * Neither the name of the <ORGANIZATION> nor the names of its
 *		    contributors may be used to endorse or promote products derived from
 *		    this software without specific prior written permission.
 *
 *		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 *		IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 *		TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 *		PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 *		OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 *		PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 *		PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 *		LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *		NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *		SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#ifdef USE_OPENCV

#ifdef _MSC_VER
#include <mycv.hpp>	// for OpenCV
#pragma comment(lib, OPENCV_LIB_EXPAND("core"))
#pragma comment(lib, OPENCV_LIB_EXPAND("imgproc"))
#pragma comment(lib, OPENCV_LIB_EXPAND("highgui"))
#pragma comment(lib, OPENCV_LIB_EXPAND("video"))
#else
#include <opencv2/opencv.hpp>
#endif

#endif

#include <armadillo>
using namespace arma;

#include "arma_ext.hpp"

namespace auxiliary
{
    /**
	 *	@brief	Template class for size type
	 *	@tparam	T	the type of width and height
	 */
	template <typename T>
	class Size : public arma::Col<T>::template fixed<2>
	{
	public:

		Size(T w = 0, T h = 0)
		{
			this->at(0) = w;
			this->at(1) = h;
		}

		T width() const     { return this->at(0); }
		T height() const    { return this->at(1); }

		T& width()          { return this->at(0); }
		T& height()         { return this->at(1); }
	};

	//!	A template image class.
	template <typename T>
	class Image : public Mat<T>
	{
	public:
		typedef T									elem_type;	///< the type of elements stored in the matrix
		typedef typename get_pod_type<T>::result	pod_type;	///< if eT is non-complex, pod_type is same as eT. otherwise, pod_type is the underlying type used by std::complex

		typedef arma::uword							size_type;

		/// Constructor
		Image(): Mat<T>() {}

		/// Constructor
		Image(const Mat<T>& m): Mat<T>(m) {}

		/// Constructor
		Image(const size_type width, const size_type height) : Mat<T>(height, width) {}

		/// Constructor
		template <typename DT>
		Image(const Mat<DT>& m): Mat<T>(m.n_rows, m.n_cols)
		{
			T* ptr = this->memptr();
			// type conversion
#if defined(USE_PPL)
			concurrency::parallel_for(size_type(0), m.n_elem, [&](size_type i) {
#elif defined(USE_OPENMP)
	#pragma omp parallel for
            for (int si = 0 ; si < (int)m.n_elem ; si++) {
				size_type i = (size_type)si;
#else
            for (size_type i = 0 ; i < m.n_elem ; i++)
#endif
				ptr[i] = arma_ext::saturate_cast<T>(m(i));
#if defined(USE_PPL)
			});
#elif defined(USE_OPENMP)
			}
#endif
		}

		/// Dummy function
		void release() {}

		/// Get image width
		inline size_type width() const { return this->n_cols; }

		/// Get image height
		inline size_type height() const { return this->n_rows; }

		/// Resize image
		inline void resize(size_type width, size_type height)
		{
			this->set_size(height, width);
		}

		// Operator overloading
		operator Mat<T>&()
		{
			return static_cast<Mat<T> >(*this);
		}
	};

	/**
	 *	@brief	Retrieves a pixel rectangle from an image with sub-pixel accuracy.
	 *	@param img source image
	 *	@param patchsize	The size of the extracted patch.
	 *	@param center		The coordinate of the center of the extracted rectangle within the source image.
	 *						The center must be inside of image.
	 *	@return	Extracted patch that has the size @c patchsize and the same format as @c img.
	 *			This function extracts pixels from src:
	 *			\f[
	 *				dst(x, y) = src(x + center.x - (dst.cols - 1) * 0.5, y + center.y - (dst.rows - 1) * 0.5)
	 *			\f]
	 *			where the values of the pixels at non-integer coordinates are retrieved using bilinear interpolation.
	 *			While the center of the rectangle must be inside the image, parts of the rectangle may be outside.
	 *			In this case, extrapolate the pixel values by replication border condition.
	 */
	template <typename pixel_type, typename vec_type>
	static arma::Mat<pixel_type> getRectSubPix(const Image<pixel_type>& img, Size<arma_ext::uword> patchsize, const vec_type center)
	{
		typedef typename vec_type::elem_type elem_type;
		typedef typename arma_ext::size_type size_type;
		arma::Mat<pixel_type> out(patchsize.height(), patchsize.width());

#ifdef __VXWORKS__
		typename arma::Col<elem_type>::template fixed<2> center_;
		center_[0] = center[0];
		center_[1] = center[1];
#else
        typename arma::Col<elem_type>::template fixed<2> center_ = center;
#endif

		center_[0] -= (elem_type)(patchsize.width() - 1) * (elem_type)0.5;
		center_[1] -= (elem_type)(patchsize.height() - 1) * (elem_type)0.5;

		int ipx = (int)std::floor(center_[0]);
		int ipy = (int)std::floor(center_[1]);

		elem_type ox = center_[0] - (elem_type)ipx;
		elem_type oy = center_[1] - (elem_type)ipy;

		elem_type a11 = (1 - ox) * (1 - oy),
				  a12 =      ox  * (1 - oy),
				  a21 = (1 - ox) * oy,
				  a22 =      ox  * oy;

		if (0 <= ipx && ipx + patchsize.width() < img.n_cols &&
			0 <= ipy && ipy + patchsize.height() < img.n_rows) {
			// extracted rectangle is totally inside the image
#ifdef USE_PPL
			concurrency::parallel_for(arma_ext::size_type(0), out.n_cols, [&](arma_ext::size_type j) {
#elif defined(USE_OPENMP)
	#pragma omp parallel for
			for (int sj = 0 ; sj < (int)out.n_cols ; sj++) {
				size_type j = (size_type)sj;
#else
            for (size_type j = 0 ; j < out.n_cols ; j++) {
#endif
				pixel_type* ptr = out.colptr(j);
				const pixel_type* src = img.colptr(ipx + j) + ipy;
				size_type i;
				for (i = 0 ; i < out.n_rows ; i++) {
					// bilinear interpolation
					ptr[i] = arma_ext::saturate_cast<pixel_type>((elem_type)src[i                 ] * a11 +
							(elem_type)src[i + 1             ] * a21 +
							(elem_type)src[i + img.n_rows    ] * a12 +
							(elem_type)src[i + img.n_rows + 1] * a22);
				}
#ifdef USE_PPL
			});
#else
			}
#endif
		} else {
			arma::ivec4 r;

			// adjust rectangle
			int sox = 0, soy = 0;

			// -------- begin --------
			if (ipx >= 0) {
				sox += ipx;	// + ipx
				r[0] = 0;
			} else {
				r[0] = -ipx;
				if (r[0] > (int)patchsize.width())
					r[0] = patchsize.width();
			}

			if (ipx + (int)patchsize.width() < (int)img.n_cols)
				r[2] = patchsize.width();
			else {
				r[2] = (int)img.n_cols - ipx - 1;
				if (r[2] < 0) {
					sox += r(2);	// + width
					r[2] = 0;
				}
			}

			if (ipy >= 0) {
				soy += ipy;	// + ipy
				r[1] = 0;
			} else {
				r[1] = -ipy;
				if (r[1] > (int)patchsize.height())
					r[1] = patchsize.height();
			}

			if (ipy + (int)patchsize.height() < (int)img.n_rows)
				r[3] = patchsize.height();
			else {
				r[3] = (int)img.n_rows - ipy - 1;
				if (r[3] < 0) {
					soy += r[3];	// + height
					r[3] = 0;
				}
			}
			// --------- end ---------

			//soy -= r(1);

			elem_type b1 = (elem_type)1.0 - ox,
					  b2 = ox;

			const pixel_type* src1 = img.colptr(sox) + soy;
			for (size_type j = 0 ; j < out.n_cols ; j++) {
				pixel_type* ptr = out.colptr(j);
				const pixel_type* src2 = src1 + img.n_rows;

				if ((int)j < r[0] || (int)j >= r[2])
					src2 -= img.n_rows;

				size_type i = 0;
				for (; i < (size_type)r(1) ; i++)
					ptr[i] = arma_ext::saturate_cast<pixel_type>((elem_type)src1[r[1]] * b1 + (elem_type)src2[r[1]] * b2);

				for ( ; i < (size_type)r(3) ; i++) {
					// bilinear interpolation
					ptr[i] = arma_ext::saturate_cast<pixel_type>((elem_type)src1[i    ] * a11 +
							(elem_type)src1[i + 1] * a21 +
							(elem_type)src2[i    ] * a12 +
							(elem_type)src2[i + 1] * a22);
				}

				for ( ; i < out.n_rows ; i++)
					ptr[i] = arma_ext::saturate_cast<pixel_type>((elem_type)src1[r[3]] * b1 + (elem_type)src2[r[3]] * b2);

				if ((int)j < r[2])
					src1 = src2;
			}
		}

		return out;
	}

	/**
	 *	@brief	Gaussian blur with given blur kernel.
	 *	@param	img		An input image.
	 *	@param	h		The blur kernel.
	 *	@return	The blurred image.
	 */
    template <typename pixel_type>
	inline Image<pixel_type> blur(const Image<pixel_type>& img, const mat& h)
	{
		typedef typename Image<pixel_type>::size_type size_type;
		return Image<pixel_type>(arma_ext::conv2(conv_to<mat>::from(img), h, arma_ext::same).eval());
	}

#ifdef USE_OPENCV
	//!	Convert Image type to the cv::Mat type.
    template <typename pixel_type>
	cv::Mat tocvMat(const Image<pixel_type>& img)
	{
		cv::Mat out(img.n_rows, img.n_cols, cv::DataType<pixel_type>::type); //!
        Image<pixel_type> t = img.t().eval();
		memcpy(out.data, t.memptr(), sizeof(pixel_type) * t.n_elem);

		//cv::imshow(name, out);
		return out;
	}

	/**
	 *	@brief	Convert BGR image or colormap to grayscale.
	 *	@param img	the truecolor BGR image to be converted into grayscale
	 *	@return	grayscale intensity image
	 *	@see	http://www.mathworks.co.kr/kr/help/images/ref/rgb2gray.html
	 */
    template <typename pixel_type>
	Image<pixel_type>	bgr2gray(const cv::Mat& img)
	{
		arma::Mat<pixel_type> gray(img.cols, img.rows);
		pixel_type* ptr = gray.memptr();
#if 0
		concurrency::parallel_for(0, img.rows, [&](int r) {
		//for (int r = 0 ; r < img.rows ; r++) {
			const uchar* src = img.ptr(r);
			uchar* dst = ptr + gray.n_rows * r;
			for (int c = 0 ; c < img.cols ; c++, src += 3)
				dst[c] = arma_ext::round<uchar>(src[2] * 0.298936021293776 + src[1] * 0.587043074451121 + src[0] * 0.114020904255103);
		//}
		});
#else
		cv::Mat bw;
		cv::cvtColor(img, bw, CV_BGR2GRAY);
		memcpy(ptr, bw.data, sizeof(pixel_type) * bw.total());
#endif

		return Image<pixel_type>(gray.t());
	}
#endif
}
<|endoftext|>


<commit_before>/*
 * LinuxGLRenderContext.cpp
 *
 * This file is part of the "LLGL" project (Copyright (c) 2015 by Lukas Hermanns)
 * See "LICENSE.txt" for license information.
 */

#include "../../GLRenderContext.h"
#include "../../../../Platform/Linux/LinuxWindow.h"
#include <LLGL/Platform/NativeHandle.h>
#include <LLGL/Log.h>
#include "../../Ext/GLExtensions.h"
#include "../../Ext/GLExtensionLoader.h"

namespace LLGL
{

void GLRenderContext::Present()
{
    glXSwapBuffers(context_.display, context_.wnd);
}

bool GLRenderContext::GLMakeCurrent(GLRenderContext* renderContext)
{
    if (renderContext)
    {
        const auto& ctx = renderContext->context_;
        return glXMakeCurrent(ctx.display, ctx.wnd, ctx.glc);
    }
    else
        return glXMakeCurrent(nullptr, 0, 0);
    return false;
}

/*
 * ======= Private: =======
 */

void GLRenderContext::GetNativeContextHandle(NativeContextHandle& windowContext)
{
    /* Open X11 display */
    windowContext.display = XOpenDisplay(nullptr);
    if (!windowContext.display)
        throw std::runtime_error("failed to open X11 display");

    windowContext.parentWindow  = DefaultRootWindow(windowContext.display);
    windowContext.screen        = DefaultScreen(windowContext.display);

    /* Create XVisualInfo and Colormap structures */
    int visualAttribs[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };

    windowContext.visual    = glXChooseVisual(windowContext.display, windowContext.screen, visualAttribs);
    windowContext.colorMap  = XCreateColormap(windowContext.display, windowContext.parentWindow, windowContext.visual->visual, AllocNone);

    if (!windowContext.visual)
        throw std::runtime_error("failed to choose X11 visual for OpenGL");
}

void GLRenderContext::CreateContext(GLRenderContext* sharedRenderContext)
{
    GLXContext glcShared = (sharedRenderContext != nullptr ? sharedRenderContext->context_.glc : nullptr);

    /* Get X11 display, window, and visual information */
    auto& window = static_cast<const LinuxWindow&>(GetWindow());
    NativeHandle nativeHandle;
    window.GetNativeHandle(&nativeHandle);

    context_.display    = nativeHandle.display;
    context_.wnd        = nativeHandle.window;
    context_.visual     = nativeHandle.visual;

    if (!context_.display || !context_.wnd || !context_.visual)
        throw std::invalid_argument("failed to create OpenGL context on X11 client, due to missing arguments");

    /* Create OpenGL context with X11 lib */
    context_.glc        = glXCreateContext(context_.display, context_.visual, glcShared, GL_TRUE);

    /* Make new OpenGL context current */
    if (glXMakeCurrent(context_.display, context_.wnd, context_.glc) != True)
        Log::StdErr() << "failed to make OpenGL render context current (glXMakeCurrent)" << std::endl;
}

void GLRenderContext::DeleteContext()
{
    glXDestroyContext(context_.display, context_.glc);
}

bool GLRenderContext::SetupVsyncInterval()
{
    /* Load GL extension "glXSwapIntervalSGI" to set v-sync interval */
    if (glXSwapIntervalSGI || LoadSwapIntervalProcs())
    {
        /* Setup v-sync interval */
        int interval = (desc_.vsync.enabled ? static_cast<int>(desc_.vsync.interval) : 0);
        return (glXSwapIntervalSGI(interval) == 0);
    }
    return false;
}

} // /namespace LLGL

// ================================================================================
<commit_msg>Updated for multi-sampled render context on Linux port.<commit_after>/*
 * LinuxGLRenderContext.cpp
 *
 * This file is part of the "LLGL" project (Copyright (c) 2015 by Lukas Hermanns)
 * See "LICENSE.txt" for license information.
 */

#include "../../GLRenderContext.h"
#include "../../../../Platform/Linux/LinuxWindow.h"
#include <LLGL/Platform/NativeHandle.h>
#include <LLGL/Log.h>
#include "../../Ext/GLExtensions.h"
#include "../../Ext/GLExtensionLoader.h"

namespace LLGL
{

void GLRenderContext::Present()
{
    glXSwapBuffers(context_.display, context_.wnd);
}

bool GLRenderContext::GLMakeCurrent(GLRenderContext* renderContext)
{
    if (renderContext)
    {
        const auto& ctx = renderContext->context_;
        return glXMakeCurrent(ctx.display, ctx.wnd, ctx.glc);
    }
    else
        return glXMakeCurrent(nullptr, 0, 0);
    return false;
}

/*
 * ======= Private: =======
 */

void GLRenderContext::GetNativeContextHandle(NativeContextHandle& windowContext)
{
    /* Open X11 display */
    windowContext.display = XOpenDisplay(nullptr);
    if (!windowContext.display)
        throw std::runtime_error("failed to open X11 display");

    windowContext.parentWindow  = DefaultRootWindow(windowContext.display);
    windowContext.screen        = DefaultScreen(windowContext.display);

    GLXFBConfig fbc = 0;

    if (desc_.multiSampling.enabled)
    {
        /* Create FB configuration for multi-sampling */
        const int fbAttribs[] =
        {
            GLX_X_RENDERABLE,   True,
            GLX_DRAWABLE_TYPE,  GLX_WINDOW_BIT,
            GLX_RENDER_TYPE,    GLX_RGBA_BIT,
            GLX_X_VISUAL_TYPE,  GLX_TRUE_COLOR,
            GLX_RED_SIZE,       8,
            GLX_GREEN_SIZE,     8,
            GLX_BLUE_SIZE,      8,
            GLX_ALPHA_SIZE,     8,
            GLX_DEPTH_SIZE,     24,
            GLX_STENCIL_SIZE,   8,
            GLX_DOUBLEBUFFER,   True,
            GLX_SAMPLE_BUFFERS, 1,
            GLX_SAMPLES,        static_cast<int>(desc_.multiSampling.samples),
            None
        };

        int attribs[100];
        memcpy(attribs, fbAttribs, sizeof(fbAttribs));

        int fbCount = 0;
        GLXFBConfig* fbcList = glXChooseFBConfig(windowContext.display, windowContext.screen, attribs, &fbCount);

        if (fbcList)
        {
            if (fbCount > 0)
                fbc = fbcList[0];
            XFree(fbcList);
        }
    }

    if (fbc)
    {
        /* Choose XVisualInfo from FB config */
        windowContext.visual = glXGetVisualFromFBConfig(windowContext.display, fbc);
    }
    else
    {
        if (desc_.multiSampling.enabled)
            Log::StdErr() << "failed to choose XVisualInfo for multi-sampling" << std::endl;

        /* Choose standard XVisualInfo structure */
        int visualAttribs[] =
        {
            GLX_RGBA,
            GLX_DEPTH_SIZE, 24,
            GLX_DOUBLEBUFFER,
            None
        };

        windowContext.visual = glXChooseVisual(windowContext.display, windowContext.screen, visualAttribs);
    }

    /* Create Colormap structure */
    windowContext.colorMap = XCreateColormap(windowContext.display, windowContext.parentWindow, windowContext.visual->visual, AllocNone);

    if (!windowContext.visual)
        throw std::runtime_error("failed to choose X11 visual for OpenGL");
}

void GLRenderContext::CreateContext(GLRenderContext* sharedRenderContext)
{
    GLXContext glcShared = (sharedRenderContext != nullptr ? sharedRenderContext->context_.glc : nullptr);

    /* Get X11 display, window, and visual information */
    auto& window = static_cast<const LinuxWindow&>(GetWindow());
    NativeHandle nativeHandle;
    window.GetNativeHandle(&nativeHandle);

    context_.display    = nativeHandle.display;
    context_.wnd        = nativeHandle.window;
    context_.visual     = nativeHandle.visual;

    if (!context_.display || !context_.wnd || !context_.visual)
        throw std::invalid_argument("failed to create OpenGL context on X11 client, due to missing arguments");

    /* Create OpenGL context with X11 lib */
    context_.glc        = glXCreateContext(context_.display, context_.visual, glcShared, GL_TRUE);

    /* Make new OpenGL context current */
    if (glXMakeCurrent(context_.display, context_.wnd, context_.glc) != True)
        Log::StdErr() << "failed to make OpenGL render context current (glXMakeCurrent)" << std::endl;
}

void GLRenderContext::DeleteContext()
{
    glXDestroyContext(context_.display, context_.glc);
}

bool GLRenderContext::SetupVsyncInterval()
{
    /* Load GL extension "glXSwapIntervalSGI" to set v-sync interval */
    if (glXSwapIntervalSGI || LoadSwapIntervalProcs())
    {
        /* Setup v-sync interval */
        int interval = (desc_.vsync.enabled ? static_cast<int>(desc_.vsync.interval) : 0);
        return (glXSwapIntervalSGI(interval) == 0);
    }
    return false;
}

} // /namespace LLGL

// ================================================================================
<|endoftext|>


<commit_before><commit_msg>Do one more network layout use case<commit_after><|endoftext|>


<commit_before>/**
Copyright (c) 2016, Philip Deegan.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

    * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
    * Neither the name of Philip Deegan nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _HTTPLUS_HPP_
#define _HTTPLUS_HPP_

#include "kul/log.hpp"
#include "kul/threads.hpp"

#include "httplus/http.hpp"
#include "httplus/html.hpp"
#include "httplus/yaml.hpp"

namespace httplus{

class Exception : public kul::Exception{
    public:
        Exception(const char*f, const uint16_t& l, const std::string& s) : kul::Exception(f, l, s){}
};

class App{
    private:
        httplus::yaml::Conf config;
    public:
        App() : config(httplus::yaml::Conf::CREATE()){}
        void load(kul::hash::map::S2T<std::shared_ptr<http::Server>>& http,
            kul::hash::map::S2T<std::shared_ptr<https::Server>>& https, Sites& sites){

            std::shared_ptr<http::Conf> defHttp;
            if(config.root()["http"])
                for(const YAML::Node& c : config.root()["http"]){
                    if(defHttp && !c["host"]) KEXCEPTION("Only one http allowed without 'host' parameter");
                    const std::string& port(c["port"] ? c["port"].Scalar() : "80");
                    kul::Dir d(c["root"].Scalar());
                    if(!d) KEXCEPTION("Directory does not exist: " + c["root"].Scalar());
                    kul::Dir p("pub", d);
                    if(!p && !p.mk()) KEXCEPTION("Invalid access on directory: " + d.real());
                    http::Server* ser = {0};
                    std::string home(c["home"] ? c["home"].Scalar() : "");
                    if(!c["host"]){
                        defHttp = std::make_shared<http::Conf>(c["root"].Scalar(), home);
                    }else if(sites.count(std::to_string(std::hash<std::string>()(d.real())))){
                        const Pages& pages((*sites.find(std::to_string(std::hash<std::string>()(d.real())))).second);
                        http.insert(port, std::make_shared<http::Server>(kul::Type::GET_UINT(port), pages));
                        ser = http[port].get();
                        ser->confs.insert(c["host"].Scalar(), std::make_shared<http::Conf>(c["root"].Scalar(), home));
                    }else
                        KOUT(NON) << "WARN: NO GENERATORS FOR HTTP ROOT: " << d;

                }
            for(const auto& p : http) p.second->def = defHttp;
            if(config.root()["https"])
                for(const YAML::Node& c : config.root()["https"]){
                    kul::Dir d(c["root"].Scalar());
                    if(!d) KEXCEPTION("Directory does not exist: " + c["root"].Scalar());
                    kul::Dir p("pub", d);
                    if(!p && !p.mk()) KEXCEPTION("Invalid access on directory: " + d.real());
                    kul::File crt(c["crt"].Scalar());
                    kul::File key(c["key"].Scalar());
                    if(!crt) KEXCEPTION("File does not exist: " + crt.full());
                    if(!key) KEXCEPTION("File does not exist: " + key.full());
                    https::Server* ser = {0};
                    const std::string& port(c["port"] ? c["port"].Scalar() : "443");
                    if(!sites.count(std::to_string(std::hash<std::string>()(d.real())))) {
                        KOUT(NON) << "WARN: NO GENERATORS FOR HTTPS ROOT: " << d;
                        continue;
                    }
                    const std::string hsh(std::to_string(std::hash<std::string>()(d.real())));
                    if(sites.count(hsh)){
                        const Pages& pages((*sites.find(hsh)).second);
                        https.insert(port, std::make_shared<https::Server>(kul::Type::GET_UINT(port), pages, crt, key));
                        ser = https[port].get();
                        std::string home(c["home"] ? c["home"].Scalar() : "");
                        ser->confs.insert(c["host"].Scalar(), std::make_shared<http::Conf>(c["root"].Scalar(), home));
                    }else{
                        KERR << "NO generator pages configured for directory: " << d.real();
                    }
                }
        }
};

}

#endif /* _HTTPLUS_HPP_ */<commit_msg>warning if no generators for https<commit_after>/**
Copyright (c) 2016, Philip Deegan.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

    * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
    * Neither the name of Philip Deegan nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _HTTPLUS_HPP_
#define _HTTPLUS_HPP_

#include "kul/log.hpp"
#include "kul/threads.hpp"

#include "httplus/http.hpp"
#include "httplus/html.hpp"
#include "httplus/yaml.hpp"

namespace httplus{

class Exception : public kul::Exception{
    public:
        Exception(const char*f, const uint16_t& l, const std::string& s) : kul::Exception(f, l, s){}
};

class App{
    private:
        httplus::yaml::Conf config;
    public:
        App() : config(httplus::yaml::Conf::CREATE()){}
        void load(kul::hash::map::S2T<std::shared_ptr<http::Server>>& http,
            kul::hash::map::S2T<std::shared_ptr<https::Server>>& https, Sites& sites){

            std::shared_ptr<http::Conf> defHttp;
            if(config.root()["http"])
                for(const YAML::Node& c : config.root()["http"]){
                    if(defHttp && !c["host"]) KEXCEPTION("Only one http allowed without 'host' parameter");
                    const std::string& port(c["port"] ? c["port"].Scalar() : "80");
                    kul::Dir d(c["root"].Scalar());
                    if(!d) KEXCEPTION("Directory does not exist: " + c["root"].Scalar());
                    kul::Dir p("pub", d);
                    if(!p && !p.mk()) KEXCEPTION("Invalid access on directory: " + d.real());
                    http::Server* ser = {0};
                    std::string home(c["home"] ? c["home"].Scalar() : "");
                    if(!c["host"]){
                        defHttp = std::make_shared<http::Conf>(c["root"].Scalar(), home);
                    }else if(sites.count(std::to_string(std::hash<std::string>()(d.real())))){
                        const Pages& pages((*sites.find(std::to_string(std::hash<std::string>()(d.real())))).second);
                        http.insert(port, std::make_shared<http::Server>(kul::Type::GET_UINT(port), pages));
                        ser = http[port].get();
                        ser->confs.insert(c["host"].Scalar(), std::make_shared<http::Conf>(c["root"].Scalar(), home));
                    }else
                        KOUT(NON) << "WARN: NO GENERATORS FOR HTTP ROOT: " << d;

                }
            for(const auto& p : http) p.second->def = defHttp;
            if(config.root()["https"])
                for(const YAML::Node& c : config.root()["https"]){
                    kul::Dir d(c["root"].Scalar());
                    if(!d) KEXCEPTION("Directory does not exist: " + c["root"].Scalar());
                    kul::Dir p("pub", d);
                    if(!p && !p.mk()) KEXCEPTION("Invalid access on directory: " + d.real());
                    kul::File crt(c["crt"].Scalar());
                    kul::File key(c["key"].Scalar());
                    if(!crt) KEXCEPTION("File does not exist: " + crt.full());
                    if(!key) KEXCEPTION("File does not exist: " + key.full());
                    https::Server* ser = {0};
                    const std::string& port(c["port"] ? c["port"].Scalar() : "443");
                    const std::string hsh(std::to_string(std::hash<std::string>()(d.real())));
                    if(!sites.count(hsh)) {
                        KERR << "WARN: NO GENERATORS FOR HTTPS ROOT: " << d;
                        continue;
                    }
                    const Pages& pages((*sites.find(hsh)).second);
                    https.insert(port, std::make_shared<https::Server>(kul::Type::GET_UINT(port), pages, crt, key));
                    ser = https[port].get();
                    std::string home(c["home"] ? c["home"].Scalar() : "");
                    ser->confs.insert(c["host"].Scalar(), std::make_shared<http::Conf>(c["root"].Scalar(), home));
                }
        }
};

}

#endif /* _HTTPLUS_HPP_ */<|endoftext|>


<commit_before>//-----------------------------------------------------------------------------
// Copyright (c) 2015-2016 Marcelo Fernandez
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef _MSC_VER
#include <libgen.h>
#endif
#include <math.h>

#include "oamlCommon.h"

oamlAudio::oamlAudio(oamlFileCallbacks *cbs, bool _verbose) {
	name = "";
	verbose = _verbose;
	fcbs = cbs;

	type = 0;
	bars = 0;
	volume = 1.f;

	channelCount = 0;
	samplesCount = 0;
	samplesPerSec = 0;
	samplesToEnd = 0;
	totalSamples = 0;
	filesSamples = 0;

	bpm = 0;
	beatsPerBar = 0;
	minMovementBars = 0;
	randomChance = 0;
	playOrder = 0;

	fadeIn = 0;
	fadeInSamples = 0;

	fadeOut = 0;
	fadeOutSamples = 0;
	fadeOutCount = 0;

	xfadeIn = 0;
	xfadeOut = 0;

	condId = 0;
	condType = 0;
	condValue = 0;
	condValue2 = 0;

	pickable = true;
}

oamlAudio::~oamlAudio() {
}

void oamlAudio::SetCondition(int id, int type, int value, int value2) {
	condId = id;
	condType = type;
	condValue = value;
	condValue2 = value2;
}

bool oamlAudio::TestCondition(int id, int value) {
	if (id != condId)
		return false;

	switch (condType) {
		case OAML_CONDTYPE_EQUAL:
			if (value == condValue)
				return true;
			break;

		case OAML_CONDTYPE_GREATER:
			if (value > condValue)
				return true;
			break;

		case OAML_CONDTYPE_LESS:
			if (value < condValue)
				return true;
			break;

		case OAML_CONDTYPE_RANGE:
			if (value >= condValue && value <= condValue2)
				return true;
			break;
	}

	return false;
}

unsigned int oamlAudio::GetBarsSamples(int bars) {
	if (bpm == 0)
		return 0;

	float secs = bars * (60.f / bpm) * beatsPerBar;
	return (unsigned int)(secs * samplesPerSec);
}

void oamlAudio::SetBPM(float _bpm) {
	bpm = _bpm;

	UpdateSamplesToEnd();
}

void oamlAudio::SetBeatsPerBar(int _beatsPerBar) {
	beatsPerBar = _beatsPerBar;

	UpdateSamplesToEnd();
}

void oamlAudio::SetBars(int _bars) {
	bars = _bars;

	UpdateSamplesToEnd();
}

void oamlAudio::UpdateSamplesToEnd() {
	samplesToEnd = GetBarsSamples(bars);
	if (samplesToEnd == 0) {
		samplesToEnd = totalSamples;
	}

	for (std::vector<oamlAudioFile>::iterator file=files.begin(); file<files.end(); ++file) {
		file->SetSamplesToEnd(samplesToEnd);
	}
}

oamlRC oamlAudio::Load() {
	oamlRC ret = Open();
	if (ret != OAML_OK) return ret;

	for (std::vector<oamlAudioFile>::iterator file=files.begin(); file<files.end(); ++file) {
		ret = file->Load();
		if (ret != OAML_OK)
			return ret;
	}

	return OAML_OK;
}

int oamlAudio::LoadProgress() {
	int ret = 0;
	for (std::vector<oamlAudioFile>::iterator file=files.begin(); file<files.end(); ++file) {
		int count = file->LoadProgress();
		if (count == -1)
			return -1;

		ret+= count;
	}

	return ret;
}

void oamlAudio::GetAudioFileList(std::vector<std::string>& list) {
	for (std::vector<oamlAudioFile>::iterator file=files.begin(); file<files.end(); ++file) {
		list.push_back(file->GetFilename());
	}
}

bool oamlAudio::HasAudioFile(std::string filename) {
	for (std::vector<oamlAudioFile>::iterator file=files.begin(); file<files.end(); ++file) {
		if (file->GetFilename().compare(filename) == 0) {
			return true;
		}
	}

	return false;
}

void oamlAudio::RemoveAudioFile(std::string filename) {
	for (std::vector<oamlAudioFile>::iterator file=files.begin(); file<files.end(); ++file) {
		if (file->GetFilename().compare(filename) == 0) {
			files.erase(file);
			return;
		}
	}
}

oamlAudioFile* oamlAudio::GetAudioFile(std::string filename) {
	for (std::vector<oamlAudioFile>::iterator file=files.begin(); file<files.end(); ++file) {
		if (file->GetFilename().compare(filename) == 0) {
			return &(*file);
		}
	}

	return NULL;
}

oamlRC oamlAudio::Open() {
	if (verbose) __oamlLog("%s %s\n", __FUNCTION__, GetName().c_str());

	for (std::vector<oamlAudioFile>::iterator file=files.begin(); file<files.end(); ++file) {
		oamlRC ret = file->Open();
		if (ret != OAML_OK)
			return ret;

		if (totalSamples == 0) {
			channelCount = file->GetChannels();
			samplesPerSec = file->GetSamplesPerSec();
			totalSamples = file->GetTotalSamples();
		}
	}

	UpdateSamplesToEnd();

	samplesCount = 0;
	fadeInSamples = 0;

	if (fadeOut) {
		fadeOutSamples = (unsigned int)((fadeOut / 1000.f) * samplesPerSec);
		fadeOutCount = fadeOutSamples;
	} else {
		fadeOutSamples = 0;
		fadeOutCount = 0;
	}

	return OAML_OK;
}

void oamlAudio::DoFadeIn(int msec) {
	fadeInSamples = (unsigned int)((msec / 1000.f) * samplesPerSec);
}

void oamlAudio::DoFadeOut(int msec) {
	fadeOutSamples = (unsigned int)((msec / 1000.f) * samplesPerSec);
	fadeOutCount = fadeOutSamples;
}

bool oamlAudio::HasFinished() {
	// Check if we're fading out
	if (fadeOutSamples) {
		if (fadeOutCount <= 0) {
			// Fade out finished so we're done
			return true;
		}
	}

	// Check if our samples reached our end (based off the number of bars)
	return samplesCount >= samplesToEnd;
}

bool oamlAudio::HasFinishedTail(unsigned int pos) {
	return pos >= totalSamples;
}

float oamlAudio::ReadFloat() {
	float sample = 0.f;

	for (std::vector<oamlAudioFile>::iterator file=files.begin(); file<files.end(); ++file) {
		sample+= file->ReadFloat(samplesCount);
	}

	if (fadeInSamples) {
		if (samplesCount < fadeInSamples) {
			float gain = 1.f - float(fadeInSamples - samplesCount) / float(fadeInSamples);
			sample*= gain;
		} else {
			fadeInSamples = 0;
		}
	}

	if (fadeOutSamples) {
		if (fadeOutCount > 0) {
			sample*= float(fadeOutCount) / float(fadeOutSamples);
			fadeOutCount--;
		} else {
			sample = 0.f;
		}
	}

	samplesCount++;

	return sample * volume;
}

float oamlAudio::ReadFloat(unsigned int pos) {
	float sample = 0.f;

	if (pos > totalSamples)
		return 0;

	for (std::vector<oamlAudioFile>::iterator file=files.begin(); file<files.end(); ++file) {
		sample+= file->ReadFloat(pos, true);
	}

	return sample * volume;
}

void oamlAudio::AddAudioFile(std::string filename, std::string layer, int randomChance) {
	oamlAudioFile file = oamlAudioFile(filename, fcbs, verbose);
	file.SetLayer(layer);
	file.SetRandomChance(randomChance);

	files.push_back(file);

	if (name == "") {
		size_t pos = filename.find_last_of(PATH_SEPARATOR);
		if (pos != std::string::npos) {
			name = filename.substr(pos+1);
			size_t pos = name.find_last_of('.');
			if (pos != std::string::npos) {
				name = name.substr(0, pos);
			}
		}
	}
}

void oamlAudio::ReadSamples(float *samples, int channels) {
	if (channelCount == 1) {
		// Mono audio to mono/stereo output
		float sample = ReadFloat();

		for (int i=0; i<channels; i++) {
			samples[i] = sample;
		}
	} else if (channelCount == 2) {
		if (channels == 1) {
			// Stereo audio to mono output
			float left = ReadFloat();
			float right = ReadFloat();

			samples[0] = left * 0.5f + right + 0.5f;
		} else if (channels == 2) {
			// Stereo audio to stereo output
			for (int i=0; i<channels; i++) {
				samples[i] = ReadFloat();
			}
		}
	}
}

unsigned int oamlAudio::ReadSamples(float *samples, int channels, unsigned int pos) {
	if (channelCount == 1) {
		float sample = ReadFloat(pos++);

		for (int i=0; i<channels; i++) {
			samples[i] = sample;
		}
	} else if (channelCount == 2) {
		if (channels == 1) {
			float left = ReadFloat(pos++);
			float right = ReadFloat(pos++);

			samples[0] = left * 0.5f + right + 0.5f;
		} else if (channels == 2) {
			for (int i=0; i<channels; i++) {
				samples[i] = ReadFloat(pos++);
			}
		}
	}

	return pos;
}

void oamlAudio::FreeMemory() {
	for (std::vector<oamlAudioFile>::iterator layer=files.begin(); layer<files.end(); ++layer) {
		layer->FreeMemory();
	}

	samplesCount = 0;
	samplesPerSec = 0;
	samplesToEnd = 0;
	totalSamples = 0;
	filesSamples = 0;
}

unsigned int oamlAudio::GetFilesSamples() {
	if (filesSamples == 0) {
		oamlRC ret = Open();
		if (ret != OAML_OK) return ret;

		for (std::vector<oamlAudioFile>::iterator file=files.begin(); file<files.end(); ++file) {
			filesSamples+= file->GetTotalSamples();
		}
	}

	return filesSamples;
}

void oamlAudio::ReadInfo(oamlAudioInfo *info) {
	info->name = GetName();
	info->type = GetType();
	info->volume = GetVolume();
	info->bars = GetBars();
	info->bpm = GetBPM();
	info->beatsPerBar = GetBeatsPerBar();
	info->minMovementBars = GetMinMovementBars();
	info->randomChance = GetRandomChance();
	info->playOrder = GetPlayOrder();
	info->fadeIn = GetFadeIn();
	info->fadeOut = GetFadeOut();
	info->xfadeIn = GetXFadeIn();
	info->xfadeOut = GetXFadeOut();
	info->condId = GetCondId();
	info->condType = GetCondType();
	info->condValue = GetCondValue();
	info->condValue2 = GetCondValue2();

	for (std::vector<oamlAudioFile>::iterator file=files.begin(); file<files.end(); ++file) {
		oamlAudioFileInfo afinfo;

		afinfo.filename = file->GetFilename();
		afinfo.layer = file->GetLayer();
		afinfo.randomChance = file->GetRandomChance();

		info->files.push_back(afinfo);
	}
}
<commit_msg>Further fix to fade out code<commit_after>//-----------------------------------------------------------------------------
// Copyright (c) 2015-2016 Marcelo Fernandez
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef _MSC_VER
#include <libgen.h>
#endif
#include <math.h>

#include "oamlCommon.h"

oamlAudio::oamlAudio(oamlFileCallbacks *cbs, bool _verbose) {
	name = "";
	verbose = _verbose;
	fcbs = cbs;

	type = 0;
	bars = 0;
	volume = 1.f;

	channelCount = 0;
	samplesCount = 0;
	samplesPerSec = 0;
	samplesToEnd = 0;
	totalSamples = 0;
	filesSamples = 0;

	bpm = 0;
	beatsPerBar = 0;
	minMovementBars = 0;
	randomChance = 0;
	playOrder = 0;

	fadeIn = 0;
	fadeInSamples = 0;

	fadeOut = 0;
	fadeOutSamples = 0;
	fadeOutCount = 0;

	xfadeIn = 0;
	xfadeOut = 0;

	condId = 0;
	condType = 0;
	condValue = 0;
	condValue2 = 0;

	pickable = true;
}

oamlAudio::~oamlAudio() {
}

void oamlAudio::SetCondition(int id, int type, int value, int value2) {
	condId = id;
	condType = type;
	condValue = value;
	condValue2 = value2;
}

bool oamlAudio::TestCondition(int id, int value) {
	if (id != condId)
		return false;

	switch (condType) {
		case OAML_CONDTYPE_EQUAL:
			if (value == condValue)
				return true;
			break;

		case OAML_CONDTYPE_GREATER:
			if (value > condValue)
				return true;
			break;

		case OAML_CONDTYPE_LESS:
			if (value < condValue)
				return true;
			break;

		case OAML_CONDTYPE_RANGE:
			if (value >= condValue && value <= condValue2)
				return true;
			break;
	}

	return false;
}

unsigned int oamlAudio::GetBarsSamples(int bars) {
	if (bpm == 0)
		return 0;

	float secs = bars * (60.f / bpm) * beatsPerBar;
	return (unsigned int)(secs * samplesPerSec);
}

void oamlAudio::SetBPM(float _bpm) {
	bpm = _bpm;

	UpdateSamplesToEnd();
}

void oamlAudio::SetBeatsPerBar(int _beatsPerBar) {
	beatsPerBar = _beatsPerBar;

	UpdateSamplesToEnd();
}

void oamlAudio::SetBars(int _bars) {
	bars = _bars;

	UpdateSamplesToEnd();
}

void oamlAudio::UpdateSamplesToEnd() {
	samplesToEnd = GetBarsSamples(bars);
	if (samplesToEnd == 0) {
		samplesToEnd = totalSamples;
	}

	for (std::vector<oamlAudioFile>::iterator file=files.begin(); file<files.end(); ++file) {
		file->SetSamplesToEnd(samplesToEnd);
	}
}

oamlRC oamlAudio::Load() {
	oamlRC ret = Open();
	if (ret != OAML_OK) return ret;

	for (std::vector<oamlAudioFile>::iterator file=files.begin(); file<files.end(); ++file) {
		ret = file->Load();
		if (ret != OAML_OK)
			return ret;
	}

	return OAML_OK;
}

int oamlAudio::LoadProgress() {
	int ret = 0;
	for (std::vector<oamlAudioFile>::iterator file=files.begin(); file<files.end(); ++file) {
		int count = file->LoadProgress();
		if (count == -1)
			return -1;

		ret+= count;
	}

	return ret;
}

void oamlAudio::GetAudioFileList(std::vector<std::string>& list) {
	for (std::vector<oamlAudioFile>::iterator file=files.begin(); file<files.end(); ++file) {
		list.push_back(file->GetFilename());
	}
}

bool oamlAudio::HasAudioFile(std::string filename) {
	for (std::vector<oamlAudioFile>::iterator file=files.begin(); file<files.end(); ++file) {
		if (file->GetFilename().compare(filename) == 0) {
			return true;
		}
	}

	return false;
}

void oamlAudio::RemoveAudioFile(std::string filename) {
	for (std::vector<oamlAudioFile>::iterator file=files.begin(); file<files.end(); ++file) {
		if (file->GetFilename().compare(filename) == 0) {
			files.erase(file);
			return;
		}
	}
}

oamlAudioFile* oamlAudio::GetAudioFile(std::string filename) {
	for (std::vector<oamlAudioFile>::iterator file=files.begin(); file<files.end(); ++file) {
		if (file->GetFilename().compare(filename) == 0) {
			return &(*file);
		}
	}

	return NULL;
}

oamlRC oamlAudio::Open() {
	if (verbose) __oamlLog("%s %s\n", __FUNCTION__, GetName().c_str());

	for (std::vector<oamlAudioFile>::iterator file=files.begin(); file<files.end(); ++file) {
		oamlRC ret = file->Open();
		if (ret != OAML_OK)
			return ret;

		if (totalSamples == 0) {
			channelCount = file->GetChannels();
			samplesPerSec = file->GetSamplesPerSec();
			totalSamples = file->GetTotalSamples();
		}
	}

	UpdateSamplesToEnd();

	samplesCount = 0;
	fadeInSamples = 0;
	fadeOutSamples = 0;
	fadeOutCount = 0;

	return OAML_OK;
}

void oamlAudio::DoFadeIn(int msec) {
	fadeInSamples = (unsigned int)((msec / 1000.f) * samplesPerSec);
}

void oamlAudio::DoFadeOut(int msec) {
	fadeOutSamples = (unsigned int)((msec / 1000.f) * samplesPerSec);
	fadeOutCount = fadeOutSamples;
}

bool oamlAudio::HasFinished() {
	// Check if we're fading out
	if (fadeOutSamples) {
		if (fadeOutCount <= 0) {
			// Fade out finished so we're done
			return true;
		}
	}

	// Check if our samples reached our end (based off the number of bars)
	return samplesCount >= samplesToEnd;
}

bool oamlAudio::HasFinishedTail(unsigned int pos) {
	return pos >= totalSamples;
}

float oamlAudio::ReadFloat() {
	float sample = 0.f;

	for (std::vector<oamlAudioFile>::iterator file=files.begin(); file<files.end(); ++file) {
		sample+= file->ReadFloat(samplesCount);
	}

	if (fadeInSamples) {
		if (samplesCount < fadeInSamples) {
			float gain = 1.f - float(fadeInSamples - samplesCount) / float(fadeInSamples);
			sample*= gain;
		} else {
			fadeInSamples = 0;
		}
	}

	if (fadeOutSamples) {
		if (fadeOutCount > 0) {
			sample*= float(fadeOutCount) / float(fadeOutSamples);
			fadeOutCount--;
		} else {
			sample = 0.f;
		}
	}

	samplesCount++;

	return sample * volume;
}

float oamlAudio::ReadFloat(unsigned int pos) {
	float sample = 0.f;

	if (pos > totalSamples)
		return 0;

	for (std::vector<oamlAudioFile>::iterator file=files.begin(); file<files.end(); ++file) {
		sample+= file->ReadFloat(pos, true);
	}

	return sample * volume;
}

void oamlAudio::AddAudioFile(std::string filename, std::string layer, int randomChance) {
	oamlAudioFile file = oamlAudioFile(filename, fcbs, verbose);
	file.SetLayer(layer);
	file.SetRandomChance(randomChance);

	files.push_back(file);

	if (name == "") {
		size_t pos = filename.find_last_of(PATH_SEPARATOR);
		if (pos != std::string::npos) {
			name = filename.substr(pos+1);
			size_t pos = name.find_last_of('.');
			if (pos != std::string::npos) {
				name = name.substr(0, pos);
			}
		}
	}
}

void oamlAudio::ReadSamples(float *samples, int channels) {
	if (channelCount == 1) {
		// Mono audio to mono/stereo output
		float sample = ReadFloat();

		for (int i=0; i<channels; i++) {
			samples[i] = sample;
		}
	} else if (channelCount == 2) {
		if (channels == 1) {
			// Stereo audio to mono output
			float left = ReadFloat();
			float right = ReadFloat();

			samples[0] = left * 0.5f + right + 0.5f;
		} else if (channels == 2) {
			// Stereo audio to stereo output
			for (int i=0; i<channels; i++) {
				samples[i] = ReadFloat();
			}
		}
	}
}

unsigned int oamlAudio::ReadSamples(float *samples, int channels, unsigned int pos) {
	if (channelCount == 1) {
		float sample = ReadFloat(pos++);

		for (int i=0; i<channels; i++) {
			samples[i] = sample;
		}
	} else if (channelCount == 2) {
		if (channels == 1) {
			float left = ReadFloat(pos++);
			float right = ReadFloat(pos++);

			samples[0] = left * 0.5f + right + 0.5f;
		} else if (channels == 2) {
			for (int i=0; i<channels; i++) {
				samples[i] = ReadFloat(pos++);
			}
		}
	}

	return pos;
}

void oamlAudio::FreeMemory() {
	for (std::vector<oamlAudioFile>::iterator layer=files.begin(); layer<files.end(); ++layer) {
		layer->FreeMemory();
	}

	samplesCount = 0;
	samplesPerSec = 0;
	samplesToEnd = 0;
	totalSamples = 0;
	filesSamples = 0;
}

unsigned int oamlAudio::GetFilesSamples() {
	if (filesSamples == 0) {
		oamlRC ret = Open();
		if (ret != OAML_OK) return ret;

		for (std::vector<oamlAudioFile>::iterator file=files.begin(); file<files.end(); ++file) {
			filesSamples+= file->GetTotalSamples();
		}
	}

	return filesSamples;
}

void oamlAudio::ReadInfo(oamlAudioInfo *info) {
	info->name = GetName();
	info->type = GetType();
	info->volume = GetVolume();
	info->bars = GetBars();
	info->bpm = GetBPM();
	info->beatsPerBar = GetBeatsPerBar();
	info->minMovementBars = GetMinMovementBars();
	info->randomChance = GetRandomChance();
	info->playOrder = GetPlayOrder();
	info->fadeIn = GetFadeIn();
	info->fadeOut = GetFadeOut();
	info->xfadeIn = GetXFadeIn();
	info->xfadeOut = GetXFadeOut();
	info->condId = GetCondId();
	info->condType = GetCondType();
	info->condValue = GetCondValue();
	info->condValue2 = GetCondValue2();

	for (std::vector<oamlAudioFile>::iterator file=files.begin(); file<files.end(); ++file) {
		oamlAudioFileInfo afinfo;

		afinfo.filename = file->GetFilename();
		afinfo.layer = file->GetLayer();
		afinfo.randomChance = file->GetRandomChance();

		info->files.push_back(afinfo);
	}
}
<|endoftext|>


<commit_before>#include "QDataRadioButton.h"
#include <QtGui/QMouseEvent>

QDataRadioButton::QDataRadioButton(DICOMStackInfo stack, QWidget *parent) :
	QLabel(parent),
	m_iCurrentImage((unsigned int)(-1)),
	m_stackInfo(stack)
{
		SetupInfo();
}
QDataRadioButton::QDataRadioButton(DICOMStackInfo stack, const QString &text, QWidget *parent) :
	QLabel(text, parent),
	m_iCurrentImage((unsigned int)(-1)),
	m_stackInfo(stack)
{
	SetupInfo();
}

void QDataRadioButton::leaveEvent ( QEvent * event ) {
	QLabel::leaveEvent(event);

	SetStackImage(m_stackInfo.m_Elements.size()/2);
}

void QDataRadioButton::mouseMoveEvent(QMouseEvent *event){
	QLabel::mouseMoveEvent(event);

	unsigned int i = (unsigned int)(float(event->x())/float(width())*m_stackInfo.m_Elements.size());

	SetStackImage(i);
}

void QDataRadioButton::SetStackImage(unsigned int i) {

	if (m_iCurrentImage == i) return;

	m_iCurrentImage = i;

	QImage image(m_stackInfo.m_ivSize.x, m_stackInfo.m_ivSize.y, QImage::Format_RGB888);

	void* pData = NULL;
	m_stackInfo.m_Elements[i].GetData(&pData);

	if (m_stackInfo.m_iComponentCount == 1) {
		switch (m_stackInfo.m_iAllocated) {
			case 8  :{
						unsigned int i = 0;
						unsigned char* pCharData = (unsigned char*)pData;
						for (int y = 0;y<image.height();y++)
							for (int x = 0;x<image.width();x++) {
								image.setPixel(x,y, qRgb(pCharData[i],pCharData[i],pCharData[i]));
								i++;
							}
					   } break;
			case 16 : {
						unsigned int i = 0;
						unsigned short* pShortData = (unsigned short*)pData;
						for (int y = 0;y<image.height();y++)
							for (int x = 0;x<image.width();x++) {
								unsigned char value = (unsigned char)(255.0f*float(pShortData[i])/float((m_stackInfo.m_iStored)));
								image.setPixel(x,y, qRgb(value,value,value));
								i++;
							}
					   } break;
			default  : break; // TODO: handle other bitwith data
		}
	} else {
		// TODO: handle color data
	}

	delete [] (char*)pData;

    setObjectName(QString::fromUtf8("label_2xxx"));
    setMinimumSize(QSize(150, 150));
    setPixmap(QPixmap(QString::fromUtf8("trans2d_c.png")));
    setScaledContents(true);

	//setPixmap(QPixmap::fromImage(image));
	update();
}

void QDataRadioButton::SetupInfo() {
	setMouseTracking(true);

	unsigned iElemCount = m_stackInfo.m_Elements.size();

	QString desc = tr(" %1 \n Acquired at %2 %3 using %4\n Size: %5 x %6 x %7\n")
		.arg(m_stackInfo.m_strDesc.c_str())
		.arg(m_stackInfo.m_strAcquDate.c_str())
		.arg(m_stackInfo.m_strAcquTime.c_str())
		.arg(m_stackInfo.m_strModality.c_str())
		.arg(m_stackInfo.m_ivSize.x)
		.arg(m_stackInfo.m_ivSize.y)
		.arg(m_stackInfo.m_ivSize.z*iElemCount);

	//setText(desc);

	SetStackImage(iElemCount/2);
}
<commit_msg><commit_after>#include "QDataRadioButton.h"
#include <QtGui/QMouseEvent>

QDataRadioButton::QDataRadioButton(DICOMStackInfo stack, QWidget *parent) :
	QLabel(parent),
	m_iCurrentImage((unsigned int)(-1)),
	m_stackInfo(stack)
{
		SetupInfo();
}
QDataRadioButton::QDataRadioButton(DICOMStackInfo stack, const QString &text, QWidget *parent) :
	QLabel(text, parent),
	m_iCurrentImage((unsigned int)(-1)),
	m_stackInfo(stack)
{
	SetupInfo();
}

void QDataRadioButton::leaveEvent ( QEvent * event ) {
	QLabel::leaveEvent(event);

	SetStackImage(m_stackInfo.m_Elements.size()/2);
}

void QDataRadioButton::mouseMoveEvent(QMouseEvent *event){
	QLabel::mouseMoveEvent(event);

	unsigned int i = (unsigned int)(float(event->x())/float(width())*m_stackInfo.m_Elements.size());

	SetStackImage(i);
}

void QDataRadioButton::SetStackImage(unsigned int i) {

	if (m_iCurrentImage == i) return;

	m_iCurrentImage = i;

	QImage image(m_stackInfo.m_ivSize.x, m_stackInfo.m_ivSize.y, QImage::Format_RGB888);

	void* pData = NULL;
	m_stackInfo.m_Elements[i].GetData(&pData);

	if (m_stackInfo.m_iComponentCount == 1) {
		switch (m_stackInfo.m_iAllocated) {
			case 8  :{
						unsigned int i = 0;
						unsigned char* pCharData = (unsigned char*)pData;
						for (int y = 0;y<image.height();y++)
							for (int x = 0;x<image.width();x++) {
								image.setPixel(x,y, qRgb(pCharData[i],pCharData[i],pCharData[i]));
								i++;
							}
					   } break;
			case 16 : {
						unsigned int i = 0;
						unsigned short* pShortData = (unsigned short*)pData;
						for (int y = 0;y<image.height();y++)
							for (int x = 0;x<image.width();x++) {
								unsigned char value = (unsigned char)(255.0f*float(pShortData[i])/float((m_stackInfo.m_iStored)));
								image.setPixel(x,y, qRgb(value,value,value));
								i++;
							}
					   } break;
			default  : break; // TODO: handle other bitwith data
		}
	} else {
		// TODO: handle color data
	}

	delete [] (char*)pData;

    setObjectName(QString::fromUtf8("label_2xxx"));
    setMinimumSize(QSize(150, 150));
	setPixmap(QPixmap::fromImage(image));
    setScaledContents(true);

	update();
}

void QDataRadioButton::SetupInfo() {
	setMouseTracking(true);

	unsigned iElemCount = m_stackInfo.m_Elements.size();

	QString desc = tr(" %1 \n Acquired at %2 %3 using %4\n Size: %5 x %6 x %7\n")
		.arg(m_stackInfo.m_strDesc.c_str())
		.arg(m_stackInfo.m_strAcquDate.c_str())
		.arg(m_stackInfo.m_strAcquTime.c_str())
		.arg(m_stackInfo.m_strModality.c_str())
		.arg(m_stackInfo.m_ivSize.x)
		.arg(m_stackInfo.m_ivSize.y)
		.arg(m_stackInfo.m_ivSize.z*iElemCount);

	//setText(desc);

	SetStackImage(iElemCount/2);
}
<|endoftext|>