I'm working on a flutter app that is using the Camera package's camera preview.
I'm initializing the camera controller like so:
final controller = CameraController(
_cameras[0],
ResolutionPreset.ultraHigh,
enableAudio: false,
imageFormatGroup: ImageFormatGroup.bgra8888,
);
The ResolutionPreset enum has these options:
enum ResolutionPreset {
/// 352x288 on iOS, 240p (320x240) on Android
low,
/// 480p (640x480 on iOS, 720x480 on Android)
medium,
/// 720p (1280x720)
high,
/// 1080p (1920x1080)
veryHigh,
/// 2160p (3840x2160)
ultraHigh,
/// The highest resolution available.
max,
}
The resolution needs to be 4032x2034. How do I use a custom resolution?
ResolutionPreset enum doesn't provide the option to set a custom resolution. As a workaround, you can use ResolutionPreset.max then resize the image. Using the image package, you can resize the image to the desired width and height and write it on storage.
// Read a jpeg image from file path
Image image = decodeImage(File('image path').readAsBytesSync());
// Resize the image
Image resizedImage = copyResize(image, width: 4032, height: 2034);
// Save the image as jpg
File('out/image-resized.jpg')
..writeAsBytesSync(encodeJpg(resizedImage, quality: 100));
Related
Currently, I'm using this package to draw some images. And I'm saving this image. I reviewed package classes and functions and tried many solution to achieve my aim. But I haven't found any solution yet. Maybe I'm trying to do impossible thing so I want to ask this: Can we draw a transparent canvas then our output image background can be another color?
Here's some code snippet:
canvas = Canvas(
recorder,
Rect.fromPoints(Offset.zero, Offset(size.width, size.height)),
);
paint.blendMode = mode;
ui.Image src = await picture.toImage(size.width.toInt(), size.height.toInt());
paint.isAntiAlias = true;
canvas.drawImage(src, Offset.zero, paint);
picture = recorder.endRecording();
ui.Image img = await picture.toImage(size.width.toInt(), size.height.toInt());
ByteData? imgBytes =
await img.toByteData(format: ui.ImageByteFormat.rawStraightRgba);
In above code snippet, we create a canvas and drawImage then we get the image bytes. But in this case, this image's background is transparent. But I want set red color. So when I
add
canvas.drawColor(Colors.red, BlendMode.src);
My image can be created as I want, but this time I see a red canvas in my view. But I want a transparent canvas when I draw it. I only want to see output image's background is red.
Is this possible?
I am trying to create custom dynamic markers (changes on tap) for my google maps project. Each marker shows a shop with some promotion going on. A single shop can have 3 promotions displayed at the same time and it is supposed to be highlighted if tapped on
I have tried to convert the SVGs for the markers in Canvas code using online tools, but it's bulky and I don't understand it well.
Here's the screenshot for an example screen
Here's the code written for converting theses SVGs to image byte data for use as marker icons
static Future<ByteData?> marker({double? width}) async {
width ??= 88;
double height = width * 1.2247191011235956;
final recorder = ui.PictureRecorder();
final canvas = Canvas(recorder,
Rect.fromPoints(const Offset(0.0, 0.0), const Offset(200.0, 200.0)));
Size size = Size(width, (width * 1.2247191011235956).toDouble());
_paintMarker(size: size, canvas: canvas);
final picture = recorder.endRecording();
final img = await picture.toImage((width).toInt(), height.toInt());
return await img.toByteData(format: ui.ImageByteFormat.png);
}
I'm using the version 1 release of Flame, and adding a parallax background which works great.
// load background layers
final layers = _layersMeta.entries.map(
(e) => loadParallaxLayer(
ParallaxImageData(e.key),
velocityMultiplier: Vector2(e.value.toDouble(), 1.0),
alignment: Alignment.center,
fill: LayerFill.none ,
),
);
// create background parallax
parallax = ParallaxComponent(
parallax: Parallax(
await Future.wait(layers),
baseVelocity: Vector2(20, 0),
),
);
add(parallax);
Once I set the camera to follow a Sprite camera.followVector2(player.position); then its obvious that the parallax was initialized to the size of the screen because as the camera moves, the edges of the parallax become visible with a black game world background. I've tried changing the size of the ParallaxComponent and the Parallax to no avail.
Changing the canvas size doesn't do much either onGameResize(Vector2(camera.canvasSize.x, 5000));
Is there a standard way to set a component fill the world size? The source code talks about the world size, but I don't see any way to control it.
The ParallaxComponent is a PositionComponent which lives in the world that the camera is viewing by default. If you want a PositionComponent to be relative to the viewport (or the GameWidget) you have to change its positionType to PositionType.viewport.
So in this case the initialization of your ParallaxComponent could look like this to make it ignore the camera:
// create background parallax
parallax = ParallaxComponent(
parallax: Parallax(
await Future.wait(layers),
baseVelocity: Vector2(20, 0),
),
)..positionType = PositionType.viewport;
On my iOS device, I'm accessing the camera through a CameraController (provided by the camera package) with controller.startImageStream((CameraImage img) {...}
The data coming out of the camera is in a bgra8888 format on my phone, but I've read that it's in yuv420 on android devices. To convert the image stream data to a usable, consistent format, I'm using:
import 'dart:typed_data';
import 'package:camera/camera.dart';
import 'package:image/image.dart' as im;
Uint8List concatenatePlanes(List<Plane> planes) {
final WriteBuffer allBytes = WriteBuffer();
planes.forEach((Plane plane) => allBytes.putUint8List(plane.bytes));
return allBytes.done().buffer.asUint8List();
}
List<CameraDescription> cameras = await availableCameras();
CameraController controller = CameraController(cameras[0], ResolutionPreset.medium);
controller.startImageStream((CameraImage img) {
print(img.format.group); // returns ImageFormatGroup.bgra8888
List<int> imgData = concatenatePlanes(img.planes);
im.Image image = im.decodeImage(imgData);
});
The imgData variable is full of data streaming off the camera, but the converted image returned from decodeImage is null.
I had read on other posts that the image package would be up to the task of decoding bgra8888/yuv420 images (https://stackoverflow.com/a/57635827/479947) but I'm not seeing support in its formats.dart source (https://github.com/brendan-duncan/image/blob/master/lib/src/formats/formats.dart).
The target Image format is defined as:
An image buffer where pixels are encoded into 32-bit unsigned ints
(Uint32). Pixels are stored in 32-bit unsigned integers in #AARRGGBB
format. This is to be consistent with the Flutter image data.
How would I get my image stream image in bgra8888/yuv420 converted into the desired Image format?
Have you check this? convertImage
If you convert from bgra8888 to Image, it's kinda fast but yuv420 to Image take much more time, so if you have problem about performance, I can help a little bit with my experience. By the way, if you have performance problem and trying using Isolate, u will meet the memory issue.
My ionic appp is to take pictures of business cards. as 99% of the business cards are landscape style so users tries to change the camera orientation to landscape mode as well. This is a natural behavior.
However, i want to avoid that and one way is to show a rectangle while camera is open (width equal to screen width and a 3:2 aspect ratio for height)
This will make life easy as users wont try to change the camera orientation.
I was looking into camera plugin which uses code like
this.camera.getPicture({
destinationType: this.camera.DestinationType.DATA_URL,
quality: 25,
correctOrientation: true,
allowEdit:false,
sourceType: this.camera.PictureSourceType.SAVEDPHOTOALBUM
}).then(async(imageData) => {
//console.log("image data is:" + imageData)
// imageData is a base64 encoded string
var base64Image = "data:image/jpeg;base64," + imageData;
I was trying targetWidth and height but that does not draw that box like i have seen in many other apps.
there are other plugins like cropperJs but seems they let u crop the image after taken which not what i need.
Use camera-preview-plugin instead of camera for that :
const cameraPreviewOpts: CameraPreviewOptions = {
x: 0,
y: 0,
width: window.screen.width,
height: window.screen.height,
camera: 'rear',
tapPhoto: true,
previewDrag: true,
toBack: true,
alpha: 1
}
Ionic Camera Preview