Confusion about Texture2D and ShaderResourceViews - resources

I am new to Direct3D11 and I am currently trying to create a texture programatically within my code using this code I found online:
// Some Constants
int w = 256;
int h = 256;
int bpp = 4;
int *buf = new int[w*h];
//declarations
ID3D11Texture2D* tex;
D3D11_TEXTURE2D_DESC sTexDesc;
D3D11_SUBRESOURCE_DATA tbsd;
// filling the image
for (int i = 0; i<h; i++)
for (int j = 0; j<w; j++)
{
if ((i & 32) == (j & 32))
buf[i*w + j] = 0x00000000;
else
buf[i*w + j] = 0xffffffff;
}
// setting up D3D11_SUBRESOURCE_DATA
tbsd.pSysMem = (void *)buf;
tbsd.SysMemPitch = w*bpp;
tbsd.SysMemSlicePitch = w*h*bpp; // Not needed since this is a 2d texture
// initializing sTexDesc
sTexDesc.Width = w;
sTexDesc.Height = h;
sTexDesc.MipLevels = 1;
sTexDesc.ArraySize = 1;
sTexDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sTexDesc.SampleDesc.Count = 1;
sTexDesc.SampleDesc.Quality = 0;
sTexDesc.Usage = D3D11_USAGE_DEFAULT;
sTexDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
sTexDesc.CPUAccessFlags = 0;
sTexDesc.MiscFlags = 0;
hr = m_pd3dDevice->CreateTexture2D(&sTexDesc, &tbsd, &tex);
and that' all fine and dandy, but I am a bit confused about how to actually load this into the shader. Below I initialized this ID3D11ShaderResourceView:
ID3D11ShaderResourceView* m_pTextureRV = nullptr;
I found on the Microsoft tutorials I need to use the CreateShaderResourceView. But how exactly do I use it? I tried this:
hr = m_pd3dDevice->CreateShaderResourceView(tex, NULL , m_pTextureRV);
but it gives me an error, telling me that m_pTextureRV is not a valid argument for the function. What am I doing wrong here?

The correct way to call that function is:
hr = m_pd3dDevice->CreateShaderResourceView(tex, nullptr, &m_pTextureRV);
Remember that ID3D11ShaderResourceView* is a pointer to an interface. You need a pointer-to-a-pointer to get a new instance of one back.
You should really consider using a COM smart-pointer like Microsoft::WRL::ComPtr instead of raw pointers for these interfaces.
Once you have created the shader resource view for your texture object, then you need to associate it with whatever slot the HLSL expects to find it in. So, for example, if you were to write an HLSL source file as:
Texture2D texture : register( t0 );
SamplerState sampler: register( s0 );
float4 PS(float2 tex : TEXCOORD0) : SV_Target
{
return texture.Sample( sampler, tex );
}
Then compile it as a Pixel Shader, and bind it to the render pipeline via PSSetShader. Then you'd need to call:
ID3D11ShaderResourceView* srv[1] = { m_pTextureRV };
m_pImmediateContext->PSSetShaderResources( 0, 1, srv );
Of course you also need a ID3D11SamplerState* sampler bound as well:
ID3D11SamplerState* m_pSamplerLinear = nullptr;
D3D11_SAMPLER_DESC sampDesc = {};
sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
sampDesc.MinLOD = 0;
sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
hr = m_pd3dDevice->CreateSamplerState( &sampDesc, &m_pSamplerLinear );
Then when you are about to draw:
m_pImmediateContext->PSSetSamplers( 0, 1, &m_pSamplerLinear );
I strongly recommend you check out the DirectX Tool Kit and the tutorials there.

Related

Trouble properly setting up descriptor sets for multiple models in Vulkan

