Skip to content

Commit

Permalink
avm2: Implement BitmapData.copyPixelsToByteArray
Browse files Browse the repository at this point in the history
This basically just re-uses the implementation of getPixels
  • Loading branch information
Aaron1011 committed Oct 5, 2023
1 parent 53babdd commit 3a658f5
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 5 deletions.
1 change: 1 addition & 0 deletions core/src/avm2/globals/flash/display/BitmapData.as
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ package flash.display {
public native function get transparent():Boolean;

public native function getPixels(rect:Rectangle):ByteArray;
public native function copyPixelsToByteArray(rect:Rectangle, data:ByteArray):void;
public native function getVector(rect:Rectangle):Vector.<uint>;
public native function getPixel(x:int, y:int):uint;
public native function getPixel32(x:int, y:int):uint;
Expand Down
42 changes: 40 additions & 2 deletions core/src/avm2/globals/flash/display/bitmap_data.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! `flash.display.BitmapData` builtin/prototype
use crate::avm2::activation::Activation;
use crate::avm2::bytearray::ByteArrayStorage;
use crate::avm2::error::{argument_error, make_error_2008, range_error};
use crate::avm2::filters::FilterAvm2Ext;
pub use crate::avm2::object::bitmap_data_allocator;
Expand Down Expand Up @@ -297,15 +298,52 @@ pub fn get_pixels<'gc>(
bitmap_data.check_valid(activation)?;
let rectangle = args.get_object(activation, 0, "rect")?;
let (x, y, width, height) = get_rectangle_x_y_width_height(activation, rectangle)?;
let storage =
operations::get_pixels_as_byte_array(activation, bitmap_data, x, y, width, height)?;
let mut storage = ByteArrayStorage::new();

operations::get_pixels_as_byte_array(
activation,
bitmap_data,
x,
y,
width,
height,
&mut storage,
)?;
let bytearray = ByteArrayObject::from_storage(activation, storage)?;
return Ok(bytearray.into());
}

Ok(Value::Undefined)
}

/// Implements `BitmapData.copyPixelsToByteArray`.
pub fn copy_pixels_to_byte_array<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(bitmap_data) = this.as_bitmap_data() {
bitmap_data.check_valid(activation)?;
let rectangle = args.get_object(activation, 0, "rect")?;
let storage = args.get_object(activation, 1, "data")?;
let mut storage = storage
.as_bytearray_mut(activation.context.gc_context)
.unwrap();
let (x, y, width, height) = get_rectangle_x_y_width_height(activation, rectangle)?;
operations::get_pixels_as_byte_array(
activation,
bitmap_data,
x,
y,
width,
height,
&mut storage,
)?;
}

Ok(Value::Undefined)
}

pub fn get_vector<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Object<'gc>,
Expand Down
6 changes: 3 additions & 3 deletions core/src/bitmap/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1622,8 +1622,8 @@ pub fn get_pixels_as_byte_array<'gc>(
y: i32,
width: i32,
height: i32,
) -> Result<ByteArrayStorage, Error<'gc>> {
let mut result = ByteArrayStorage::new();
result: &mut ByteArrayStorage,
) -> Result<(), Error<'gc>> {
let mut region = PixelRegion::for_region_i32(x, y, width, height);
region.clamp(target.width(), target.height());

Expand All @@ -1637,7 +1637,7 @@ pub fn get_pixels_as_byte_array<'gc>(
}
}

Ok(result)
Ok(())
}

