针对每一种后缀名Nuke都提供了对应的模块。为了决定用哪个版本的reader或writer模块,Nuke会先解析文件后缀名再以此为依据调用相关模块。

以JPG为例:

该文件格式有两种后缀名:.jpg和.jpeg。实际上两种后缀名用同一个模块来解决即可。Nuke中用tcl脚本来解决这个问题。Nuke文件路径中有这样一个文件:jpegReader.tcl,内容如下:

#jpegReader.tcl
load jpgReader

当Nuke主程序解析后缀名为.jpeg的时候就会调用jpegReader.tcl脚本。该脚本会将调用指向jpgReader模块。通过这种方式就解决了一种图像格式有多种后缀名的问题。

Nuke中提供了对应大部分图像格式的reader和writer模块,例如:dpxWriter,dpxReader,exifReader,exifWriter。

分别针对对应的图像格式。

NDK文档中提供了标准的一个Reader基础模板如下:

class MyReader : DD::Image::Reader
{
static const Description d;
...
}; static Reader* build( Read* r, int fd, const unsigned char* b, int n )
{
return new MyReader( r, fd, b, n );
} static bool test( int fd, const unsigned char* block, int n )
{
return ( block[0] == MY_MAGIC_BYTE );
} const Reader::Description MyReader::d( "myFile\0", "my file format", build, test );

首先定义了一个继承Reader的子类:MyReader,继而定义其中的build及test、Description函数。

Description函数将通过build及test函数来控制和估计是否MyReader类适用于操作当前的图像格式。

一般来说,Reader实例通过后缀名来寻找对应的读取器,一旦找到了特定的图像格式,就是启动test函数去确定读取器与当前格式是否匹配。

在这种情况下,MY_MAGIC_BYTE会被当做内存中第一个元素来识别。为了防止错误的后缀名图像格式(比如dpx格式的文件后缀名却是.jpg),Nuke还会再次测试tester方法,来告诉用户,testing可以决定文件类型是可读的,同时避免了相同的文件后缀冲突。

和使用tcl语言的的方法一样,多种文件后缀也可以在description中被定义。案例如下:

const Reader::Description MyReader::d( "myFile\0someOtherFile", "my file format", build, test );

这样的话Reader就可以适用于.myFile格式和.someOtherFile格式了。

这个Reader结构可以通过DD::Image::Reader::set_info()l来设置IO访问的区域。这会是一个快速的处理过程。复杂的读取,解码,缓存可以通过DD::Image::Reader::open()来解决。

最后一个需要用户自己定义来创造基本的读取机制的方法是DD::Image::Reader::engine()。下面这个案例会显示Nuke自己的图像处理过程:

void MyReader::engine( int y, int x, int r, ChannelMask mask, Row& row )
{
row.range( 0, width() ); for( int z = 0; z < 4; z++ ) {
// A user implemented read function
custom_read_channel( y, z, row.writable( z ) );
}
}

这个实例会在开始时设置画面的宽度,然后读取每一个通道的数据到row中。

row就是一个数据缓冲机制。

还有一些其他的方法:

以下的方法都是可选的,不必每一个都定义。他们提供了一些额外的功能和信息给Reader类。

void DD::Image::Reader::prefetchMetaData()

这个方法可以用来获取特定帧的metadata(元数据)。

const MetaData::Bundle& DD::Image::Reader::fetchMetaData(const char* key)

这个方法可以用来获取metadata(元数据)。

bool DD::Image::Reader::supports_stereo() const

这是一个flag,决定当前类是否支持立体双视角的读取。

bool DD::Image::Reader::fileStereo() const

这是一个flag,表明当前文件是否为立体素材。

bool DD::Image::Reader::videosequence() const

这是一个flag,表示当前文件是否是视频素材,即mov。

关于FileReader基类:

FileReader是一个继承自Reader的类,但它总表现的像是一个基类。它需要实例化的函数方法同Reader一样。然后FileReader这个类之所有有趣,主要还在于它有一些新加的超越Reader的特性。

当用户直接继承Reader类来创建自己的reader类的时候你必须也实例化文件操作函数。FileReader会提供方法直接进入或者操作文件数据,基于此,对于大部分实例,FileReader是一种非常合适的解决方案。

要使用更多的特性,只需要向下面一样自定义一个类继承DD::Image::FileReader即可。

class MyReader : public DD::Image::FileReader
{
...
};

 FileReader的扩展特性有以下这些:

int DD::Image::FileReader::lock(FILE_OFFSET offset, int min_length, int length)
int DD::Image::FileReader::lock(FILE_OFFSET offset, int l)
int DD::Image::FileReader::lock(FILE_OFFSET offset, unsigned int l)

