dotnetdreamer/nativescript-http-formdata

How to use android.graphics.Bitmap in JavaScript

andresilva-cc opened this issue · 2 comments

I'm not using TypeScript and I'm trying to follow the example in README, but I have a problem with this specific line:

let bitmapImage: android.graphics.Bitmap = image;

I can't use types, so I tried refactoring this line in several ways, but they all fail:

// Assigning it like this won't work because bitmapImage will not have method compress used later
const bitmapImage = image;
// Error: Cannot convert object to Ljava/lang/String; at index 0

// Using like a method
const bitmapImage = android.graphics.Bitmap(image);
// Error: Trying to link invalid 'this' to a Java object

// Using new keyword
const bitmapImage = new android.graphics.Bitmap(image);
// Error: Cannot marshal JavaScript argument Image(96) at index 0 to Java type.

// Tried using BitmapFactory
const bitmapImage = android.graphics.BitmapFactory.decodeFile(image.src);
// Error: Cannot convert object to Ljava/lang/String; at index 0

Valid to mention that I'm not using gallery picker, but nativescript-camera, my complete code is like this:

import { Image } from 'tns-core-modules/ui/image';

const imageAsset = await camera.takePicture({
  saveToGallery: true,
  cameraFacing: 'front',
});
const image = new Image();
image.src = imageAsset;

let imageData;

if (isAndroid) {
  const bitmapImage = new android.graphics.Bitmap(image);
  const stream = new java.io.ByteArrayOutputStream();
  bitmapImage.compress(android.graphics.Bitmap.CompressFormat.PNG, 100, stream);
  const byteArray = stream.toByteArray();
  bitmapImage.recycle();
  imageData = byteArray;
} else {
  imageData = UIImagePNGRepresentation(image);
}

This is something related to NS and not the plugin itself. You will need to check that by your own as I havn't tried it in JavaScript. One thing you can do is, let the plugin compile to JS and check the demo project. After that you can check the compiled JS code and see how its done.

For anyone wondering how to make it work with JavaScript, I discovered. I'm using ImageSource module from NativeScript, which encapsulates the common abstraction behind the native Bitmap. I use the module to read the image from the File System, then I get the platform-specific object, and then I can continue the code as per the README. Check it out:

import { ImageSource } from 'tns-core-modules/image-source';

// I'm using nativescript-camera, but it could be anything
const imageAsset = await camera.takePicture({
  saveToGallery: true,
  cameraFacing: 'front',
});

// Use ImageSource fromFileSync to read the image from a given source
const image = ImageSource.fromFileSync(imageAsset.android);

let imageData;

if (image.ios) {
  imageData = UIImagePNGRepresentation(image);
} else {
  // The only change is here, instead of using android.graphics.Bitmap, I simple set bitmapImage to
  // image.android, which is the native image object (in this case, android.graphics.Bitmap)
  const bitmapImage = image.android;
  const stream = new java.io.ByteArrayOutputStream();
  bitmapImage.compress(android.graphics.Bitmap.CompressFormat.PNG, 100, stream);
  const byteArray = stream.toByteArray();
  bitmapImage.recycle();
  imageData = byteArray;
}

const data = [{
  data: imageData,
  contentType: 'image/png',
  fileName: 'test.png',
  parameterName: 'avatar',
}];