Cropping an image in flutter - flutter

So I've been trying really hard to crop an image according to my needs in flutter.
Problem statement:
I have a screen and in that screen I show a frame while the device camera is run on the background. Now, what I want is that whenever the user clicks a photo, only the area of that image inside the frame should be kept and rest should be cropped.
What I have done so far?
Added a package image 3.1.3
Wrote code to fetch x,y coordinates of my frame.
Using the calculated x,y coordinates and copyCrop method from the Image package to crop the clicked image.
Now the problem is that I do not know how copyCrop works and the code right now does not give me the expected results.
final GlobalKey _key = GlobalKey();
void _getOffset(GlobalKey key) {
RenderBox? box = key.currentContext?.findRenderObject() as RenderBox?;
Offset? position = box?.localToGlobal(Offset.zero);
if (position != null) {
setState(() {
_x = position.dx;
_y = position.dy;
});
}
}
I assign this _key to my Image.file(srcToFrameImage) and the function above yields 10, 289.125
Here 10 is the offset from x and 289.125 is the offset from y. I used this tutorial for the same.
Code to crop my image using the Image package:
var bytes = await File(pictureFile!.path).readAsBytes();
img.Image src = img.decodeImage(bytes)!;
img.Image destImage = img.copyCrop(
src, _x!.toInt(), _y!.toInt(), src.width, src.height);
var jpg = img.encodeJpg(destImage);
await File(pictureFile!.path).writeAsBytes(jpg);
bloc.addFrontImage(File(pictureFile!.path));
Now, can anyone tell me how i can do this effectively? Right now, it does crop my image but not as I want it to be. It would be really great if someone could tell me how does copyCrop work and what is the meaning of all these different parameters that we pass into it.
Any help would be appreciated.
Edit:
Now, as you can see, i only want the image between this frame to be kept after being captured and rest to be cropped off.

Related

Vertical lines between tiles when camera is moving

I'm trying to build a simple side-scroller game with a level built of square tiles using Flame.
#override
Future<void> onLoad() async {
final orange = Paint()..color = Color(0xFFFF9000);
final double tileSize = 64;
for (var i = 0; i <= 100; i++) {
add(RectangleComponent(position: Vector2(i * tileSize, 100), size: Vector2.all(tileSize), paint: orange));
}
}
When the screen is static, everything works as expected. However, when I add camera movement, I see vertical lines between the tiles.
#override
void update(double dt) {
camera.moveTo((Vector2(camera.position.x + 1, 0)));
super.update(dt);
}
I suspect it might be something to do with Flutter antialiasing bug. Does anybody know if there's a workaround? Thanks!
This is indeed that bug, we have it documented on a few of our issues too (like this one for example https://github.com/flame-engine/flame/issues/1888)
You can try to use Impeller if that is an option for you, where this bug shouldn't be present.
Other workarounds would be to draw the same color underneath the tiles where they are overlapping, that is of course not always possible though.
And the other option is to use a camera that only moves in full pixels, so that there are no rounding errors.

Flutter is this possible canvas color is transparent but picture recorder image background is another?

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?

Flutter - How to map mouse position/coordinates when zooming in

I have a project that uses the "flutter_painter" library to draw on top of an image, the problem is that when I zoom in on the image, the coordinates are still from the original image and not with the zoom applied, I need to map these coordinates to draw under the zoomed image, and when you unzoom it stays in the drawn location.
I use the "onSecondaryTapUp: (details){}" from the "GestureDetector" widget around the "Flutter_Painter" library to get the click position on the image.
try transformationController.toScene(update.localPosition);
_onDragUpdate(BuildContext context, DragUpdateDetails update) {
RenderBox getBox = context.findRenderObject() as RenderBox;
var local = getBox.globalToLocal(update.globalPosition);
final Offset scenePoint = transformationController.toScene(update.localPosition);
print("Update Point");
debugPrint("local: $local");
debugPrint("scenePoint: $scenePoint");
}

Flutter Google maps marker - create custom shapes and convert to uintlist

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);
}

Phone saves only the top left corner of the image - ActionScript3

I am trying to save an image to my phone's camera Roll using Action Script 3. The image saves fine on tablet devices. However, when I save the image to my phone, it saves only the top-left corner of the image.
Here is my code,
var media:DisplayItem;
public function SaveAsBitmap():void
{
var cameraRoll:CameraRoll = new CameraRoll();
cameraRoll.addBitmapData(this.GetAsBitmapData());
}
public function GetAsBitmapData():BitmapData
{
var bmpData:BitmapData = new BitmapData(this.width,this.height, false, 0x000000);
this.media.DrawToBitmap(bmpData);
return bmpData;
}
How do I save an image which is larger than the display area of my phone?
Any help appreciated.
In this line:
var bmpData:BitmapData = new BitmapData(this.width,this.height, false, 0x000000);
Check the value of these variables: 'this.width' and 'this.height', probably it's not the right dimensions as you want.
To check the user screen resolution, you can try:
// remember to import
import flash.system.Capabilities;
trace('Capabilities.screenResolutionX: ', Capabilities.screenResolutionX);
trace('Capabilities.screenResolutionY: ', Capabilities.screenResolutionY);
I also saw something on your code, I cannot see all scope, but try to do something:
public function GetAsBitmapData():BitmapData
{
// you can replace this.width and this.height to Capabilities.screenResolutionX/Capabilities.screenResolutionY
var bmpData:BitmapData = new BitmapData(this.width,this.height, false, 0x000000);
bmpData.draw(this.media); // be sure that this.media is IBitmapDrawable
return bmpData;
}
As the other poster stated, the problem is in the following line:
var bmpData:BitmapData = new BitmapData(this.width,this.height, false, 0x000000);
this.width and this.height are returning to you the 'size' of the device screen. What you need to put in in place of those items are the actual width and height of the image you want to load from the camera roll.