以上三个方法用于锁定给定参数上的数据。

const unsigned char& DD::Image::FileReader::byte( FILE_OFFSET n ) const
const unsigned char* DD::Image::FileReader::at( FILE_OFFSET n ) const

以上两个方法用于进入给定offset上的字节。

void DD::Image::FileReader::unlock()

解锁之前锁住的内存。

int DD::Image::FileReader::read(void* p, FILE_OFFSET offset, int min_, int max_)
int DD::Image::FileReader::read(void* p, FILE_OFFSET offset, int l)
int DD::Image::FileReader::read(void* p, File_OFFSET offset, unsigned int l)

直接读取存入内存的文件。

Reader的KNOBS机制:

在reader类中添加knobs需要额外的步骤,因为Reader类并不同于Ops。有特定的对象可以跟Reader一起被初始化和注册来赋予Reader类似常规Op创建Knobs的能力。有两个主要步骤如下:

1.继承一个DD::Image::ReaderFormat类。用这个ReaderFormat类就可以将knobs()及knob_changed()接口实例化了。

2.用你自己的reader类创建一个新的正确类型的对象,确保正确的reader format被初始化了。

代码如下:

class MyFileFormat : public DD::Image::ReaderFormat
{
// implementation of the knobs call
void knobs(Knob_Callback c)
} class MyReader : public DD::Image::FileReader
{
static const Description d;
} static Reader* build( Read* r, int fd, const unsigned char* b, int n )
{
return new MyReader( r, fd, b, n );
} static bool test( int fd, const unsigned char* block, int n )
{
return ( block[] == MY_MAGIC_BYTE );
} static ReaderFormat* buildformat(Read* iop)
{
return new MyFileFormat();
} const Reader::Description MyReader::d( "myFile\0", "my file format", build, test, buildFormat );

第一个MyFileFormat类是一个包装器,用来包含knobs类。第二个类即为MyReader,继承自FileReader,在类中定义了description。第三个代码块是对build函数的定义,第四个代码块是对test函数的定义,第五个是对buildformat函数的定义。最后定义Description函数,该函数是对MyReader类的一个说明,参数与Reader基类比较多了一个buildFormat。这也是FileReader基类的一个特点,有扩展属性,可以很方便的添加新的属性功能。

案例中就通过buildFormat函数新添加了knobs对象。

Reading MetaData:

Metadata可以再解码的时候使用相同的模式去读取。DD::Image::fetchMetaData( const char* key )实例化之后可以返回DD::Image::MetaData::Bundle的对象。代码如下:

class MyReader : public DD::Image::FileReader
{
...
DD::Image::MetaData::Bundle& fetchMetaData( const char* key )
{
return _metaData;
} DD::Image::MetaData::Bundle _metaData;
}

在这个案例中,_metaData信息可以在requested的时候获得。reader对象构建的时候这个metadata已经提前建好了。可以直接调用。

Testing with Tester:

正如之前提到的,当读取一个文件的时候,基于对应于文件格式的已注册的可用扩展名,Nuke会判断用哪一个reader来读取。这下面的代码是一个简单的测试模块来检查第一个字节来确保匹配MY_MAGIC_BYTE宏。这当然是一个简单的例子简单表示一下怎样设置该函数,真实的实例会检查更多更复杂的模式来确保匹配。(这个函数似乎是对指令地址逐一测试用的)test代码块如下:

#define MY_MAGIC_BYTE 0x000000001
static bool test( int fd, const unsigned char* block, int n )
{
return ( block[] == MY_MAGIC_BYTE );
}

第二个用来防止出现错误文件后缀的机制如下:

typedef bool (*Tester)(int fd, const unsigned char* buf, int bufsize);
DD::Image::Reader::(Tester* )( int fd,const unsigned char* block,int n )

Tester函数返回值是指针,执行结果是bool值,当指针非零时,表示一个Unix文件被用来存储图像了。这种情况下,Reader类就会打开这个Unix文件调用该函数。如果函数执行结果是True,那么对应reader就会被调用。当然该机制也允许所有的reader类对一个未知文件类型进行投票来确定谁来读取这个文件。

如果返回值是Null,那么图像就会以空值的形式传递给reader机制。

Working Metadata:

metadata在nuke中是通过DD::Image::Metadata::Bundle对象来解决的。这个抽象的对象提供了了所有需要读写的功能。

在使用metadata的过程中有两件事需要注意,metadata可以被分成两种机制:

1:nuke识别的默认的metadata机制。比如时码(DD::Image::MetaData::TIMECODE)这个关键字是用来存储特定值的。所以nuke读写时码的时候,使用这个关键字的。

2:自定义的metadata机制。如果你想用其他名称来代替timecode这个关键字,Nuke内部也会认可这种key-value值对的方式。