I'm having a problem trying to implement multiple models in Vulkan. I used the official Vulkan tutorial to set up most of the boilerplate code, then the rest is custom. At the moment, I am able to get one model to render perfectly, while the other identical model renders in about 60% of frames and doesn't render at all in others, as shown in the gif: Engine output
I've tried changing many things to fix it, but I can't pinpoint what is causing the issue. Any help would be appreciated wholly. I'm attaching the code snippets I think most relevant but I can include more if it helps solve the issue.
CreateCommandBuffers():
...
vkCmdBindVertexBuffers(commandBuffers[i], 0, 1, vertexBuffers, offsets);
vkCmdBindIndexBuffer(commandBuffers[i], indexBuffer, 0, VK_INDEX_TYPE_UINT32);
vkCmdBindDescriptorSets(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets[i], 0, nullptr); //COMEBACKTO
vkCmdDrawIndexed(commandBuffers[i], models[0].getModelIndicesSize(), 1, 0, 0, 0);
vkCmdBindDescriptorSets(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets[i + 1], 0, nullptr);
vkCmdDrawIndexed(commandBuffers[i], models[0].getModelIndicesSize(), 1, 0, 0, 0);
...
createDescriptorSets():
std::vector<VkDescriptorSetLayout> layouts(swapChainImages.size() * models.size(), descriptorSetLayout);
VkDescriptorSetAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = descriptorPool;
allocInfo.descriptorSetCount = static_cast<uint32_t>(swapChainImages.size() * models.size());
allocInfo.pSetLayouts = layouts.data();
descriptorSets.resize(swapChainImages.size() * models.size());
if (vkAllocateDescriptorSets(device, &allocInfo, descriptorSets.data()) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate descriptor sets!");
}
for (int i = 0; i < swapChainImages.size(); i++) {
std::vector<VkWriteDescriptorSet> descWrites;
descWrites.resize(models.size() * 2);
for (int j = 0; j < models.size(); j++) {
VkDescriptorBufferInfo bufferInfo{};
bufferInfo.offset = 0;
bufferInfo.range = sizeof(UniformBufferObject);
//bufferInfo.buffer = uniformBuffers[i];
bufferInfo.buffer = uniformBuffers[j + (i * (models.size() - 1))];
VkDescriptorImageInfo imageInfo{};
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
imageInfo.imageView = textureImageView; //set these up
imageInfo.sampler = textureSampler; //set these up
int tmp = j * 2;
int tmp1 = tmp + 1;
descWrites[tmp].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descWrites[tmp].dstSet = descriptorSets[j + (i * (models.size() - 1))];
descWrites[tmp].dstBinding = 0;
descWrites[tmp].dstArrayElement = 0;
descWrites[tmp].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descWrites[tmp].descriptorCount = 1;
descWrites[tmp].pBufferInfo = &bufferInfo;
descWrites[tmp1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descWrites[tmp1].dstSet = descriptorSets[j + (i * (models.size() - 1))];
descWrites[tmp1].dstBinding = 1;
descWrites[tmp1].dstArrayElement = 0;
descWrites[tmp1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descWrites[tmp1].descriptorCount = 1;
descWrites[tmp1].pImageInfo = &imageInfo;
}
vkUpdateDescriptorSets(device, static_cast<uint32_t>(descWrites.size()), descWrites.data(), 0, nullptr);
}

How is a JPEG file formated?

I'm trying to write Bytes into a JPEG file, but I don't know the file's format and so the Bytes aren't in the right place of the image after writing into the file.
Does somebody know?
There are several markers that must appear in a JPEG file stream. I believe you can easily find the detailed description of the tags listed below on Internet.
SOI(0xFFD8) Start of Image
APP0(0xFFE0) Application
[APPn(0xFFEn)] (alternative)
DQT(0xFFDB) Define Quantization Table
SOF0(0xFFC0) Start of Frame
DHT(0xFFC4) Difine Huffman Table
SOS(0xFFDA) Start of Scan
DRI(0xFFDD) Define Restart Interval,(alternative)
...Image Stream
EOI(0xFFD9) End of Image
Those markers are followed by lengths in BIG ENDIAN format. You can decode Image Stream that exactly follows DRI using the huffman trees you decoded by DQT. For easier illustration, here are some functions I have written on my own in Java that decodes a header of JPEG, but without doubt there are many better JPEG Java projects on Github that you can refer to.
public int[][] cutX(byte[] x){
int s = x.length;int k = 1;int i = 2;int j;
d2[0][0]=Tool.unsignDecoder(x[1]);d2[1][0]=0;d2[2][0]=1;
while(d2[0][k-1]!=218){
d2[1][k]=i;
d2[0][k]=Tool.unsignDecoder(x[i+1]);
i=i+2+Tool.unsignDecoder(x[i+2])*256+Tool.unsignDecoder(x[i+3]);
d2[2][k]=i-1;
k=k+1;
}
for (j=s-1;j<i;j--){
if((Tool.unsignDecoder(x[j-1])==255)&&(Tool.unsignDecoder(x[j])==217)) break;
}
d2[0][k]=217;d2[1][k]=i;d2[2][k]=j+1;
return d2;
}
public void cutdata(byte[] x,int[][] d){
int a =Tool.indexOf_1(d[0],218);
int b =Tool.indexOf_1(d[0],217);
head = Arrays.copyOfRange(x, 0, d[2][a]+1);
byte[] im = Arrays.copyOfRange(x, d[1][b], d[2][b]-1);//-2:delete the last EOI message.
im1 = new byte[im.length];
int j=0;int i=0;//dynamically record the length of the revised sequence
while(i<im.length){
im1[j]=im[i];
j++;
if((i!=im.length-1)&&(Tool.unsignDecoder(im[i])==255)&&(Tool.unsignDecoder(im[i+1]))==0){
i++;//move rightward i
}
i++;
}
im1=Arrays.copyOfRange(im1, 0, j);//delete zeros in the end of the sequence
}
public void sof(byte[] x,int[][] d){
int z = Tool.indexOf_1(d[0],192);
int i = d[1][z];
int[] temp = new int[19];
for(int j=0;j<19;j++){
temp[j]=Tool.unsignDecoder(x[j+i]);
}
int ph=i+5;int pw=i+7;
size[0] = Tool.unsignDecoder(x[ph])*256+Tool.unsignDecoder(x[ph+1]);
size[1] = Tool.unsignDecoder(x[pw])*256+Tool.unsignDecoder(x[pw+1]);
i += 11;//skip some unused letters
for(int j=0;j<3;j++){
int k = Tool.unsignDecoder(x[i]);
Q[j][0] = (k & 0xF0)/16;
Q[j][1] = k & 0x0F;
i += 3;
}
}
public void hfm(byte[] x,int[][] d){
//the DHT marker may appear several times in a JPEG, or several huffman trees can be found in a single DHT.
ArrayList res =Tool.indexOf(d[0],196);int thisLength;int pointer;int pointerOrigin;
int a;int huffLength = 0;
for(int z=0;z<res.size();z++){
a=(int) res.get(z);
pointer = d[1][a];pointerOrigin = d[1][a]+2;//please follow the straight-forward moving of this pointer
thisLength = Tool.unsignDecoder(x[pointer+2])*256+Tool.unsignDecoder(x[pointer+3]);
int[] temp = new int[thisLength+4];
for(int i=0;i<thisLength;i++){
temp[i]=Tool.unsignDecoder(x[pointer+i]);
}
pointer += 4;
while(huffLength<thisLength){
int mode = Tool.unsignDecoder(x[pointer]);pointer += 1;
int[] huff_num = new int[16];int total=0;
for(int i=0;i<16;i++){//码字总个数
huff_num[i] = x[pointer+i];total+=huff_num[i];
}
pointer +=16;int codePointer=0;int code=0;
int[][] huffmanTree = new int[3][total];
for(int i=0;i<16;i++){
if(i!=0){
code *= 2;
}
for(int j=0;j<huff_num[i];j++){
huffmanTree[0][codePointer]=i+1;
huffmanTree[1][codePointer]=code;
huffmanTree[2][codePointer]=Tool.unsignDecoder(x[pointer+codePointer]);
code++;codePointer++;
}
}
huffLength += pointer + codePointer - pointerOrigin;pointer += codePointer;
pointerOrigin = pointer;
switch(mode){
case(0):d0 = huffmanTree;break;
case(1):d1 = huffmanTree;break;
case(16):a0 = huffmanTree;break;
case(17):a1 = huffmanTree;break;
}
}
}
}
public void dri(byte[] x,int[][] d){
int z = Tool.indexOf_1(d[0],221);
if(z!=-1){
int pointer = d[1][z];
int len = Tool.unsignDecoder(x[pointer+2])*256+Tool.unsignDecoder(x[pointer+3]);
int[] temp = new int[len+2];
for(int i=0;i<len;i++){
temp[i]=Tool.unsignDecoder(x[pointer+i]);
}
DRI = Tool.unsignDecoder(x[d[1][z]+4])*256+Tool.unsignDecoder(x[d[1][z]+5]);}
}
public void sos(byte[] x,int[][] d){
int z = Tool.indexOf_1(d[0],218);int a = d[1][z];
int len = Tool.unsignDecoder(x[a+2])*256+Tool.unsignDecoder(x[a+3]);
int[] temp = new int[len+2];
for(int j=0;j<len+2;j++){
temp[j]=Tool.unsignDecoder(x[j+a]);
}
int pointer = d[1][z]+6;
for(int j=0;j<3;j++){
treeSelect[j] = Tool.unsignDecoder(x[pointer]);
pointer += 2;
}
}

Counting Shapes/Objects Created Continuously within Processing

My code takes an image and creates a pointillist image through creating ellipses with a pixel's color.
After a while, the image is fully 'painted' and I want to automatically switch to another image in my sketch folder.
I would like to be able to count the number of ellipses generated. Once 'z' ellipses are generated I want to tell my code to erase all ellipses and start over with a new image.
CODE:
PImage img;
int smallPoint, largePoint;
void setup() {
size(1920, 1080);
img = loadImage("rio.jpg");
smallPoint = 12;
largePoint = 12;
imageMode(CENTER);
noStroke();
background(255);
}
void draw() {
for (int i = 0; i < 1000; i++)
{
drawADot();
}
}
void drawADot()
{
int imageWidth = img.width;
int imageHeight = img.height;
int ptSize = int(random(100)) + 4;
float pointillize = map(mouseX, 0, width, smallPoint, largePoint); //not used right now but for controlling ellipse size
int x = int(random(0, imageWidth/8));
int y = int(random(0, imageHeight/8));
color pix = img.get(x*8, y*8);
fill(pix, 255);
ellipse(x*8, y*8, pointillize, pointillize);
}
Store the images in an array, count the dots added, and conditionally (based in number of dots) change the image being used to next one in the array, you can pass the image to the drawADot() function as a parameter. Something like:
PImage img[] = new PImage[2];
int smallPoint, largePoint;
final int DOTSPERDRAW = 500;
int numberOfDots = 0;
final int MAXDOTS = DOTSPERDRAW * 100;
PImage workingImage ;
int index;
void setup() {
size(810, 455);
img[0] = loadImage("http://assets2.exame.abril.com.br/assets/images/2014/8/506584/size_810_16_9_rio.jpg");
img[1] = loadImage("http://upload.wikimedia.org/wikipedia/commons/1/1e/Pilcomayo_rio.jpg");
img[1].resize(810, 0);
smallPoint = 12;
largePoint = 12;
imageMode(CENTER);
noStroke();
background(255);
workingImage = img[0];
}
void draw() {
if (numberOfDots > MAXDOTS) {
index = (index + 1) % img.length;
workingImage = img[index];
numberOfDots = 0;
}
for (int i = 0; i < DOTSPERDRAW; i++)
{
drawADot(workingImage);
}
numberOfDots += DOTSPERDRAW;
}
void drawADot(PImage theImage)
{
int imageWidth = theImage.width;
int imageHeight = theImage.height;
int ptSize = int(random(100)) + 4;
float pointillize = map(mouseX, 0, width, smallPoint, largePoint); //not used right now but for controlling ellipse size
int x = int(random(0, imageWidth/8));
int y = int(random(0, imageHeight/8));
color pix = theImage.get(x*8, y*8);
fill(pix, 255);
ellipse(x*8, y*8, pointillize, pointillize);
}

Extracting a portion of Image in C#

I have made a C# Windows application with two Picture-Boxes one as MainPictureBox and other as ThumbnailBox, I want to Extract a portion of Image upon moving mouse over Main Image and load it into ThumbnailPictureBox.
Here is a way to get a thumbnail from the image.
public static Bitmap Thumb(this Image inputStream, int width, int height)
{
using (var bitMap = new Bitmap(inputStream))
{
int originalWidth = bitMap.Width;
int originalHeight = bitMap.Height;
int startPositionHeight = 0;
int startPosionWidth = 0;
int widthHeight = 0;
if (originalWidth > originalHeight)
{
startPosionWidth = (originalWidth - originalHeight) / 2;
widthHeight = originalHeight;
}
else if (originalHeight > originalWidth)
{
startPositionHeight = (originalHeight - originalWidth) / 2;
widthHeight = originalWidth;
}
else if (originalWidth == originalHeight)
{
widthHeight = originalHeight;
}
var rect = new Rectangle(startPosionWidth, startPositionHeight, widthHeight, widthHeight);
using (Bitmap cropped = bitMap.Clone(rect, bitMap.PixelFormat))
{
using (var newbitmap = new Bitmap(cropped, width, height))
{
var stream = new MemoryStream();
newbitmap.Save(stream, ImageFormat.Tiff);
stream.Position = 0;
return new Bitmap(stream);
}
}
}
}

Haxe & NME: fastest method for per pixel bitmap manipulation

This is a small project for testing pixel level manipulation performance of NME for different builds (Windows c++, Flash).
It uses BitmapData.setPixel to modify the pixels one by one (320x240 for every frame). The C++ build runs at 22 FPS, and the flash build around ~100 FPS. Whats the reason for the huge performance drop for the C++ build compared to flash? How could I improve the code to get higher FPS using the C++ build?
Mandelbrot.hx
import nme.display.Sprite;
import nme.display.Bitmap;
import nme.display.BitmapData;
import nme.text.TextField;
import nme.events.Event;
import nme.events.TimerEvent;
import nme.utils.Timer;
import nme.geom.Matrix;
import nme.geom.Rectangle;
import nme.utils.ByteArray;
class Mandelbrot
{
public static function main() : Void
{
new Mandelbrot();
}
public var pixels:Array<Array<Int>>;
public var colorModifier:Int;
private var bitmapData:BitmapData;
private var bigBitmapData:BitmapData;
private var fps:TextField;
private var width:Int;
private var height:Int;
private var matrix:Matrix;
public function new()
{
width = 320; //Std.int(flash.Lib.current.stage.stageWidth/2);
height = 240; //Std.int(flash.Lib.current.stage.stageHeight/2);
var scale:Float = 2;//flash.Lib.current.stage.stageWidth/width;
matrix = new Matrix();
matrix.scale(scale, scale);
var setBitmap:Bitmap = new Bitmap();
bitmapData = new BitmapData( width , height , false , 0x000000 );
bigBitmapData = new BitmapData( nme.Lib.current.stage.stageWidth , nme.Lib.current.stage.stageHeight , false , 0x000000 );
setBitmap.bitmapData = bigBitmapData;
nme.Lib.current.addChild( setBitmap );
var maxIterations:Int = 128;
pixels = new Array();
var beforeTime = nme.Lib.getTimer();
var xtemp;
var iteration;
var x0:Float = 0;
var y0:Float = 0;
for(ix in 0...width) {
pixels[ix] = new Array();
for(iy in 0...height) {
x0 = 0;
y0 = 0;
iteration = 128;
while ( x0*x0 + y0*y0 <= 4 && iteration > 0 )
{
xtemp = x0*x0 - y0*y0 + (ix-14*5000)/50000;
y0 = 2*x0*y0 + (iy-(height/0.6))/50000;
x0 = xtemp;
iteration--;
}
pixels[ix][iy] = iteration;
}
}
var afterTime = nme.Lib.getTimer();
var tf = new TextField();
tf.width = 400;
tf.text = "Generating fractal took "+(afterTime-beforeTime)+" ms";
nme.Lib.current.addChild(tf);
fps = new TextField();
fps.width = 400;
fps.y = 10;
fps.text = "FPS: ";
nme.Lib.current.addChild(fps);
colorModifier = 2;
var timer:haxe.Timer = new haxe.Timer(10);
runLoop();
timer.run = runLoop;
}
public function runLoop() {
var r:Int=0, b:Int=0, g:Int=0;
var pixel:Int = 0;
var beforeTime = nme.Lib.getTimer();
for(iy in 0...height) {
for(ix in 0...width) {
pixel = pixels[ix][iy];
r = pixel + colorModifier;
g = pixel + colorModifier + r;
b = pixel + colorModifier + g;
bitmapData.setPixel(ix, iy, (r<<16 | g<<8 | b));
}
}
bigBitmapData.draw(bitmapData, matrix, null, null, null, false);
var afterTime = nme.Lib.getTimer();
fps.text = "FPS: "+Math.round(1000/(afterTime-beforeTime));
colorModifier += 2;
if(colorModifier > 65530)
colorModifier = 0;
}
}
Mandelbrot.nmml
<?xml version="1.0" encoding="utf-8"?>
<project>
<app
file="Mandelbrot.hx"
title="Mandelbrot sample"
package="org.haxe.nme.mandelbrot"
version="1.0.0"
company="nme"
main="Mandelbrot"
/>
<window
width="640"
height="480"
orientation="landscape"
fps="60"
background="0xffffff"
resizeable="true"
hardware="true"
/>
<classpath name="." />
<haxelib name="nme" />
<ndll name="std" />
<ndll name="regexp" />
<ndll name="zlib" />
<ndll name="nme" haxelib="nme" />
<setenv name="SHOW_CONSOLE"/>
</project>
Look into the nme.Memory API. The idea is to create a ByteArray with the correct size (or get it from a BitmapData), select it as the current virtual memory space and manipulate its bytes directly.
You'll get an approximately 10x speed boost with Flash and it should be way faster with the CPP target too. Don't forget to compile in Release mode or method inlining will be disabled and performances will suffer a lot.
Basic usage example (untested code) :
var rect:Rectangle = bitmapData.rect;
// 32bits integer = 4 bytes
var size:Int = bitmapData.width * bitmapData.height * 4;
// The virtual memory space we'll use
var pixels:ByteArray = new ByteArray();
// CPP does not support setting the length property directly
#if (cpp) pixels.setLength(size);
#else pixels.length = size; #end
// Select the memory space (call it once, not every frame)
Memory.select(pixels);
// And in your loop set your color
// Color is in BGRA mode, nme.Memory can only be used in little endian mode.
Memory.setI32((y * width + x) * 4, color);
// When you're done, render the BitmapData
// (don't forget to reset the ByteArray position)
pixels.position = 0;
bitmapData.setPixels(rect, pixels);
Keep in mind this is a very basic code example. In your case, you'd need to adapt it and actually use a double sized ByteArray because you need to store the iteration count too. Nested loops can be optimized in your main loop and you can avoid a lot of extra index/address computations :
// Note the size * 2 !
// First part of the ByteArray will be used to store the iteration count,
// the second part to draw the pixels.
#if (cpp) pixels.setLength(size * 2);
#else pixels.length = size * 2; #end
Memory.select(pixels);
// First loop storing iteration count
for (iy in 0...height)
{
for (ix in 0...width)
{
// ... do some stuff ...
Memory.setI32((iy * width + ix) << 2, iteration);
}
}
// In your runLoop :
for (i in 0...(height * width))
{
// Get the iteration count
var pixel:Int = Memory.getI32(i << 2);
r = pixel + colorModifier;
g = pixel + colorModifier + r;
b = pixel + colorModifier + g;
// Note that we're writing the pixel in the second part of our ByteArray
Memory.setI32(size + (i << 2), r | g << 8 | b << 16);
}
// Sets the position to the second part of our ByteArray
pixels.position = size;
bitmapData.setPixels(rect, pixels);
And this is it. If you really don't want to use Alchemy Opcodes on the Flash target, the next fastest way to blit pixels is to use getVector() / setVector() from the BitmapData class. But it's really not as fast.
Array itself is not true liner array in flash, more like a map.
For the per-pixel manipulation I can recommend to use getVector/setVector api of the BitmapData class, which can retrieve (and assign) a rectangular area of the image as flat pixel data. In which case you can access individual pixels in the vector as:
pixels[ix + image_width*iy] = <argb32>
Also, instead of constructing an intermediate Array of Arrays it would be faster to assign pixels directly.
Try to use ByteArray. It would be faster in Flash and C++, I think.

Resources