- 浏览: 576837 次
- 性别:
- 来自: 广州
文章分类
- 全部博客 (338)
- 已过时文章(留念用) (39)
- Android学习笔记 (30)
- Android开发指引自译 (100)
- Android NDK文档自译 (23)
- Android设计指引自译 (2)
- xp(ペケピー)&linux(理奈、铃)酱~ (4)
- ui酱&歌词自译~ (9)
- lua酱~ (9)
- 自我反省 (1)
- 羽game计划 (1)
- XSL酱 (2)
- java酱 (3)
- 设计的领悟 (58)
- 涂鸦作品(pixiv) (1)
- ruby酱 (2)
- Objective-C编程语言自译 (2)
- Android开发月报 (6)
- objc酱 (2)
- photoshop (3)
- js酱 (6)
- cpp酱 (8)
- antlr酱 (7)
- Lua 5.1参考手册自译 (11)
- 收藏品 (3)
- 待宵草计划 (4)
- 体验版截图 (1)
最新评论
-
naruto60:
太给力了!!!!我这网打不开Intel官网,多亏楼主贴了连接, ...
使用HAXM加速的Android x86模拟器(和一些问题) -
yangyile2011:
谢谢博主,翻译得很好哦
【翻译】(4)片段 -
ggwang:
牙痛的彼岸:痹!
牙痛的彼岸 -
ggwang:
总结得很简练清晰啊,学习了!
ANTLR学习笔记一:概念理解 -
leisurelife1990:
mk sdd
用git下载Android自带app的源代码
Run-Time Specified Images and Image Views
运行时特定图片和图片视图
So far we have created a generic function that computes the image gradient of a templated image view. Sometimes, however, the properties of an image view, such as its color space and channel depth, may not be available at compile time. GIL's dynamic_image extension allows for working with GIL constructs that are specified at run time, also called variants. GIL provides models of a run-time instantiated image, any_image, and a run-time instantiated image view, any_image_view. The mechanisms are in place to create other variants, such as any_pixel, any_pixel_iterator, etc. Most of GIL's algorithms and all of the view transformation functions also work with run-time instantiated image views and binary algorithms, such as copy_pixels can have either or both arguments be variants.
到现在为止,我们已经创建一个泛型函数计算模板图片视图的图片梯度。然而有时,图片视图的属性,诸如它的颜色空间和通道深度,可能在编译期不可用。GIL的dynamic_image扩展允许处理运行期特定的GIL构造类型,或称为variants(注:变数类型)。GIL提供运行期实例化图片any_image和运行期实例化图片视图any_image_view的模型。这里还有其它建立变数类型的机制,诸如any_pixel、any_pixel_iterator等等。大多数GIL算法和所有视图函数都可以工作在运行期实例化图片视图,而二元算法,诸如copy_pixels可以把变数类型作为一个或全部参数。
Lets make our x_luminosity_gradient algorithm take a variant image view. For simplicity, let's assume that only the source view can be a variant. (As an example of using multiple variants, see GIL's image view algorithm overloads taking multiple variants.)
让我们制造我们自己的可传入变数类型的x_luminosity_gradient算法。简单起见,让我们假设只有源视图是变数的。(作为使用多变数的示例,参考GIL图片视图算法的带多个变数的重载)
First, we need to make a function object that contains the templated destination view and has an application operator taking a templated source view:
首先,我们需要制造一个函数对象(注:即functor,仿函数),包含模板化目标视图和一个带模板化源视图参数的应用操作符(注:即operator()):
#include <boost/gil/extension/dynamic_image/dynamic_image_all.hpp>
template <typename DstView>
struct x_gradient_obj {
typedef void result_type; // required typedef //需要typedef
const DstView& _dst;
x_gradient_obj(const DstView& dst) : _dst(dst) {}
template <typename SrcView>
void operator()(const SrcView& src) const { x_luminosity_gradient(src, _dst); }
};
The second step is to provide an overload of x_luminosity_gradient that takes image view variant and calls GIL's apply_operation passing it the function object:
第二步是提供一个x_luminosity_gradient的重载,以图片视图变数为参数,调用GIL的apply_operation向它传递函数对象:
template <typename SrcViews, typename DstView>
void x_luminosity_gradient(const any_image_view<SrcViews>& src, const DstView& dst) {
apply_operation(src, x_gradient_obj<DstView>(dst));
}
any_image_view<SrcViews> is the image view variant. It is templated over SrcViews, an enumeration of all possible view types the variant can take. src contains inside an index of the currently instantiated type, as well as a block of memory containing the instance. apply_operation goes through a switch statement over the index, each case of which casts the memory to the correct view type and invokes the function object with it. Invoking an algorithm on a variant has the overhead of one switch statement. Algorithms that perform an operation for each pixel in an image view have practically no performance degradation when used with a variant.
any_image_view<SrcViews>是一个图片视图变数。它的模板参数SrcViews是变数可以携带的所有可能的视图类型的一个枚举。src之中包含一个当前实例化类型,还有一个承载实例的内存块。apply_operation流经一个针对索引的switch语句,它的每个case把内存转换成正确的视图类型并且用它调用函数对象。在变数上调用一个算法有一个switch语句的开销。当使用一个变数时,对图片视图的每个像素执行一个操作的算法实际上不会有性能下降。
Here is how we can construct a variant and invoke the algorithm:
这里展示我们如何构造一个变数并且调用算法:
#include <boost/mpl/vector.hpp>
#include <boost/gil/extension/io/jpeg_dynamic_io.hpp>
typedef mpl::vector<gray8_image_t, gray16_image_t, rgb8_image_t, rgb16_image_t> my_img_types;
any_image<my_img_types> runtime_image;
jpeg_read_image("input.jpg", runtime_image);
gray8s_image_t gradient(runtime_image.dimensions());
x_luminosity_gradient(const_view(runtime_image), view(gradient));
jpeg_write_view("x_gradient.jpg", color_converted_view<gray8_pixel_t>(const_view(gradient)));
In this example, we create an image variant that could be 8-bit or 16-bit RGB or grayscale image. We then use GIL's I/O extension to load the image from file in its native color space and channel depth. If none of the allowed image types matches the image on disk, an exception will be thrown. We then construct a 8 bit signed (i.e. char) image to store the gradient and invoke x_gradient on it. Finally we save the result into another file. We save the view converted to 8-bit unsigned, because JPEG I/O does not support signed char.
在这个例子中,我们创建一个图片变数,它可能是8位或16位RGB或灰度图。然后我们使用GIL的I/O扩展从文件中以原生的颜色空间和通道深度加载图片。如果硬盘的图片没有允许的图片类型可匹配,将抛出一个异常。然后我们构造一个8位有符号(即char)图片以保存梯度并在它上面调用x_gradient。最后我们把结果保存进另一个文件。我们保存转为8位无符号的视图因为JPEG I/O不支持有符号char。
Note how free functions and methods such as jpeg_read_image, dimensions, view and const_view work on both templated and variant types. For templated images view(img) returns a templated view, whereas for image variants it returns a view variant. For example, the return type of view(runtime_image) is any_image_view<Views> where Views enumerates four views corresponding to the four image types. const_view(runtime_image) returns a any_image_view of the four read-only view types, etc.
注意自由函数和方法诸如jpeg_read_image,dimensions,view和const_view是如何工作在模板和变数类型上的。
对于模板化图片view(img)返回一个模板化的view,而对于图片变数则返回视图变数。
例如,view(runtime_image)的返回类型是any_image_view<Views>,其中Views枚举了对应4种图片类型的四种视图。 const_view(runtime_image)返回4种只读视图的any_image_view,等等。
A warning about using variants: instantiating an algorithm with a variant effectively instantiates it with every possible type the variant can take. For binary algorithms, the algorithm is instantiated with every possible combination of the two input types! This can take a toll on both the compile time and the executable size.
关于使用变数的警告:用一个变数实例化一个算法会有效地用变数能携带的每个可能的类型来实例化它。对于二元算法,算法用两个输入类型的每个可能组合来实例化!这可能花费编译时间和增大可执行文件的大小。
Conclusion
结论
This tutorial provides a glimpse at the challenges associated with writing generic and efficient image processing algorithms in GIL. We have taken a simple algorithm and shown how to make it work with image representations that vary in bit depth, color space, ordering of the channels, and planar/interleaved structure. We have demonstrated that the algorithm can work with fully abstracted virtual images, and even images whose type is specified at run time. The associated video presentation also demonstrates that even for complex scenarios the generated assembly is comparable to that of a C version of the algorithm, hand-written for the specific image types.
这个教程提供关于使用GIL书写泛型和高效图片处理算法的难题的一瞥。我们已经得到一个简单的算法并展示如何使它处理不同位深、颜色空间、通道顺序、以及平面/间隔结构的图片表现。我们已经演示了可以工作于抽象虚拟图片,甚至运行期特定类型图片的算法。相关视频也会展示一些的演示,针对复杂场景生成的组合,可以与C版本和对特定图片类型而手写的算法媲美。
Yet, even for such a simple algorithm, we are far from making a fully generic and optimized code. In particular, the presented algorithms work on homogeneous images, i.e. images whose pixels have channels that are all of the same type. There are examples of images, such as a packed 565 RGB format, which contain channels of different types. While GIL provides concepts and algorithms operating on heterogeneous pixels, we leave the task of extending x_gradient as an exercise for the reader. Second, after computing the value of the gradient we are simply casting it to the destination channel type. This may not always be the desired operation. For example, if the source channel is a float with range [0..1] and the destination is unsigned char, casting the half-difference to unsigned char will result in either 0 or 1. Instead, what we might want to do is scale the result into the range of the destination channel. GIL's channel-level algorithms might be useful in such cases. For example, channel_convert converts between channels by linearly scaling the source channel value into the range of the destination channel.
但是,即使只是简单的算法,我们还无法写出完全泛型和优化的代码。特别地,给出的算法只能工作在同质图片,即像素拥有同类型通道的图片。这种图片,例如一个打包的565 RGB格式,包含不同类型的通道。然而GIL提供概念和算法操作混杂像素,我们把扩展x_gradient的任务作为练习留给读者。其次,在计算梯度值之后,我们简单地把它转换成目标通道类型,这可能不总是理想的操作。例如,如果源通道时一个区间为[0..1]的浮点数,而目标是一个unsigned char,把半差分转换为unsigned char的结果将是0或1。取而代之,我们可能想做的是把结果缩放进目标通道的区间。GIL的通道级算法可能在这些情况下有用。例如,channel_convert在通道间转换,把源通道值线性缩放到目标通道中。
There is a lot to be done in improving the performance as well. Channel-level operations, such as the half-difference, could be abstracted out into atomic channel-level algorithms and performance overloads could be provided for concrete channel types. Processor-specific operations could be used, for example, to perform the operation over an entire row of pixels simultaneously, or the data could be prefetched. All of these optimizations can be realized as performance specializations of the generic algorithm. Finally, compilers, while getting better over time, are still failing to fully optimize generic code in some cases, such as failing to inline some functions or put some variables into registers. If performance is an issue, it might be worth trying your code with different compilers.
对于提升性能来说还有很多东西要做。通道级操作,诸如半差分,可以抽象出来放入原子通道级算法,而对实际通道类型可能有性能开销。可以使用处理器特定的操作,例如对一整行像素同时执行操作,或者数据能预取。所有这些优化可以实现为泛型算法的性能特化(注:这里可能指模板特化)。最后,编译器,虽然在时间上较好,但在某些情况下仍然无法对生成完全优化的泛型代码,诸如无法行内展开一些函数或把一些变量放入寄存器。如果性能是一个问题,你的代码可能值得用不同的编译器测试。
Appendix
附录
Naming convention for GIL concrete types
GIL实际类型的命名约定
Concrete (non-generic) GIL types follow this naming convention:
实际(非泛型)GIL类型遵循以下命名约定:(注:这里+表示字符串连接)
ColorSpace + BitDepth + [f | s]+ [c] + [_planar] + [_step] + ClassType + _t
色空间(注:原色的排列) + 位深(注:通道的位数) + [f | s] + [c(注:常量性,不可变)] + [_planar(注:平面)] + 类名称(注:图片、像素、引用、指针等) + _t
Where ColorSpace also indicates the ordering of components. Examples are rgb, bgr, cmyk, rgba. BitDepth indicates the bit depth of the color channel. Examples are 8,16,32. By default the type of channel is unsigned integral; using s indicates signed integral and f - a floating point type, which is always signed. c indicates object operating over immutable pixels. _planar indicates planar organization (as opposed to interleaved). _step indicates special image views, locators and iterators which traverse the data in non-trivial way (for example, backwards or every other pixel). ClassType is _image (image), _view (image view), _loc (pixel 2D locator) _ptr (pixel iterator), _ref (pixel reference), _pixel (pixel value).
其中ColorSpace还表明构成的次序。例如rgb,bgr,cmyk,rgba。BitDepth表明颜色通道的位数,例如8,16,32。默认通道类型是无符号整型;使用s表明是有符号整型而f表明是总是有符号的浮点数。 c表明操作只读像素的对象。 _planar表明是平面结构的(不同于交错)(注:“平面”指同一通道的像素在内存上是连续的)。 _step表明以非细微的方式(例如向后遍历或者每隔一个像素的遍历)遍历数据的特殊的图片视图、定位器和迭代器。 ClassType是_image(图片)、_view(图片视图)、_loc(像素二维定位器)、_ptr(像素迭代器)、_ref(像素引用), _pixel(像素值).
bgr8_image_t a; // 8-bit interleaved BGR image // 8位交错BGR图片
cmyk16_pixel_t; b; // 16-bit CMYK pixel value; // 16位CMYK像素值;
cmyk16c_planar_ref_t c(b); // const reference to a 16-bit planar CMYK pixel x. // 指向16位平面的CMYK像素x的常量引用。
rgb32f_planar_step_ptr_t d; // step pointer to a 32-bit planar RGB pixel. // 指向32位平面RGB像素的步进指针。
Copyright (c) 2005 Adobe Systems Incorporated
(译后注:一篇非常棒的教程,对C++代码优化的见解非常精辟,很值得反复斟酌和回味)
更新日志:
2012-07-04:从回收站中粘贴出来,重新发布,内容无改变。
2011-01-14:翻译并发布(后删除)
发表评论
-
【翻译】泛型图片库(GIL)教程(上)
2012-07-04 22:57 2004原文引用自 http://stlab.adobe.co ... -
C++标准库笔记四:用户定义分配器
2012-06-10 22:16 1254C++标准库笔记四:用户定义分配器 下面的代码用g ... -
C++的throw;
2011-10-26 15:11 1880在github上看到一段代码,发现C++的throw;可以写在 ... -
C++标准库笔记三:STL容器
2011-09-02 23:04 1370C++标准库笔记三:STL容器 (20141 ... -
C++和Java异常区别的个人总结
2011-03-23 22:58 1671(个人总结,不全面) ... -
C++标准库笔记二:STL迭代器和STL函数对象
2011-03-17 22:19 3982下面的代码用gcc version 3.4.5 (min ... -
C++标准库笔记一:STL基本组件和STL算法
2011-01-29 09:32 4681下面的代码用gcc version 3.4.5 (mingw- ...
相关推荐
13. **图形用户界面**:如GIL(Generic Image Library)库,用于处理图像数据。 14. **数学和数值计算**:包括高精度计算(mpfr、gmp),随机数生成(random),优化算法(numeric_optimization)等。 15. **测试...
7. **泛型编程**:Boost库中还有许多用于泛型编程的工具,如Boost.MPL(元编程库)、Boost.TypeTraits和Boost.FunctionTypes等,它们可以用来编写高度抽象和高效的代码。 8. **数学与随机数**:Boost.Math库提供了...
3. **泛型编程与元编程**: Boost库是泛型编程和元编程的典范,比如Boost.Lambda、Boost.Bind、Boost.Fusion等,它们使程序员能够编写更灵活、更具表达力的代码。 4. **数学与数值计算**: Boost库中包含数学库,如...
Boost库是C++编程语言中的一个开源库集合,它提供了许多功能强大的工具,包括但不限于泛型编程、模板元编程、容器、算法、线程管理、异常处理等。在这个"boost1.57 libs源代码第一部分"中,我们主要关注以下几个关键...
14. **Boost.TypeErasure**:类型擦除库,允许编写泛型代码,而无需牺牲类型安全。 15. **Boost.Iterator**:扩展了C++的迭代器概念,提供更高级别的迭代器实现。 通过学习《Boost中文手册》,C++开发者不仅可以...
5. **图形库**:虽然Boost库主要关注通用的C++编程,但Boost.GIL(Generic Image Library)提供了一种模板化的图像处理框架,适用于图像处理和计算机视觉应用。 6. **正则表达式**:Boost.Regex库实现了C++的正则...
Boost库是C++编程语言的一个开源库集合,它提供了大量的高效、高质量的工具,用于提升C++的功能性和可移植性。Boost库在C++社区中备受推崇,因为它的设计目标是帮助开发人员解决实际问题,同时又保持了与C++标准库的...
Boost库的核心理念是为C++添加现代编程范式,如泛型编程、元编程和模式匹配。它包含的库涵盖了各种领域,例如: 1. **智能指针**:例如`shared_ptr`和`unique_ptr`,提供了一种安全的管理动态内存的方式,避免了...
通过使用Boost中的`Boost.GIL`(Generic Image Library)、`Boost.Geometry`等库,开发者可以编写高度灵活且易于扩展的代码,这些库支持多种数据类型和结构,使得代码更加通用。 #### 3. **内存管理** Boost提供了...
Python是一种广泛使用的高级编程语言,以其易读性、丰富的库和强大的功能而受到开发者们的喜爱。随着Python在各个领域的广泛应用,对于Python开发者的面试要求也日益提高,特别是对于中高级职位,深入理解Python的...
解释具有通用多态性的语言中协变和逆变的概念(用书面例子),并解释在什么情况下它们的使用是安全的 解释控制反转和依赖注入 什么是 Haskell 中的惰性评估并解释 IO Monads 的精神 学生选择的主题:Java 中的 ...
在学习这两本书时,开发者会了解到如何利用C++的模板和STL来编写泛型代码,以及Python的模块化设计和面向对象特性来组织复杂项目。同时,书中还提醒读者注意潜在的陷阱,比如C++中的悬挂指针和Python中的全局解释器...
Dataset是DataFrame的类型安全版本,支持Java泛型,提供了更强大的编译时检查和更高的性能。 PySpark中的主要组件有: 1. SparkContext:它是PySpark程序的入口点,负责与Spark集群建立连接,并管理所有的资源。 2....
此外,理解和使用泛型、并发容器如ConcurrentHashMap也是面试中的常见问题。 3. **异常处理**:掌握如何正确使用try-catch-finally语句块,理解不同类型的异常,以及自定义异常的创建和抛出。 4. **多线程**:包括...
使用方法: 1.引用HtmlAgilityPack.dll文件 2.引用命名空间: 代码如下:using HtmlAgilityPack; 3.调用 代码如下: static void Main(string[] args) { string ... HtmlNode node = doc.DocumentNod