I want to use a C-Function from Node.js by using N-API with node-addon-api module wrapper. This is the first time with N-API for me and I'm also a beginner with Node and C++. I have a experience in C programming of embedded systems but this Node.jS / N-API thing I don't understand completely yet...
What I wan't to do is to call a C-Function with this prototype from Node.js:
unsigned char *MyFunction(unsigned char *data, size_t size, size_t min, size_t max)
*data is a pointer to an array containing RGB image data [R0, G0, B0, R1, G1, B1, ...] with size size which should be processed in MyFunction (extracting RGB channels, inverting, ...).
What I have so far is this c++ code:
#include <napi.h>
using namespace Napi;
Napi::Value Method(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
if (info.Length() != 3) {
Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
return env.Null();
}
else {
const Napi::Array inputArray = info[0].As<Napi::Array>();
const float smin = info[1].As<Napi::Number>().FloatValue();
const float smax = info[2].As<Napi::Number>().FloatValue();
const unsigned int length = inputArray.Length();
unsigned int i;
Napi::Array outputArray = Napi::Array::New(env, length);
Napi::Array redArray = Napi::Array::New(env, length / 3);
Napi::Array greenArray = Napi::Array::New(env, length / 3);
Napi::Array blueArray = Napi::Array::New(env, length / 3);
// Extract Channels
for (i = 0; i < (length / 3); i++) {
redArray[i] = inputArray[i * 3];
greenArray[i] = inputArray[i * 3 + 1];
blueArray[i] = inputArray[i * 3 + 2];
}
// Apply Simple Color Balance to each channel
for (i = 0; i < (length / 3); i++) {
outputArray[i] = redArray[i];
}
return redArray; // Test => this works
}
}
Napi::Object Init(Napi::Env env, Napi::Object exports) {
exports.Set(Napi::String::New(env, "Test"),
Napi::Function::New(env, Method));
return exports;
}
NODE_API_MODULE(module, Init)
and this is the node part:
const sharp = require('sharp');
sharp('testPic.jpg')
.resize(800, 600)
.toFile('SharpOut.jpg')
.then( data => {
console.log('Resize & Negate => OK')
// Extract Channel data
sharp('SharpOut.jpg')
.raw()
.toBuffer()
.then(data => {
var smin = 0.0;
var smax = 0.0;
var testArr = [];
for (let n = 0; n < data.length; n++) {
testArr[n] = data[n];
}
const HelloWorld = require('./build/Release/module.node');
const result = HelloWorld.Test(testArr, smin, smax);
})
.catch(err => {
console.log('ERROR during extraction of RED channel. ERR:');
console.log(err);
});
})
.catch( err => {
console.log('ERROR');
console.log(err);
});
My problems
Sharp outputs a buffer and not an array but with ArrayBuffer instead of Array I was not able to get working code. Compiling is ok but when I execute it in node I'm getting
Error: Invalid argument at D:\temp\testSCB\index.js:30:34
which is this line of code const result = HelloWorld.Test(testArr, smin, smax);)
If I change redArray[i] = inputArray[i * 3]; to redArray[i] = ~(inputArray[i * 3]); to invert the color I'm getting two errors:
error C2675: unary '~': 'Napi::Value' does not define this operator or a
conversion to a type acceptable to the predefined operator
and
error C2088: '~': illegal for class
My Question
What is the correct way to implement my c-Function to work from node.js?
Thanks for any help!
The node.js team has created Array buffer example by using the node-addon-api (the C++ wrapper to N-API), it can be accessed from the following URL. https://github.com/nodejs/node-addon-examples/tree/master/array_buffer_to_native/node-addon-api
If you are looking for a pure N-API implementation (without using any wrapper) then you may take a look on the following examples, this has been created while I was learning the pure N-API.
https://github.com/msatyan/MyNodeC/blob/master/src/mync1/ArrayBuff.cpp.
This example covers the following scenario:
Receive an ArrayBuffer from JavaScript
Create an ArrayBuffer at native layer and return it to JavaScript
Create a TypedArray at native layer and return it to JavaScript
Create an ArrayBuffer at native layer with externally allocated memory
and return it to JavaScript
Sample JavaScript usage of it is available: https://github.com/msatyan/MyNodeC/blob/master/test/TestArrayBuff.js
If you are starting a new native add-on module, I may encourage to use CMake.js instead of node-gyp (look like node-gyp is ending its support). You can get more information about the modern project structure from a sample project that I have created during my N-API study. https://github.com/msatyan/MyNodeC
Related
I've recently started learning Zig.
As a little project I wanted to implement a small QuickCheck [1] style helper library for writing randomized tests.
However, I can't figure out how to write a generic way to call a function with an arbitrary number of arguments.
Here's a simplified version that can test functions with two arguments:
const std = #import("std");
const Prng = std.rand.DefaultPrng;
const Random = std.rand.Random;
const expect = std.testing.expect;
// the thing we want to test
fn some_property(a: u64, b: u64) !void {
var tmp: u64 = undefined;
var c1 = #addWithOverflow(u64, a, b, &tmp);
var c2 = #addWithOverflow(u64, a, b, &tmp);
expect(c1 == c2);
}
// helper for generating random arguments for the function under test
fn gen(comptime T: ?type, rnd: Random) (T orelse undefined) {
switch (T orelse undefined) {
u64 => return rnd.int(u64),
f64 => return rnd.float(f64),
else => #compileError("unsupported type"),
}
}
/// tests if 'property' holds.
fn for_all(property: anytype) !void {
var rnd = Prng.init(0);
const arg_types = #typeInfo(#TypeOf(property)).Fn.args;
var i: usize = 0;
while (i < 100) {
var a = gen(arg_types[0].arg_type, rnd.random());
var b = gen(arg_types[1].arg_type, rnd.random());
var args = .{a, b}; // <-- how do I build args for functions with any number of arguments?
try #call(.{}, property, args);
i += 1;
}
}
test "test" {
try for_all(some_property);
}
I've tried a few different things, but I can't figure out how to get the above code to work for functions with any number of arguments.
Things I've tried:
Make args an array and fill it with an inline for loop. Doesn't work since []anytype is not a valid type.
Use a bit of comptime magic to build a struct type whose fields hold the arguments for #call. This hits a TODO in the compiler: error: TODO: struct args.
Write generic functions that return an appropriate argument tuple call. I don't really like this one, since you need one function for every arity you want to support. But it doesn't seem to work anyway since antype is not a valid return type.
I'm on Zig 0.9.1.
Any insight would be appreciated.
[1] https://hackage.haskell.org/package/QuickCheck
This can be done with std.meta.ArgsTuple (defined in this file of the zig standard library)
const Args = std.meta.ArgsTuple(#TypeOf(property));
var i: usize = 0;
while (i < 1000) : (i += 1) {
var args: Args = undefined;
inline for (std.meta.fields(Args)) |field, index| {
args[index] = gen(field.field_type, rnd.random());
}
try #call(.{}, property, args);
}
The way this works internally is it constructs a tuple type with #Type(). We can then fill it with values and use it to call the function.
I'm trying to write an RCON Client in dart, but I'm getting stuck at this point:
The server recives the packet but seems like it cannot read it properly as reply I'm getting:
Rcon auth failed from rcon whitelist address 2.xxx.xxx.169:52672
Even tough the password is right:
"rcon_password" = "foo" ( def. "" ) - remote console password.
I've provided links to the valve's wiki within the code comments.
This is my code at the moment:
Socket socket;
int _id = 1;
const int SERVERDATA_AUTH = 3;
const int SERVERDATA_AUTH_RESPONSE = 2;
const int SERVERDATA_EXECCOMMAND = 2;
const int SERVERDATA_RESPONSE_VALUE = 0;
void main() async {
socket = await Socket.connect('hexah.net', 27015);
await socket.listen(onSocketData, onError: onError, onDone: onDone);
await _write(SERVERDATA_AUTH, 'foo');
}
void _write(int type, String body) async {
var bodyASCII = ascii.encode(body); //Get ASCII string with Null terminator
// Should I use this or the other way? ??
var size = bodyASCII.length + 14;
var buffer = new Int8List(size).buffer;
var bdata = new ByteData.view(buffer);
bdata.setInt32(0, size - 4, Endian.little); //Byte requests length (32bit le signed int).
bdata.setInt32(4, _id, Endian.little); //Any integer (32bit le signed int).
bdata.setInt32(8, type, Endian.little); //Valid values: SERVERDATA_* (32bit le signed int).
int writepos = 12;
await bodyASCII.forEach((element) {
bdata.setInt8(writepos, element);
writepos +=1;
});
bdata.setInt16(size-2, 0, Endian.little); //Write the null terminators
await socket.write(bdata);
_id++;
}
void onSocketData(var data){
print(data);
}
void onError(var data, StackTrace stack){
print(stack);
}
void onDone(){
print('Connection terminated');
}
Here is also a small example with nodejs:
var size = Buffer.byteLength(body) + 14,
buffer = new Buffer(size);
buffer.writeInt32LE(size - 4, 0);
buffer.writeInt32LE(id, 4);
buffer.writeInt32LE(type, 8);
buffer.write(body, 12, size - 2, "ascii");
buffer.writeInt16LE(0, size - 2);
Do you have any ideas?
especially about getting properly the lengths.
This is how the packet payload should be
Using a RawSocket I get this as reply:
RawSocketEvent.write
RawSocketEvent.readClosed
EDIT:
I'm seeing that the same packet sent from nodejs resulted in a successful authentication but Dart failes, any ideas why this is happening? (converting the packets from nodejs & dart to an array they resulted the same)
Solved!
The issue was that I had to use a RawSocket and write something like this:
var packet = bdata.buffer.asInt8List();
await socket.write(packet, 0, packet.length);
I see there are several node packages that allow you to look up a specific process's usage, such as https://www.npmjs.com/package/usage
I am trying to get the overall sever usage/stats (CPU and Memory), not just one specific process or another. Maybe even disk space usage.
I am currently unable to find anything like this, is this possible?
The native module os can give you some memory and cpu usage statistics.
var os = require('os');
console.log(os.cpus());
console.log(os.totalmem());
console.log(os.freemem())
The cpus() function gives you an average, but you can calculate the current usage by using a formula and an interval, as mentioned in this answer.
There is also a package that does this for you, called os-utils.
Taken from the example on github:
var os = require('os-utils');
os.cpuUsage(function(v){
console.log( 'CPU Usage (%): ' + v );
});
For information about the disk you can use diskspace
Check node-os-utils
CPU average usage
Free and used drive space
Free and used memory space
Operating System
All processes running
TTY/SSH opened
Total opened files
Network speed (input and output)
var osu = require('node-os-utils')
var cpu = osu.cpu
cpu.usage()
.then(info => {
console.log(info)
})
As I found no code to solve this problem and don't want to rely on other packages just for some lines of code, I wrote a function that calculates the average CPU load between two successive function calls. I am assuming t_idle + t_user + t_sys = total cpu time and results are kind of similar to the ones of my Windows task manager, however, the usage seems little more sensitive to me (e.g. music playback increases the cpu load more than in the Windows task manager). Please corret me if my assumptions are wrong.
const os = require('os');
// Initial value; wait at little amount of time before making a measurement.
let timesBefore = os.cpus().map(c => c.times);
// Call this function periodically e.g. using setInterval,
function getAverageUsage() {
let timesAfter = os.cpus().map(c => c.times);
let timeDeltas = timesAfter.map((t, i) => ({
user: t.user - timesBefore[i].user,
sys: t.sys - timesBefore[i].sys,
idle: t.idle - timesBefore[i].idle
}));
timesBefore = timesAfter;
return timeDeltas
.map(times => 1 - times.idle / (times.user + times.sys + times.idle))
.reduce((l1, l2) => l1 + l2) / timeDeltas.length;
}
You can also use process.cpuUsage() to return the system and user cpu time in microseconds. It can also calculate the difference to a previous call.
https://nodejs.org/api/process.html#process_process_cpuusage_previousvalue
Node.js has os.loadavg() method
// Require os module
const os = require('os');
// Printing os.loadavg() value
var avg_load = os.loadavg();
console.log("Load average (1 minute):"
+ String(avg_load[0]));
console.log("Load average (5 minute):"
+ String(avg_load[1]));
console.log("Load average (15 minute):"
+ String(avg_load[2]));
More info here
async function getinfo() {
const cpu = await si.cpu();
const disk = (await si.diskLayout())[0];
const os = await si.osInfo();
const versions = await si.versions();
const ram = await si.mem();
// CPU Info
let info = `CPU: ${cpu.manufacturer} ${cpu.brand} ${cpu.speed}GHz\n`;
info += `Cores: ${cpu.cores} (${cpu.physicalCores} Physical)\n`;
// RAM Info
const totalRam = Math.round(ram.total / 1024 / 1024 / 1024);
info += `RAM: ${totalRam}GB\n`;
// Disk Info
const size = Math.round(disk.size / 1024 / 1024 / 1024);
info += `Disk: ${disk.vendor} ${disk.name} ${size}GB ${disk.type} (${disk.interfaceType})\n`;
//OS Info
info += `OS: ${os.distro} ${os.codename} (${os.platform})\n`;
info += `Kernel: ${os.kernel} ${os.arch}\n`;
// Node Info
info += `Node: v${versions.node}\n`;
info += `V8: ${versions.v8}`;
return info;
}
Of course it is possible. But you'll need a C++ native module to do that. And keep in mind that every OS has their own way of querying system resource usage.
For example, if you're on Windows (which might be what you're looking for since usage doesn't support Windows), you could do something like
performance.cpp
#include <node.h>
#include "performance_algorithm.hpp"
using namespace v8;
void InitAll(Handle<Object> exports) {
PerformanceAlgorithm::Initialize();
PerformanceAlgorithm::RegisterMethod(exports);
}
NODE_MODULE(Performance, InitAll)
performance_algorithm.cpp
#include <algorithm>
#include "baton.hpp"
#include "structs.hpp"
#include "performance_algorithm.hpp"
void PerformanceAlgorithm::Initialize() {
PdhOpenQuery(NULL, NULL, &cpuQuery);
PdhAddCounter(cpuQuery, "\\Processor(_Total)\\% Processor Time", NULL, &cpuTotal);
PdhCollectQueryData(cpuQuery);
}
void PerformanceAlgorithm::RegisterMethod(Handle<Object> exports) {
NODE_SET_METHOD(exports, "getPerformanceData", PerformanceAlgorithm::GetPerformanceDataAsync);
}
void PerformanceAlgorithm::GetPerformanceDataAsync(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
if (args.Length() != 1) {
isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Wrong number of arguments")));
} else {
if (!args[0]->IsFunction()) {
isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "Wrong arguments type")));
} else {
Local<Function> callbackFunction = Local<Function>::Cast(args[0]);
Baton<string, PerformanceData>* baton = new Baton<string, PerformanceData>();
baton->request.data = baton;
baton->callbackFunction.Reset(isolate, callbackFunction);
uv_queue_work(uv_default_loop(), &baton->request, PerformanceAlgorithm::GetPerformanceDataWork, PerformanceAlgorithm::GetPerformanceDataAsyncAfter);
}
}
}
void PerformanceAlgorithm::GetPerformanceDataWork(uv_work_t* request) {
Baton<string, PerformanceData>* baton = static_cast<Baton<string, PerformanceData>*>(request->data);
baton->result.memory_info.dwLength = sizeof(MEMORYSTATUSEX);
GlobalMemoryStatusEx(&baton->result.memory_info);
PDH_FMT_COUNTERVALUE counterVal;
PdhCollectQueryData(cpuQuery);
PdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, NULL, &counterVal);
baton->result.cpu_usage = counterVal.doubleValue;
DWORD processIDs[1024], bytesReturned;
EnumProcesses(processIDs, sizeof(processIDs), &bytesReturned);
DWORD numberOfProcesses = bytesReturned / sizeof(DWORD);
for (int i = 0; i < numberOfProcesses; i++) {
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processIDs[i]);
HMODULE hMods[1024];
DWORD cbNeeded;
if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) {
for (int j = 0; j < (cbNeeded / sizeof(HMODULE)); j++) {
TCHAR szModName[MAX_PATH];
GetModuleFileNameEx(hProcess, hMods[j], szModName, sizeof(szModName) / sizeof(TCHAR));
ProcessInfo info;
info.process_id = processIDs[i];
info.path = string(szModName);
baton->result.processes.push_back(info);
break;
}
}
CloseHandle(hProcess);
}
sort(baton->result.processes.begin(), baton->result.processes.end(), [](ProcessInfo a, ProcessInfo b) -> bool {
return a.process_id < b.process_id;
});
GetPerformanceInfo(&baton->result.performance_info, sizeof(PERFORMACE_INFORMATION));
}
void PerformanceAlgorithm::GetPerformanceDataAsyncAfter(uv_work_t* request, int status) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
EscapableHandleScope escapableHandleScope(isolate);
Baton<string, PerformanceData>* baton = static_cast<Baton<string, PerformanceData>*>(request->data);
Local<Function> callbackFunction = Local<Function>::New(isolate, baton->callbackFunction);
Local<Object> returnValue = Object::New(isolate);
returnValue->Set(String::NewFromUtf8(isolate, "cpu_usage"), Number::New(isolate, baton->result.cpu_usage));
returnValue->Set(String::NewFromUtf8(isolate, "ram_usage"), Number::New(isolate, baton->result.memory_info.dwMemoryLoad));
returnValue->Set(String::NewFromUtf8(isolate, "total_physical_memory"), Number::New(isolate, baton->result.memory_info.ullTotalPhys));
returnValue->Set(String::NewFromUtf8(isolate, "available_physical_memory"), Number::New(isolate, baton->result.memory_info.ullAvailPhys));
returnValue->Set(String::NewFromUtf8(isolate, "total_page_file"), Number::New(isolate, baton->result.memory_info.ullTotalPageFile));
returnValue->Set(String::NewFromUtf8(isolate, "available_page_file"), Number::New(isolate, baton->result.memory_info.ullAvailPageFile));
returnValue->Set(String::NewFromUtf8(isolate, "total_virtual"), Number::New(isolate, baton->result.memory_info.ullTotalVirtual));
returnValue->Set(String::NewFromUtf8(isolate, "available_virtual"), Number::New(isolate, baton->result.memory_info.ullAvailVirtual));
Local<Array> processes = Array::New(isolate, baton->result.processes.size());
for (int i = 0; i < baton->result.processes.size(); i++) {
Local<Object> processInfo = Object::New(isolate);
processInfo->Set(String::NewFromUtf8(isolate, "process_id"), Number::New(isolate, baton->result.processes[i].process_id));
processInfo->Set(String::NewFromUtf8(isolate, "path"), String::NewFromUtf8(isolate, baton->result.processes[i].path.c_str()));
processes->Set(i, processInfo);
}
returnValue->Set(String::NewFromUtf8(isolate, "running_processes"), processes);
const unsigned int argc = 1;
Handle<Value> argv[argc] = { escapableHandleScope.Escape(returnValue) };
callbackFunction->Call(isolate->GetCurrentContext()->Global(), argc, argv);
baton->callbackFunction.Reset();
delete baton;
}
I am creating a DataFrame to hold a parsed haproxy http log files which has quite a few fields (25+).
If I add more than 20 vectors (one for each field), I get the compilation error:
no matching function call to 'create'
The create method:
return DataFrame::create(
_["clientIp"] = clientIp,
_["clientPort"] = clientPort,
_["acceptDate"] = acceptDate,
_["frontendName"] = frontendName,
_["backendName"] = backendName,
_["serverName"] = serverName,
_["tq"] = tq,
_["tw"] = tw,
_["tc"] = tc,
_["tr"] = tr,
_["tt"] = tt,
_["status_code"] = statusCode,
_["bytes_read"] = bytesRead,
#if CAPTURED_REQUEST_COOKIE_FIELD == 1
_["capturedRequestCookie"] = capturedRequestCookie,
#endif
#if CAPTURED_REQUEST_COOKIE_FIELD == 1
_["capturedResponseCookie"] = capturedResponseCookie,
#endif
_["terminationState"] = terminationState,
_["actconn"] = actconn,
_["feconn"] = feconn,
_["beconn"] = beconn,
_["srv_conn"] = srvConn,
_["retries"] = retries,
_["serverQueue"] = serverQueue,
_["backendQueue"] = backendQueue
);
Questions:
Have I hit a hard limit?
Is there a workaround to allow me to add more than 20 vectors to a data frame?
Yes, you have hit a hard limit -- Rcpp is limited by the C++98 standard, which requires explicit code bloat to support 'variadic' arguments. Essentially, a new overload must be generated for each create function used, and to avoid choking the compiler Rcpp just provides up to 20.
A workaround would be to use a 'builder' class, where you successively add elements, and then convert to DataFrame at the end. A simple example of such a class -- we create a ListBuilder object, for which we successively add new columns. Try running Rcpp::sourceCpp() with this file to see the output.
#include <Rcpp.h>
using namespace Rcpp;
class ListBuilder {
public:
ListBuilder() {};
~ListBuilder() {};
inline ListBuilder& add(std::string const& name, SEXP x) {
names.push_back(name);
// NOTE: we need to protect the SEXPs we pass in; there is
// probably a nicer way to handle this but ...
elements.push_back(PROTECT(x));
return *this;
}
inline operator List() const {
List result(elements.size());
for (size_t i = 0; i < elements.size(); ++i) {
result[i] = elements[i];
}
result.attr("names") = wrap(names);
UNPROTECT(elements.size());
return result;
}
inline operator DataFrame() const {
List result = static_cast<List>(*this);
result.attr("class") = "data.frame";
result.attr("row.names") = IntegerVector::create(NA_INTEGER, XLENGTH(elements[0]));
return result;
}
private:
std::vector<std::string> names;
std::vector<SEXP> elements;
ListBuilder(ListBuilder const&) {}; // not safe to copy
};
// [[Rcpp::export]]
DataFrame test_builder(SEXP x, SEXP y, SEXP z) {
return ListBuilder()
.add("foo", x)
.add("bar", y)
.add("baz", z);
}
/*** R
test_builder(1:5, letters[1:5], rnorm(5))
*/
PS: With Rcpp11, we have variadic functions and hence the limitations are removed.
The other common approach with Rcpp is to just use an outer list containing as many DataFrame objects (with each limited by the number of elements provided via the old-school macro expansion / repetition) in the corresponding header) as you need.
In (untested) code:
Rcpp::DataFrame a = Rcpp::DateFrame::create(/* ... */);
Rcpp::DataFrame b = Rcpp::DateFrame::create(/* ... */);
Rcpp::DataFrame c = Rcpp::DateFrame::create(/* ... */);
return Rcpp::List::create(Rcpp::Named("a") = a,
Rcpp::Named("b") = b,
Rcpp::Named("c") = c);
Using the Haxe programming language, is there any cross-platform way to read a PNG image, and get the pixel data from the image?
I have a file called stuff.png, and I want to obtain an array of RGB values from the image (as an integer array).
Here's an example usage of the Haxe format library to read a PNG file. You need -lib format in your compiler args / build.hxml:
function readPixels(file:String):{data:Bytes, width:Int, height:Int} {
var handle = sys.io.File.read(file, true);
var d = new format.png.Reader(handle).read();
var hdr = format.png.Tools.getHeader(d);
var ret = {
data:format.png.Tools.extract32(d),
width:hdr.width,
height:hdr.height
};
handle.close();
return ret;
}
Here's an example of how to get ARGB pixel data from the above:
public static function main() {
if (Sys.args().length == 0) {
trace('usage: PNGReader <filename>');
Sys.exit(1);
}
var filename = Sys.args()[0];
var pixels = readPixels(filename);
for (y in 0...pixels.height) {
for (x in 0...pixels.width) {
var p = pixels.data.getInt32(4*(x+y*pixels.width));
// ARGB, each 0-255
var a:Int = p>>>24;
var r:Int = (p>>>16)&0xff;
var g:Int = (p>>>8)&0xff;
var b:Int = (p)&0xff;
// Or, AARRGGBB in hex:
var hex:String = StringTools.hex(p,8);
trace('${ x },${ y }: ${ a },${ r },${ g },${ b } - ${ StringTools.hex(p,8) }');
}
}
You can always access the pixel data with BitmapData.getPixels/BitmapData.setPixels.
If you are using haXe NME, you can use Assets.getBitmapData() to load an asset image file.
If you want to load images from network, then you can use Loader class, it can asynchronous loading remote images, but in flash please mind the cross-domain issue.
For more generic ByteArray -> BitmapData conversion, use following code:
var ldr = new Loader();
ldr.loadBytes(cast(byteArray)); // bytearray contains raw image data
var dp: DisplayObject = ldr.content; // actually ontent should be of Bitmap class
var bitmapData = new BitmapData(Std.int(dp.width), Std.int(dp.height), true, 0);
bitmapData.draw(dp);