NDK学习笔记(五)Reader机制的更多相关文章

  1. C#可扩展编程之MEF学习笔记(五):MEF高级进阶

    好久没有写博客了,今天抽空继续写MEF系列的文章.有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后. 前面四篇讲了MEF的基础知识,学完了前四篇,MEF中比较常用 ...

  2. (转)Qt Model/View 学习笔记 (五)——View 类

    Qt Model/View 学习笔记 (五) View 类 概念 在model/view架构中,view从model中获得数据项然后显示给用户.数据显示的方式不必与model提供的表示方式相同,可以与 ...

  3. Java IO学习笔记五:BIO到NIO

    作者:Grey 原文地址: Java IO学习笔记五:BIO到NIO 准备环境 准备一个CentOS7的Linux实例: 实例的IP: 192.168.205.138 我们这次实验的目的就是直观感受一 ...

  4. java之jvm学习笔记五(实践写自己的类装载器)

    java之jvm学习笔记五(实践写自己的类装载器) 课程源码:http://download.csdn.net/detail/yfqnihao/4866501 前面第三和第四节我们一直在强调一句话,类 ...

  5. java学习笔记09--反射机制

    java学习笔记09--反射机制 什么是反射: 反射是java语言的一个特性,它允许程序在运行时来进行自我检查并且对内部的成员进行操作.例如它允许一个java的类获取他所有的成员变量和方法并且显示出来 ...

  6. Learning ROS for Robotics Programming Second Edition学习笔记(五) indigo computer vision

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...

  7. Storm学习笔记 - 消息容错机制

    Storm学习笔记 - 消息容错机制 文章来自「随笔」 http://jsynk.cn/blog/articles/153.html 1. Storm消息容错机制概念 一个提供了可靠的处理机制的spo ...

  8. Typescript 学习笔记五:类

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  9. ES6学习笔记<五> Module的操作——import、export、as

    import export 这两个家伙对应的就是es6自己的 module功能. 我们之前写的Javascript一直都没有模块化的体系,无法将一个庞大的js工程拆分成一个个功能相对独立但相互依赖的小 ...

随机推荐

  1. 【转载】 PyTorch学习之六个学习率调整策略

    原文地址: https://blog.csdn.net/shanglianlm/article/details/85143614 ----------------------------------- ...

  2. Quorum算法

    分布式系统中,一般保存多个数据副本,明显可以提高系统可靠性.并且存储这些数据副本的节点,不仅做容灾用,也可以提供服务,作负载均衡. 这里就涉及到一个数据一致性的问题,也就是各副本间要进行同步,来保持最 ...

  3. Django之模版层-语法:标签 {% %}

    标签 {% %} for循环以及for..empty.. <h4>for标签</h4> {% for i in lis %} <p>{{ i }}</p> ...

  4. angular的点击添加

    首先是在js里面我们可以用clone来点击添加一些东西比如列表或者其他的div之类的,但是在angular里面怎么实现点击添加呢? 类似这种: 这样就尴尬了,最少我这样的菜鸟是不知道怎么去写的,网上好 ...

  5. ZOJ4062 Plants vs. Zombies(二分+贪心)

    题目链接:传送门 题目大意: 有n棵植物依次放在1-n,机器人从0出发浇水,每棵植物被浇水时di += ai,求浇m次水后min{di|1 ≤ i ≤ n}的最大值.(浇水时必须往左或往右走一步,落脚 ...

  6. Windows下安装Python模块时环境配置

    “Win +R”打开cmd终端,如果直接在里面使用pip命令的时候,要么出现“syntax invalid”,要么出现: 'pip' is not recognized as an internal ...

  7. 【JVM】java对象

    一.对象内存布局 对象在内存中存储可分为3块区域:对象头,实例数据,对齐填充 1.对象头 对象头包含两部分内容. 第一部分:存储对象自身的运行时数据,哈希吗(hashCode),GC分代年龄,锁状态标 ...

  8. 【shell编程】之基础知识-常用命令

    一.Shell echo命令 Shell 的 echo 指令与 PHP 的 echo 指令类似,都是用于字符串的输出.命令格式: echo string 您可以使用echo实现更复杂的输出格式控制. ...

  9. 刚开始学java和刚去工作的时候,1.path路径 2.classpath路径 还有JAVA_HOME相当于/dgs这个路径

    把里面bin文件夹下面的可执行文件都配置到path路径下了,以后只要在Dos窗口输入命令就可以运行 无论是在dos窗口下还是在eclispe中只需要配置这个path变量,不需要配置classpath ...

  10. Coding kata: get the top two teams in one group

    In this week, we did a coding kata, the subject is to select the top two teams of football group mat ...