pub fn set_pixels_from_byte_array<'gc>(
Expand Down
55 changes: 55 additions & 0 deletions tests/tests/swfs/avm2/bitmapdata_copypixelstobytearray/Test.as
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package {
import flash.display.DisplayObjectContainer;
import flash.display.BitmapData;
import flash.geom.Rectangle;
import flash.utils.ByteArray;

public class Test {
static var WIDTH: uint = 10;
static var HEIGHT: uint = 10;

public function Test() {
var src: BitmapData = createSource();
printPixels(src, 0, 0, 5, 5);
printPixels(src, 5, 5, 3, 3);
printPixels(src, 0, 0, 10, 10);
printPixels(src, -1, -1, 2, 2);
}

static function createSource(): BitmapData {
var src: BitmapData = new BitmapData(WIDTH, HEIGHT, true, 0x00000000);
src.noise(0);
return src;
}

static function printPixels(src: BitmapData, x: int, y: int, width: uint, height: uint): void {
var rect: Rectangle = new Rectangle(x, y, width, height);
var pixels = new ByteArray();
pixels.writeByte(42);
pixels.writeByte(5);
pixels.position = 100;
pixels.writeByte(255);
pixels.position = 1;
src.copyPixelsToByteArray(rect, pixels);

trace("/// copyPixelsToByteArray(new Rectangle(" + x + ", " + y + ", " + width + ", " + height + "))");

trace("// pixels.length");
trace(pixels.length);
trace("");

trace("// pixels.position");
trace(pixels.position);
trace("");

trace("// pixels");
var result = [];
pixels.position = 0;
for (var i = 0; i < pixels.length; i++) {
result.push(pixels.readUnsignedByte());
}
trace(result);
trace("");
}
}
}
40 changes: 40 additions & 0 deletions tests/tests/swfs/avm2/bitmapdata_copypixelstobytearray/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/// copyPixelsToByteArray(new Rectangle(0, 0, 5, 5))
// pixels.length
101

// pixels.position
101

// pixels
42,255,167,241,217,255,42,130,200,255,216,254,67,255,77,152,85,255,140,226,179,255,153,146,72,255,51,98,65,255,243,13,35,255,229,95,48,255,209,200,237,255,42,202,229,255,72,233,197,255,241,176,196,255,21,138,229,255,155,77,57,255,108,195,81,255,226,32,174,255,12,225,6,255,152,109,97,255,255,52,161,255,68,85,122,255,200,171,80,255,201,178,222,255,178,246,181,255,226,76,79

/// copyPixelsToByteArray(new Rectangle(5, 5, 3, 3))
// pixels.length
101

// pixels.position
37

// pixels
42,255,134,156,196,255,46,54,42,255,2,115,18,255,238,154,235,255,215,24,204,255,79,162,124,255,127,242,179,255,140,109,72,255,208,30,72,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255

/// copyPixelsToByteArray(new Rectangle(0, 0, 10, 10))
// pixels.length
401

// pixels.position
401

// pixels
42,255,167,241,217,255,42,130,200,255,216,254,67,255,77,152,85,255,140,226,179,255,71,23,17,255,152,84,47,255,17,45,5,255,88,245,107,255,214,136,7,255,153,146,72,255,51,98,65,255,243,13,35,255,229,95,48,255,209,200,237,255,97,12,75,255,2,53,57,255,129,132,184,255,20,162,156,255,180,90,103,255,42,202,229,255,72,233,197,255,241,176,196,255,21,138,229,255,155,77,57,255,246,247,232,255,161,5,211,255,254,237,165,255,213,243,217,255,228,91,250,255,108,195,81,255,226,32,174,255,12,225,6,255,152,109,97,255,255,52,161,255,30,25,253,255,54,80,233,255,183,129,143,255,195,58,30,255,15,192,44,255,68,85,122,255,200,171,80,255,201,178,222,255,178,246,181,255,226,76,79,255,221,159,136,255,103,189,206,255,31,242,97,255,0,142,120,255,151,151,14,255,52,98,7,255,215,94,71,255,161,88,41,255,142,91,162,255,245,98,70,255,134,156,196,255,46,54,42,255,2,115,18,255,100,230,6,255,135,239,83,255,9,209,8,255,83,79,81,255,248,101,143,255,180,240,128,255,183,203,25,255,238,154,235,255,215,24,204,255,79,162,124,255,140,55,223,255,193,173,165,255,209,51,209,255,58,190,3,255,240,33,233,255,177,183,140,255,203,216,47,255,127,242,179,255,140,109,72,255,208,30,72,255,27,45,79,255,175,113,113,255,128,95,215,255,242,211,158,255,244,196,241,255,155,148,150,255,232,29,171,255,129,147,179,255,115,126,27,255,39,217,196,255,57,87,22,255,100,65,185,255,53,21,232,255,240,60,149,255,216,232,206,255,30,24,100,255,250,173,104,255,221,252,89,255,50,19,1,255,9,57,11,255,15,31,229,255,202,113,104

/// copyPixelsToByteArray(new Rectangle(-1, -1, 2, 2))
// pixels.length
101

// pixels.position
5

// pixels
42,255,167,241,217,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255

Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
num_ticks = 1

0 comments on commit 3a658f5

Please sign in to comment.