#include <iostream>
#include <fstream>
#include <cassert>
#include <algorithm>
#include <cmath>
#include <ctime>
#include "ofxCore.h"
#include "ofxImageEffect.h"
#include "ofxPixels.h"
#include "ofxhBinary.h"
#include "ofxhPropertySuite.h"
#include "ofxhClip.h"
#include "ofxhParam.h"
#include "ofxhMemory.h"
#include "ofxhImageEffect.h"
#include "ofxhPluginAPICache.h"
#include "ofxhPluginCache.h"
#include "ofxhHost.h"
#include "ofxhImageEffectAPI.h"
#include "hostDemoHostDescriptor.h"
#include "hostDemoEffectInstance.h"
#include "hostDemoClipInstance.h"
namespace MyHost {
const double kPalPixelAspect = double(768)/double(720);
const int kPalSizeXPixels = 720;
const int kPalSizeYPixels = 576;
const OfxRectI kPalRegionPixels = {0, 0, kPalSizeXPixels, kPalSizeYPixels};
const char digits[11][5][3] = {
{ {0,1,0},
{1,0,1},
{1,0,1},
{1,0,1},
{0,1,0} },
{ {0,1,0},
{1,1,0},
{0,1,0},
{0,1,0},
{0,1,0} },
{ {0,1,0},
{1,0,1},
{0,0,1},
{0,1,0},
{1,1,1} },
{ {1,1,0},
{0,0,1},
{0,1,1},
{0,0,1},
{1,1,0} },
{ {0,1,0},
{1,0,0},
{1,0,1},
{1,1,1},
{0,0,1} },
{ {1,1,1},
{1,0,0},
{1,1,0},
{0,0,1},
{1,1,0} },
{ {0,1,1},
{1,0,0},
{1,1,0},
{1,0,1},
{0,1,0} },
{ {1,1,1},
{0,0,1},
{0,1,0},
{0,1,1},
{0,1,0} },
{ {0,1,0},
{1,0,1},
{0,1,0},
{1,0,1},
{0,1,0} },
{ {0,1,0},
{1,0,1},
{0,1,1},
{0,0,1},
{1,1,0} },
{ {0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,1,0} }
};
static void drawDigit(OfxRGBAColourB* data, int width, int height, int d, int x, int y , int scale, OfxRGBAColourB color) {
assert(0 <= x && x+3*scale < width);
assert(0 <= y && y+5*scale < height);
for (int j = 0; j < 5; ++j) {
for (int i = 0; i < 3; ++i) {
if (digits[d][j][i]) {
for (int jj = 0; jj < scale; ++jj) {
for (int ii = 0; ii < scale; ++ii) {
int x1 = x + i*scale + ii;
int y1 = y + j*scale + jj;
data[x1+y1*width] = color;
}
}
}
}
}
}
MyImage::MyImage(MyClipInstance &clip, OfxTime time, int view)
: OFX::Host::ImageEffect::Image(clip) , _data(NULL)
{
_data = new OfxRGBAColourB[kPalSizeXPixels * kPalSizeYPixels] ;
int fillValue = (int)(floor(255.0 * (time/OFXHOSTDEMOCLIPLENGTH))) & 0xff;
OfxRGBAColourB color;
color.r = color.g = color.b = fillValue;
color.a = 255;
std::fill(_data, _data + kPalSizeXPixels * kPalSizeYPixels, color);
const int scale = 5;
const int charwidth = 4*scale;
color.r = color.g = color.b = 255-fillValue;
int xx = 50;
int yy = 50;
int d;
d = (int(time)/10)%10;
drawDigit(_data, kPalSizeXPixels, kPalSizeYPixels, d, xx, yy, scale, color);
xx += charwidth;
d = int(time)%10;
drawDigit(_data, kPalSizeXPixels, kPalSizeYPixels, d, xx, yy, scale, color);
xx += charwidth;
d = 10;
drawDigit(_data, kPalSizeXPixels, kPalSizeYPixels, d, xx, yy, scale, color);
xx += charwidth;
d = int(time*10)%10;
drawDigit(_data, kPalSizeXPixels, kPalSizeYPixels, d, xx, yy, scale, color);
xx = 50;
yy += 8*scale;
d = int(view)%10;
drawDigit(_data, kPalSizeXPixels, kPalSizeYPixels, d, xx, yy, scale, color);
setDoubleProperty(kOfxImageEffectPropRenderScale, 1.0, 0);
setDoubleProperty(kOfxImageEffectPropRenderScale, 1.0, 1);
setPointerProperty(kOfxImagePropData,_data);
setIntProperty(kOfxImagePropBounds, kPalRegionPixels.x1, 0);
setIntProperty(kOfxImagePropBounds, kPalRegionPixels.y1, 1);
setIntProperty(kOfxImagePropBounds, kPalRegionPixels.x2, 2);
setIntProperty(kOfxImagePropBounds, kPalRegionPixels.y2, 3);
setIntProperty(kOfxImagePropRegionOfDefinition, kPalRegionPixels.x1, 0);
setIntProperty(kOfxImagePropRegionOfDefinition, kPalRegionPixels.y1, 1);
setIntProperty(kOfxImagePropRegionOfDefinition, kPalRegionPixels.x2, 2);
setIntProperty(kOfxImagePropRegionOfDefinition, kPalRegionPixels.y2, 3);
setIntProperty(kOfxImagePropRowBytes, kPalSizeXPixels * sizeof(OfxRGBAColourB));
}
OfxRGBAColourB* MyImage::pixel(int x, int y) const
{
OfxRectI bounds = getBounds();
if ((x >= bounds.x1) && ( x< bounds.x2) && ( y >= bounds.y1) && ( y < bounds.y2) )
{
int rowBytes = getIntProperty(kOfxImagePropRowBytes);
int offset = (y - bounds.y1) * rowBytes + (x - bounds.x1) * sizeof(OfxRGBAColourB);
return reinterpret_cast<OfxRGBAColourB*>(&(reinterpret_cast<char*>(_data)[offset]));
}
return 0;
}
MyImage::~MyImage()
{
delete _data;
}
MyClipInstance::MyClipInstance(MyEffectInstance* effect, OFX::Host::ImageEffect::ClipDescriptor *desc)
: OFX::Host::ImageEffect::ClipInstance(effect, *desc)
, _effect(effect)
, _name(desc->getName())
, _outputImage(NULL)
{
}
MyClipInstance::~MyClipInstance()
{
if(_outputImage)
_outputImage->releaseReference();
}
const std::string &MyClipInstance::getUnmappedBitDepth() const
{
static const std::string v(kOfxBitDepthByte);
return v;
}
const std::string &MyClipInstance::getUnmappedComponents() const
{
static const std::string v(kOfxImageComponentRGBA);
return v;
}
const std::string &MyClipInstance::getPremult() const
{
static const std::string v(kOfxImageUnPreMultiplied);
return v;
}
double MyClipInstance::getAspectRatio() const
{
return kPalPixelAspect;
}
double MyClipInstance::getFrameRate() const
{
return 25.0;
}
void MyClipInstance::getFrameRange(double &startFrame, double &endFrame) const
{
startFrame = 0;
endFrame = 25;
}
const std::string &MyClipInstance::getFieldOrder() const
{
static const std::string v(kOfxImageFieldNone);
return v;
}
bool MyClipInstance::getConnected() const
{
return true;
}
double MyClipInstance::getUnmappedFrameRate() const
{
return 25;
}
void MyClipInstance::getUnmappedFrameRange(double &unmappedStartFrame, double &unmappedEndFrame) const
{
unmappedStartFrame = 0;
unmappedEndFrame = 25;
}
bool MyClipInstance::getContinuousSamples() const
{
return false;
}
OfxRectD MyClipInstance::getRegionOfDefinition(OfxTime time) const
{
OfxRectD v;
v.x1 = v.y1 = 0;
v.x2 = 768;
v.y2 = 576;
return v;
}
OFX::Host::ImageEffect::Image* MyClipInstance::getImage(OfxTime time, const OfxRectD *optionalBounds)
{
if(_name == "Output") {
if(!_outputImage) {
_outputImage = new MyImage(*this, 0);
}
_outputImage->addReference();
return _outputImage;
}
else {
MyImage *image = new MyImage(*this, time);
return image;
}
}
}