使用 PixelBender 将位图大小加倍
我有一个关于像素弯曲器的性能问题。我想放大许多 BitmapData(将它们的大小加倍为新的 BitmapData)。我是用 as3 做的,但想使用 Pixel Bender 来获得更好的性能。在我的机器上,我从像素弯曲器中获得了更好的性能 演示然后是as3。
令我惊讶的是(或者糟糕的编码/理解),我的像素弯曲器的性能差很多——2 秒 vs 1/2 秒!我期望获得至少相同与 as3 的性能。我做错了什么?
我得到了简单的像素弯曲器代码 此处(为了方便参考,它包含在下面)。
package
{
import flash.display.BitmapData;
import flash.display.Shader;
import flash.display.ShaderJob;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.geom.Matrix;
public class flashFlash extends Sprite
{
[Embed ( source="pixelbender/bilinearresample.pbj", mimeType="application/octet-stream" ) ]
private static var BilinearScaling:Class;
public function flashFlash( ):void
{
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
addEventListener( Event.ENTER_FRAME, efCb, false, 0, true );
}
private function efCb( evt:Event ):void
{
removeEventListener( Event.ENTER_FRAME, efCb, false );
traceTime( "init" );
var srcBmd:BitmapData = new BitmapData( 80, 120, false, 0 );
var destBmd:BitmapData = new BitmapData( 160, 240, false, 0 );
var mx:Matrix = new Matrix( );
mx.scale( 2, 2 );
for (var i:uint = 0; i < 3000; i++)
{ destBmd.draw( srcBmd, mx );
}
traceTime( "scaled with as3" );
// create and configure a Shader object
var shader:Shader = new Shader( );
shader.byteCode = new BilinearScaling( );
shader.data.scale.value = [.5];
shader.data.src.input = srcBmd;
for (var j:uint = 0; j < 3000; j++)
{
var shaderJob:ShaderJob = new ShaderJob( );
shaderJob.shader = shader;
shaderJob.target = destBmd;
shaderJob.start( true );
}
traceTime( "scaled with pixel bender bilinearresample.pbj" );
}
private static var _lastTraceTime:Number = new Date().getTime();
public static function traceTime( note:String ):Number
{ var nowTime:Number = new Date().getTime();
var diff:Number = (nowTime-_lastTraceTime);
trace( "[t" + diff + "] " + note );
_lastTraceTime = nowTime;
return diff;
}
}
}
和像素弯曲器代码:
<languageVersion : 1.0;>
kernel BilinearResample
< namespace : "com.brooksandrus.pixelbender";
vendor : "Brooks Andrus";
version : 1;
description : "Resizes an image using bilinear resampling. Constrains aspect ratio - divide Math.max( input.width / output.width, input.height / output.height ) and pass in to the scale parameter";
>
{
parameter float scale
<
minValue: 0.0;
maxValue: 1000.0;
defaultValue: 1.0;
>;
input image4 src;
output pixel4 dst;
void
evaluatePixel()
{
// scale should be Math.max( src.width / output.width, src.height / output.height )
dst = sampleLinear( src, outCoord() * scale ); // bilinear scaling
}
}
I have a performance question about pixel bender. I want to enlarge many BitmapData (double their size into new BitmapData). I was doing this with as3, but wanted to use pixel bender to get better performance. On my machine, I get better performance out of pixel bender demonstrations then as3.
To my surprise (or bad coding / understanding), I am getting much worse performance out of pixel bender -- 2 seconds vs 1/2 second! I expected to get at least the same performance as as3. What am I doing wrong?
I got the straightforward pixel bender code here (and it is included below for easy reference).
package
{
import flash.display.BitmapData;
import flash.display.Shader;
import flash.display.ShaderJob;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.geom.Matrix;
public class flashFlash extends Sprite
{
[Embed ( source="pixelbender/bilinearresample.pbj", mimeType="application/octet-stream" ) ]
private static var BilinearScaling:Class;
public function flashFlash( ):void
{
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
addEventListener( Event.ENTER_FRAME, efCb, false, 0, true );
}
private function efCb( evt:Event ):void
{
removeEventListener( Event.ENTER_FRAME, efCb, false );
traceTime( "init" );
var srcBmd:BitmapData = new BitmapData( 80, 120, false, 0 );
var destBmd:BitmapData = new BitmapData( 160, 240, false, 0 );
var mx:Matrix = new Matrix( );
mx.scale( 2, 2 );
for (var i:uint = 0; i < 3000; i++)
{ destBmd.draw( srcBmd, mx );
}
traceTime( "scaled with as3" );
// create and configure a Shader object
var shader:Shader = new Shader( );
shader.byteCode = new BilinearScaling( );
shader.data.scale.value = [.5];
shader.data.src.input = srcBmd;
for (var j:uint = 0; j < 3000; j++)
{
var shaderJob:ShaderJob = new ShaderJob( );
shaderJob.shader = shader;
shaderJob.target = destBmd;
shaderJob.start( true );
}
traceTime( "scaled with pixel bender bilinearresample.pbj" );
}
private static var _lastTraceTime:Number = new Date().getTime();
public static function traceTime( note:String ):Number
{ var nowTime:Number = new Date().getTime();
var diff:Number = (nowTime-_lastTraceTime);
trace( "[t" + diff + "] " + note );
_lastTraceTime = nowTime;
return diff;
}
}
}
And the pixel bender code:
<languageVersion : 1.0;>
kernel BilinearResample
< namespace : "com.brooksandrus.pixelbender";
vendor : "Brooks Andrus";
version : 1;
description : "Resizes an image using bilinear resampling. Constrains aspect ratio - divide Math.max( input.width / output.width, input.height / output.height ) and pass in to the scale parameter";
>
{
parameter float scale
<
minValue: 0.0;
maxValue: 1000.0;
defaultValue: 1.0;
>;
input image4 src;
output pixel4 dst;
void
evaluatePixel()
{
// scale should be Math.max( src.width / output.width, src.height / output.height )
dst = sampleLinear( src, outCoord() * scale ); // bilinear scaling
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为问题在于您实际上是将 Pixel Bender 与本机播放器代码进行比较,而不是与“actionscript”进行比较。我怀疑 Pixel Bender 是否会在这种情况下获胜。
此处发生的缩放
destBmd.draw( srcBmd, mx );
直接在播放器中编码;这可能是您能达到的最快速度(使用等效算法)。另一方面,您的内核至少必须首先编译(或 JIT 编译)才能运行(可能还有许多其他原因导致它变慢;不过,我不太了解具体细节)。查看 Flash Player 工程师的博客中的这篇文章:
因此,基本上,Pixel Bender 比直接在 Actionscript 中操作像素更快。它将胜过无数次 setPixel 和 getPixel 调用。但它不会比玩家本身更快(同样,使用相同的算法)。
在某种程度上,您想要做的事情就像在 PB 中编写辉光滤镜一样。当然,它很酷,如果您对图像处理感兴趣,您可以从中学到很多东西。但是,如果您的过滤器旨在像本机过滤器一样工作,那么除了教育目的之外,它没有太多意义:本机过滤器会更快并且它已经可用,无需额外的代码行。
I think the problem is that you are really comparing Pixel Bender against native player code, not against "actionscript". I doubt Pixel Bender will ever win on that scenario.
The scaling that takes place here
destBmd.draw( srcBmd, mx );
is coded directly in the player; that's probably as fast as you can get (using an equivalent algorithm). Your kernel on the other hand has at least to be compiled (or JIT compiled) first in order to run (probably there are a number of other reasons for it to be slower; I don't know much about the specifics, though).Check out this post from the blog of a Flash Player engineer:
So, basically, Pixel Bender is faster than manipulating pixels directly in Actionscript. It will outperform an equivalent zillion of setPixel and getPixel calls. But it won't be faster than the player itself (again, using the same algorithm).
In a way, what you're trying to do is like writting, say, a glow filter in PB. Sure, it's cool and you can learn a lot from it if you're interested in image processing. But if your filter is meant to work just like the native filter, there's not much point in it, aside from educational purposes: the native filter will be faster and it's already available, without an extra line of code.
我隐约记得听说虽然连接到像素弯曲器文件等的过程较慢,但处理本身却更快。所以我想你会看到随着图像尺寸变大,像素弯曲滤波器最终可能会变得更加高效。或者,也许 PixelBender 最适合稍微复杂的图像处理。
I vaguely remember hearing that while the process of connecting to a pixel bender file etc is slower, the processing itself is faster. So I imagine what you'd see is that as image size gets larger, the pixel bender filter may eventually get more efficient. Or maybe PixelBender is best saved for slightly more complex image manipulations.