Flutter - How to draw an Image on Canvas using DrawImage method - android

I'm trying to draw an image file into the canvas to compose my widget in Flutter.
I did follow canvas documentation but a did not success. O Image docs, thay say that:
To obtain an Image object, use instantiateImageCodec.
I did try use instantiateImageCodec method, but i just get a Codec instance, not a Image
How is the right way to get an instance of ui.Image to draw on canvas using canvas.drawImage
Here is a snnipet of my code:
Future<ui.Codec> _loadImage(AssetBundleImageKey key) async {
final ByteData data = await key.bundle.load(key.name);
if (data == null)
throw 'Unable to read data';
return await ui.instantiateImageCodec(data.buffer.asUint8List());
}
final Paint paint = new Paint()
..color = Colors.yellow
..strokeWidth = 2.0
..strokeCap = StrokeCap.butt
..style = PaintingStyle.stroke;
var sunImage = new ExactAssetImage("res/images/grid_icon.png");
sunImage.obtainKey(new ImageConfiguration()).then((AssetBundleImageKey key){
_loadImage(key).then((ui.Codec codec){
print("frameCount: ${codec.frameCount.toString()}");
codec.getNextFrame().then((info){
print("image: ${info.image.toString()}");
print("duration: ${info.duration.toString()}");
canvas.drawImage(info.image, size.center(Offset.zero), paint);
});
});
});

This simple utility method returns a Future<UI.Image> given the image asset's path:
import 'dart:async';
import 'dart:typed_data';
import 'dart:ui' as UI;
import 'package:flutter/services.dart';
Future<UI.Image> loadUiImage(String imageAssetPath) async {
final ByteData data = await rootBundle.load(imageAssetPath);
final Completer<UI.Image> completer = Completer();
UI.decodeImageFromList(Uint8List.view(data.buffer), (UI.Image img) {
return completer.complete(img);
});
return completer.future;
}

ui.Codec has a method getNextFrame() which returns a Future<FrameInfo> (you should probably have logic around how many frames but if you know it's always a normal picture you could skip that.) FrameInfo has an image property which is the Image you need.
EDIT: looking at the code you have in the post, it's not clear where you're doing what. Is that all defined within the CustomPainter.paint method? If so, you'd definitely have issues because you can only use the canvas for the duration of the paint call; you should not retain any references to it outside of the function (which would include any asynchronous call).
I'd recommend using a FutureBuilder so that you only draw on the canvas once you've added the image.
That would look something like this:
Future<Image> _loadImage(AssetBundleImageKey key) async {
final ByteData data = await key.bundle.load(key.name);
if (data == null)
throw 'Unable to read data';
var codec = await ui.instantiateImageCodec(data.buffer.asUint8List());
// add additional checking for number of frames etc here
var frame = await codec.getNextFrame();
return frame.image;
}
new FutureBuilder<Image>(
future: loadImage(....), // a Future<String> or null
builder: (BuildContext context, AsyncSnapshot<Image> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting: return new Text('Image loading...');
default:
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
else
// ImageCanvasDrawer would be a (most likely) statless widget
// that actually makes the CustomPaint etc
return new ImageCanvasDrawer(image: snapshot.data)
}
},
)

Simple example, based on idea from Simon
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
Future<ui.Image> loadImage(String imageName) async {
final data = await rootBundle.load('assets/image/$imageName');
return decodeImageFromList(data.buffer.asUint8List());
}
late ui.Image image;
void main() async {
image = await loadImage('image.jpg');
runApp(App());
}
// canvas.drawImage(image, Offset.zero, Paint());

class ImagePainter extends CustomPainter {
List<ui.Image> images = new List<ui.Image>();
ImagePainter(
{Key key,
#required this.noOfSlice,
#required this.images,
#required this.rotation,
this.boxfit = BoxFit.contain})
:
// : path = new Path()
// ..addOval(new Rect.fromCircle(
// center: new Offset(75.0, 75.0),
// radius: 40.0,
// )),
tickPaint = new Paint() {
tickPaint.strokeWidth = 2.5;
}
final int noOfSlice;
final tickPaint;
final BoxFit boxfit;
ui.ImageByteFormat img;
ui.Rect rect, inputSubrect, outputSubrect;
Size imageSize;
FittedSizes sizes;
double radius,
rotation = 0.0,
_x,
_y,
_angle,
_radiun,
_baseLength,
_imageCircleradius,
_incircleRadius,
_imageOffset = 0.0,
_imageSizeConst = 0.0;
#override
void paint(ui.Canvas canvas, ui.Size size) {
print("image data:: $images");
radius = size.width / 2;
_angle = 360 / (noOfSlice * 2.0);
_radiun = (_angle * pi) / 180;
_baseLength = 2 * radius * sin(_radiun);
_incircleRadius = (_baseLength / 2) * tan(_radiun);
if (noOfSlice == 4) {
_imageOffset = 30.0;
_imageSizeConst = 30.0;
_x = 8.60;
_y = 4.10;
} else if (noOfSlice == 6) {
_imageOffset = 20.0;
_x = 10.60;
_y = 5.60;
} else if (noOfSlice == 8) {
_imageOffset = 40.0;
_imageSizeConst = 30.0;
_x = 12.90;
_y = 6.60;
}
//print("circle radisu:: $_incircleRadius");
canvas.save();
canvas.translate(size.width / 2, size.height / 2);
canvas.rotate(-rotation);
int incr = 0;
rect = ui.Offset((size.width / _x), size.width / _y) & new Size(0.0, 0.0);
imageSize = new Size(size.width * 1.5, size.width * 1.5);
sizes = applyBoxFit(
boxfit,
imageSize,
new Size(size.width / 2 * .50 + _incircleRadius * .8,
size.width / 2 * .50 + _incircleRadius * .8));
inputSubrect =
Alignment.center.inscribe(sizes.source, Offset.zero & imageSize);
outputSubrect = Alignment.center.inscribe(sizes.destination, rect);
if (images.length == noOfSlice && images.isNotEmpty)
for (var i = 1; i <= noOfSlice * 2; ++i) {
if (i % 2 != 0) {
canvas.drawLine(
new Offset(0.0, 0.0),
new Offset(0.0, size.width / 2 - 4.2),
tickPaint,
);
} else {
canvas.save();
canvas.translate(-0.0, -((size.width) / 2.2));
ui.Image image = images[incr];
if (image != null) {
canvas.drawImageRect(
image, inputSubrect, outputSubrect, new Paint());
}
canvas.restore();
incr++;
}
canvas.rotate(2 * pi / (noOfSlice * 2.0));
}
canvas.restore();
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}

Related

did some one know how can i crop face after recognize it using google_mlkit on flutter?

hello i have problem im working in a preoject that recognize face from gallery image and crop the face to return cropped face as new image
i read all questions in stackoverflow but the results very old its not working with the new version of flutter , and google_mlkit
Future<File> cropImageToFace(File image) async {
final path = image.path; final FaceDetector _faceDetector =
FaceDetector( options: FaceDetectorOptions(
enableContours: true, ));
final imageBytes = await image.readAsBytes();
final imageList = <int>[];
imageList.addAll(imageBytes);
final imageData = InputImage.fromFile(image);
print(imageData.filePath);
print(imageData.inputImageData!.size);
final faces = await _faceDetector.processImage(imageData);
if (faces.isNotEmpty) {
final face = faces.first;
final faceRect = face.boundingBox;
final cropRect = Rect.fromLTRB(
faceRect.left - (224 - faceRect.width) / 2,
faceRect.top - (224 - faceRect.height) / 2,
faceRect.left + (224 + faceRect.width) / 2,
faceRect.top + (224 + faceRect.height) / 2);
final croppedFile = await ImageCropper().cropImage(
sourcePath: image.path,
cropStyle: CropStyle.rectangle,
aspectRatio: CropAspectRatio(ratioX: 1, ratioY: 1),
compressQuality: 100,
androidUiSettings: AndroidUiSettings(
toolbarColor: Colors.deepOrange,
toolbarWidgetColor: Colors.white,
toolbarTitle: 'Crop It'),
iosUiSettings: IOSUiSettings(
minimumAspectRatio: 1.0, aspectRatioLockEnabled: true));
return croppedFile!;
} else {
throw Exception('No face found in the image');
}
}

Is there a way to put label text vertically in flutter charts_flutter: ^0.8.1

I am trying to create a graph using charts_flutter: ^0.8.1 package in flutter.
Here is my code. I have added SlidingViewport and PanAndZoomBehavior in behaviour.
charts.BarChart(
generateGraphData(months),
barRendererDecorator: charts.BarLabelDecorator<String>(
labelAnchor: charts.BarLabelAnchor.middle,
labelPosition: charts.BarLabelPosition.inside, ),
domainAxis: new charts.OrdinalAxisSpec(viewport: new charts.OrdinalViewport('month', 5),),
animate: false,
rtlSpec: charts.RTLSpec(axisDirection: charts.AxisDirection.reversed),
defaultInteractions: false,
behaviors: [
new charts.SlidingViewport(),
new charts.PanAndZoomBehavior(),
],
),
Is it possible to make the labeltext align vertically like in Horizontal Bar Label Bar? Some thing like the below image. I want to align the label text in the direction of bar chart.
To achieve it you need to create a new class where you need to overwrite one of the internal classes - 'BarRendererDecorator'. In that class there is a method - _decorateVerticalBars which writes the value inside the bars. There is a method call - canvas.drawText() which needs to be fed with one new argument rotation:-math.pi/2. Also to center the text inside the bar need to change the X offset like this - labelX = labelX + (labelElement.measurement.horizontalSliceWidth / 2.5).round();
And then in your decorator call in your graph use the new class you have created. Here is the complete code of the new class. And accept it as answer if it works for you.
import 'dart:math' as math;
import 'package:meta/meta.dart' show required;
import "package:charts_common/common.dart"
show
Color,
GraphicsFactory,
TextDirection,
TextElement,
TextStyle,
ChartCanvas,
TextStyleSpec,
ImmutableBarRendererElement,
BarRendererDecorator;
import "package:charts_common/src/data/series.dart" show AccessorFn;
import "chart_canvas_wrkaround.dart";
import "package:charts_flutter/src/chart_canvas.dart" as Canvasee;
import "package:charts_common/common.dart" as comm;
/* import '../../common/color.dart' show Color;
import '../../common/graphics_factory.dart' show GraphicsFactory;
import '../../common/text_element.dart' show TextDirection, TextElement;
import '../../common/text_style.dart' show TextStyle;
import '../../data/series.dart' show AccessorFn;
import '../cartesian/axis/spec/axis_spec.dart' show TextStyleSpec;
import '../common/chart_canvas.dart' show ChartCanvas;
import 'bar_renderer.dart' show ImmutableBarRendererElement;
import 'bar_renderer_decorator.dart' show BarRendererDecorator; */
class BarLabelDecoratorWorkAround<D> extends BarRendererDecorator<D> {
// Default configuration
static const _defaultLabelPosition = BarLabelPosition.auto;
static const _defaultLabelPadding = 5;
static const _defaultHorizontalLabelAnchor = BarLabelAnchor.start;
static const _defaultVerticalLabelAnchor = BarLabelAnchor.end;
static final _defaultInsideLabelStyle =
new TextStyleSpec(fontSize: 12, color: Color.white);
static final _defaultOutsideLabelStyle =
new TextStyleSpec(fontSize: 12, color: Color.black);
static final _labelSplitPattern = '\n';
static final _defaultMultiLineLabelPadding = 2;
/// Configures [TextStyleSpec] for labels placed inside the bars.
final TextStyleSpec insideLabelStyleSpec;
/// Configures [TextStyleSpec] for labels placed outside the bars.
final TextStyleSpec outsideLabelStyleSpec;
/// Configures where to place the label relative to the bars.
final BarLabelPosition labelPosition;
/// For labels drawn inside the bar, configures label anchor position.
final BarLabelAnchor labelAnchor;
/// Space before and after the label text.
final int labelPadding;
BarLabelDecoratorWorkAround(
{TextStyleSpec insideLabelStyleSpec,
TextStyleSpec outsideLabelStyleSpec,
this.labelAnchor = null,
this.labelPosition = _defaultLabelPosition,
this.labelPadding = _defaultLabelPadding})
: insideLabelStyleSpec = insideLabelStyleSpec ?? _defaultInsideLabelStyle,
outsideLabelStyleSpec =
outsideLabelStyleSpec ?? _defaultOutsideLabelStyle;
#override
void decorate(Iterable<ImmutableBarRendererElement<D>> barElements,
comm.ChartCanvas canvas, GraphicsFactory graphicsFactory,
{#required math.Rectangle drawBounds,
#required double animationPercent,
#required bool renderingVertically,
bool rtl = false}) {
// Only decorate the bars when animation is at 100%.
if (animationPercent != 1.0) {
return;
}
/* final newCanvas = canvas as Canvasee.ChartCanvas;
final canvee =
ChartCanvasWorkAround(newCanvas.canvas, newCanvas.graphicsFactory); */
if (renderingVertically) {
_decorateVerticalBars(
barElements, canvas, graphicsFactory, drawBounds, rtl);
} else {
_decorateHorizontalBars(
barElements, canvas, graphicsFactory, drawBounds, rtl);
}
}
void _decorateVerticalBars(
Iterable<ImmutableBarRendererElement<D>> barElements,
ChartCanvas canvas,
GraphicsFactory graphicsFactory,
math.Rectangle drawBounds,
bool rtl) {
// Create [TextStyle] from [TextStyleSpec] to be used by all the elements.
// The [GraphicsFactory] is needed so it can't be created earlier.
final insideLabelStyle =
_getTextStyle(graphicsFactory, insideLabelStyleSpec);
final outsideLabelStyle =
_getTextStyle(graphicsFactory, outsideLabelStyleSpec);
for (var element in barElements) {
final labelFn = element.series.labelAccessorFn;
final datumIndex = element.index;
final label = (labelFn != null) ? labelFn(datumIndex) : null;
// If there are custom styles, use that instead of the default or the
// style defined for the entire decorator.
final datumInsideLabelStyle = _getDatumStyle(
element.series.insideLabelStyleAccessorFn,
datumIndex,
graphicsFactory,
defaultStyle: insideLabelStyle);
final datumOutsideLabelStyle = _getDatumStyle(
element.series.outsideLabelStyleAccessorFn,
datumIndex,
graphicsFactory,
defaultStyle: outsideLabelStyle);
// Skip calculation and drawing for this element if no label.
if (label == null || label.isEmpty) {
continue;
}
var labelElements = label
.split(_labelSplitPattern)
.map((labelPart) => graphicsFactory.createTextElement(labelPart));
final bounds = element.bounds;
// Get space available inside and outside the bar.
final totalPadding = labelPadding * 2;
final insideBarHeight = bounds.height - totalPadding;
final outsideBarHeight = drawBounds.height - bounds.height - totalPadding;
var calculatedLabelPosition = labelPosition;
if (calculatedLabelPosition == BarLabelPosition.auto) {
// For auto, first try to fit the text inside the bar.
labelElements = labelElements.map(
(labelElement) => labelElement..textStyle = datumInsideLabelStyle);
final labelMaxWidth = labelElements
.map(
(labelElement) => labelElement.measurement.horizontalSliceWidth)
.fold(0, (max, current) => max > current ? max : current);
// Total label height depends on the label element's text style.
final totalLabelHeight = _getTotalLabelHeight(labelElements);
// A label fits if the length and width of the text fits.
calculatedLabelPosition =
totalLabelHeight < insideBarHeight && labelMaxWidth < bounds.width
? BarLabelPosition.inside
: BarLabelPosition.outside;
}
// Set the max width, text style, and text direction.
labelElements = labelElements.map((labelElement) => labelElement
..textStyle = calculatedLabelPosition == BarLabelPosition.inside
? datumInsideLabelStyle
: datumOutsideLabelStyle
..maxWidth = bounds.height * 100
..textDirection = rtl ? TextDirection.rtl : TextDirection.ltr);
// Total label height depends on the label element's text style.
final totalLabelHeight = _getTotalLabelHeight(labelElements);
var labelsDrawn = 0;
for (var labelElement in labelElements) {
// Calculate the start position of label based on [labelAnchor].
int labelY;
final labelHeight = labelElement.measurement.verticalSliceWidth.round();
final offsetHeight =
(labelHeight + _defaultMultiLineLabelPadding) * labelsDrawn;
if (calculatedLabelPosition == BarLabelPosition.inside) {
final _labelAnchor = labelAnchor ?? _defaultVerticalLabelAnchor;
switch (_labelAnchor) {
case BarLabelAnchor.end:
labelY = bounds.top + labelPadding + offsetHeight;
break;
case BarLabelAnchor.middle:
labelY = (bounds.bottom -
bounds.height / 2 -
totalLabelHeight / 2 +
offsetHeight)
.round();
break;
case BarLabelAnchor.start:
labelY = bounds.bottom -
labelPadding -
totalLabelHeight +
offsetHeight;
break;
}
} else {
// calculatedLabelPosition == LabelPosition.outside
labelY = bounds.top - labelPadding - totalLabelHeight + offsetHeight;
}
// Center the label inside the bar.
int labelX = (bounds.left +
bounds.width / 2 -
labelElement.measurement.horizontalSliceWidth / 2)
.round();
labelX = labelX +
(labelElement.measurement.horizontalSliceWidth / 2.5).round();
canvas.drawText(labelElement, labelX, labelY, rotation: -math.pi / 2);
labelsDrawn += 1;
}
}
}
void _decorateHorizontalBars(
Iterable<ImmutableBarRendererElement<D>> barElements,
ChartCanvas canvas,
GraphicsFactory graphicsFactory,
math.Rectangle drawBounds,
bool rtl) {
// Create [TextStyle] from [TextStyleSpec] to be used by all the elements.
// The [GraphicsFactory] is needed so it can't be created earlier.
final insideLabelStyle =
_getTextStyle(graphicsFactory, insideLabelStyleSpec);
final outsideLabelStyle =
_getTextStyle(graphicsFactory, outsideLabelStyleSpec);
for (var element in barElements) {
final labelFn = element.series.labelAccessorFn;
final datumIndex = element.index;
final label = (labelFn != null) ? labelFn(datumIndex) : null;
// If there are custom styles, use that instead of the default or the
// style defined for the entire decorator.
final datumInsideLabelStyle = _getDatumStyle(
element.series.insideLabelStyleAccessorFn,
datumIndex,
graphicsFactory,
defaultStyle: insideLabelStyle);
final datumOutsideLabelStyle = _getDatumStyle(
element.series.outsideLabelStyleAccessorFn,
datumIndex,
graphicsFactory,
defaultStyle: outsideLabelStyle);
// Skip calculation and drawing for this element if no label.
if (label == null || label.isEmpty) {
continue;
}
final bounds = element.bounds;
// Get space available inside and outside the bar.
final totalPadding = labelPadding * 2;
final insideBarWidth = bounds.width - totalPadding;
final outsideBarWidth = drawBounds.width - bounds.width - totalPadding;
final labelElement = graphicsFactory.createTextElement(label);
var calculatedLabelPosition = labelPosition;
if (calculatedLabelPosition == BarLabelPosition.auto) {
// For auto, first try to fit the text inside the bar.
labelElement.textStyle = datumInsideLabelStyle;
// A label fits if the space inside the bar is >= outside bar or if the
// length of the text fits and the space. This is because if the bar has
// more space than the outside, it makes more sense to place the label
// inside the bar, even if the entire label does not fit.
calculatedLabelPosition = (insideBarWidth >= outsideBarWidth ||
labelElement.measurement.horizontalSliceWidth < insideBarWidth)
? BarLabelPosition.inside
: BarLabelPosition.outside;
}
// Set the max width and text style.
if (calculatedLabelPosition == BarLabelPosition.inside) {
labelElement.textStyle = datumInsideLabelStyle;
labelElement.maxWidth = insideBarWidth;
} else {
// calculatedLabelPosition == LabelPosition.outside
labelElement.textStyle = datumOutsideLabelStyle;
labelElement.maxWidth = outsideBarWidth;
}
// Only calculate and draw label if there's actually space for the label.
if (labelElement.maxWidth > 0) {
// Calculate the start position of label based on [labelAnchor].
int labelX;
if (calculatedLabelPosition == BarLabelPosition.inside) {
final _labelAnchor = labelAnchor ?? _defaultHorizontalLabelAnchor;
switch (_labelAnchor) {
case BarLabelAnchor.middle:
labelX = (bounds.left +
bounds.width / 2 -
labelElement.measurement.horizontalSliceWidth / 2)
.round();
labelElement.textDirection =
rtl ? TextDirection.rtl : TextDirection.ltr;
break;
case BarLabelAnchor.end:
case BarLabelAnchor.start:
final alignLeft = rtl
? (_labelAnchor == BarLabelAnchor.end)
: (_labelAnchor == BarLabelAnchor.start);
if (alignLeft) {
labelX = bounds.left + labelPadding;
labelElement.textDirection = TextDirection.ltr;
} else {
labelX = bounds.right - labelPadding;
labelElement.textDirection = TextDirection.rtl;
}
break;
}
} else {
// calculatedLabelPosition == LabelPosition.outside
labelX = bounds.right + labelPadding;
labelElement.textDirection = TextDirection.ltr;
}
// Center the label inside the bar.
final labelY = (bounds.top +
(bounds.bottom - bounds.top) / 2 -
labelElement.measurement.verticalSliceWidth / 2)
.round();
canvas.drawText(labelElement, labelX, labelY);
}
}
}
/// Helper function to get the total height for a group of labels.
/// This includes the padding in between the labels.
int _getTotalLabelHeight(Iterable<TextElement> labelElements) =>
(labelElements.first.measurement.verticalSliceWidth *
labelElements.length)
.round() +
_defaultMultiLineLabelPadding * (labelElements.length - 1);
// Helper function that converts [TextStyleSpec] to [TextStyle].
TextStyle _getTextStyle(
GraphicsFactory graphicsFactory, TextStyleSpec labelSpec) {
return graphicsFactory.createTextPaint()
..color = labelSpec?.color ?? Color.black
..fontFamily = labelSpec?.fontFamily
..fontSize = labelSpec?.fontSize ?? 12
..lineHeight = labelSpec?.lineHeight;
}
/// Helper function to get datum specific style
TextStyle _getDatumStyle(AccessorFn<TextStyleSpec> labelFn, int datumIndex,
GraphicsFactory graphicsFactory,
{TextStyle defaultStyle}) {
final styleSpec = (labelFn != null) ? labelFn(datumIndex) : null;
return (styleSpec != null)
? _getTextStyle(graphicsFactory, styleSpec)
: defaultStyle;
}
}
/// Configures where to place the label relative to the bars.
enum BarLabelPosition {
/// Automatically try to place the label inside the bar first and place it on
/// the outside of the space available outside the bar is greater than space
/// available inside the bar.
auto,
/// Always place label on the outside.
outside,
/// Always place label on the inside.
inside,
}
/// Configures where to anchor the label for labels drawn inside the bars.
enum BarLabelAnchor {
/// Anchor to the measure start.
start,
/// Anchor to the middle of the measure range.
middle,
/// Anchor to the measure end.
end,
}

Android: Shape detection with JavaCV

I am new to JavaCV. I am trying to detect largest rectangle in image and outline it with color over original image. I am posting code below which I have tried but it is not working. I am getting edgeDetectedImage properly. I am getting 4 corner points properly. Just cvDrawLine is not working. Please Help if I am missing anything:
OnClick of button I am processing image and showing it again on ImageView.
In onClickListener of button:
if ((new File(path + "trial.jpg")).exists()) {
opencv_core.IplImage originalImage = opencv_imgcodecs.cvLoadImage(path + "trial.jpg", opencv_imgcodecs.CV_IMWRITE_JPEG_QUALITY);
opencv_core.IplImage iplImage = opencv_imgcodecs.cvLoadImage(path + "trial.jpg", opencv_imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);
opencv_core.IplImage edgeDetectedImage = applyCannyRectangleEdgeDetection(iplImage, 80);
opencv_core.CvSeq largestContour = findLargestContour(edgeDetectedImage);
opencv_core.CvPoint[] cvPoints = new opencv_core.CvPoint[4];
for(int i=0; i<largestContour.total();i++)
{
opencv_core.CvPoint cvPoint = new opencv_core.CvPoint(cvGetSeqElem(largestContour, i));
cvPoints[i] = cvPoint;
}
cvDrawLine(originalImage, cvPoints[0], cvPoints[1], opencv_core.CvScalar.YELLOW, 10, 10, 10);
cvDrawLine(originalImage, cvPoints[1], cvPoints[2], opencv_core.CvScalar.YELLOW, 10, 10, 10);
cvDrawLine(originalImage, cvPoints[2], cvPoints[3], opencv_core.CvScalar.YELLOW, 10,10, 10);
cvDrawLine(originalImage, cvPoints[3], cvPoints[0], opencv_core.CvScalar.YELLOW, 10, 10,10);
opencv_imgcodecs.cvSaveImage(path + "img1.jpg", originalImage);
if ((new File(path + "img1.jpg").exists())) {
imageView.setImageDrawable(Drawable.createFromPath(path + "img1.jpg"));
}
}
Method applyCannyRectangleEdgeDetection(IplImage, int):
private opencv_core.IplImage applyCannyRectangleEdgeDetection(opencv_core.IplImage iplImage, int percent) {
opencv_core.IplImage destImage = downScaleImage(iplImage, percent);
OpenCVFrameConverter.ToMat converterToMat = new OpenCVFrameConverter.ToMat();
Frame grayImageFrame = converterToMat.convert(destImage);
opencv_core.Mat grayImageMat = converterToMat.convertToMat(grayImageFrame);
GaussianBlur(grayImageMat, grayImageMat, new opencv_core.Size(5, 5), 0.0, 0.0, BORDER_DEFAULT);
destImage = converterToMat.convertToIplImage(grayImageFrame);
cvErode(destImage, destImage);
cvDilate(destImage, destImage);
cvCanny(destImage, destImage, 20, 55);
return destImage;
}
Method downScaleImage(IplImage, int)
private opencv_core.IplImage downScaleImage(opencv_core.IplImage srcImage, int percent) {
opencv_core.IplImage destImage = cvCreateImage(cvSize((srcImage.width() * percent) / 100, (srcImage.height() * percent) / 100), srcImage.depth(), srcImage.nChannels());
cvResize(srcImage, destImage);
return destImage;
}
Method findLargestContour(IplImage)
private opencv_core.CvSeq findLargestContour(opencv_core.IplImage edgeDetectedImage) {
opencv_core.IplImage foundContoursOfImage = cvCloneImage(edgeDetectedImage);
opencv_core.CvMemStorage memory = new opencv_core.CvMemStorage().create();
opencv_core.CvSeq contours = new opencv_core.CvSeq();
cvFindContours(foundContoursOfImage, memory, contours, Loader.sizeof(opencv_core.CvContour.class), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, new opencv_core.CvPoint(0, 0));
int maxWidth = 0;
int maxHeight = 0;
opencv_core.CvRect contr = null;
opencv_core.CvSeq seqFound = null;
opencv_core.CvSeq nextSeq;
for (nextSeq = contours; nextSeq != null; nextSeq = nextSeq.h_next()) {
contr = cvBoundingRect(nextSeq, 0);
if ((contr.width() >= maxWidth) && (contr.height() >= maxHeight)) {
maxHeight = contr.height();
maxWidth = contr.width();
seqFound = nextSeq;
}
}
opencv_core.CvSeq result = cvApproxPoly(seqFound, Loader.sizeof(opencv_core.CvContour.class), memory, CV_POLY_APPROX_DP, cvContourPerimeter(seqFound) * 0.1, 0);
return result;
}
Sorry this should be in comments but I don't have enough reputation. What I can see from your code is that the canny is applied on a downscaled image and so is the contour. You are drawing the lines on the original image (which isn't downscaled by percent) so naturally it wouldn't look correct (if it isn't looking correct but something is being drawn). Otherwise, you should mention the color space of the image, it doesn't matter for drawing but does for canny.

unity float and object error in android platform

i write this code and i don't know how to fix all error of this code but this code work correctly in pc mode but give error in android mode this is my code :
var background : Texture2D;
var splash : Texture2D;
var font : Font;
private var showADPresents = 3.0;
var size = null;
static var virtualScreen : Vector2 = Vector2(800, 600);
function Update()
{
showADPresents -= Time.deltaTime;
if (Application.CanStreamedLevelBeLoaded(1) && Input.anyKeyDown)
Application.LoadLevel(1);
}
function OnGUI()
{
GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, Vector3(Screen.width / virtualScreen.x, Screen.height / virtualScreen.y, 1));
GUI.DrawTexture(Rect(0, 0, virtualScreen.x, virtualScreen.y), splash);
if (showADPresents > 0)
{
var alpha = Mathf.Clamp01(showADPresents);
var color = Color.white;
color.a = alpha;
GUI.color = color;
GUI.DrawTexture(Rect(0, 0, virtualScreen.x, virtualScreen.y), background);
var presentsStyle = new GUIStyle(GUI.skin.label);
presentsStyle.font = font;
presentsStyle.fontSize = 48;
size = 300;
color = Color.black;
color.a = alpha;
GUI.color = color;
GUI.Label(Rect(( virtualScreen.x - size) * 0.5, (virtualScreen.y - size) * 0.5, size, size), "Autodesk Presents:", presentsStyle);
}
else
{
var notificationStyle = new GUIStyle(GUI.skin.label);
notificationStyle.font = font;
notificationStyle.fontSize = 16;
GUI.color = Color.black;
var content = null;
if (Application.CanStreamedLevelBeLoaded(1))
content = new GUIContent("Click Screen to Continue");
else
content = new GUIContent("Loading...");
size = notificationStyle.CalcSize(content);
GUI.Label(Rect((virtualScreen.x - size.x) * 0.5, virtualScreen.y - size.y - 80, size.x, size.y),
content, notificationStyle);
}
}
and unity give me this error i cant solve this error plz help to me help :'(
http://upload.ghashang.com/images/gm214joveg1z354rkli.jpg
plz Belief i cant solve this error plz help me
plz solve all error
This is because size is not a static type. It is dynamic, and because there is no operator for a object subtracted from a float, this error is thrown. You have two options. One, you can cast as a float before you subtract.
GUI.Label(Rect(( virtualScreen.x - (float)size) * 0.5, (virtualScreen.y - (float)size) * 0.5, size, size), "Autodesk Presents:", presentsStyle);
The other, is to declare size as a float or int in the declaration.
float size = 0.0f;
//or
int size = 0;
However, later you try to reference size as though it was a Rect, which causes other errors. I would a)declare size as a Rect b)access the respective members of size. Your code will look like:
Rect size;
...
//remove the size = 300; line and replace it with a constructor
GUI.Label(Rect(( virtualScreen.x - size.x) * 0.5, (virtualScreen.y - size.y) * 0.5, size, size), "Autodesk Presents:", presentsStyle);
This will solve your issue, and I recommend you read more about static classes

Android Toast in iPhone?

When I write Android apps, I love the Toast feature. Is there a way to get this kind of set and forget popup message in iPhone development using MonoTouch (C# .NET)?
MonoTouch Toast Version here. Inspired by Android.
To call it,
ToastView t = new ToastView ("Email Sent", 1000);
t.Show ();
Enum File:
public enum ToastGravity
{
Top = 0,
Bottom = 1,
Center = 2
}
ToastSettings File:
using System;
using System.Drawing;
using MonoTouch.UIKit;
namespace General
{
public class ToastSettings
{
public ToastSettings ()
{
this.Duration = 500;
this.Gravity = ToastGravity.Center;
}
public int Duration
{
get;
set;
}
public double DurationSeconds
{
get { return (double) Duration/1000 ;}
}
public ToastGravity Gravity
{
get;
set;
}
public PointF Position
{
get;
set;
}
}
}
Main Toast Class:
using System;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using System.Drawing;
using MonoTouch.ObjCRuntime;
namespace General
{
public class ToastView : NSObject
{
ToastSettings theSettings = new ToastSettings ();
private string text = null;
UIView view;
public ToastView (string Text, int durationMilliseonds)
{
text = Text;
theSettings.Duration = durationMilliseonds;
}
int offsetLeft = 0;
int offsetTop = 0;
public ToastView SetGravity (ToastGravity gravity, int OffSetLeft, int OffSetTop)
{
theSettings.Gravity = gravity;
offsetLeft = OffSetLeft;
offsetTop = OffSetTop;
return this;
}
public ToastView SetPosition (PointF Position)
{
theSettings.Position = Position;
return this;
}
public void Show ()
{
UIButton v = UIButton.FromType (UIButtonType.Custom);
view = v;
UIFont font = UIFont.SystemFontOfSize (16);
SizeF textSize = view.StringSize (text, font, new SizeF (280, 60));
UILabel label = new UILabel (new RectangleF (0, 0, textSize.Width + 5, textSize.Height + 5));
label.BackgroundColor = UIColor.Clear;
label.TextColor = UIColor.White;
label.Font = font;
label.Text = text;
label.Lines = 0;
label.ShadowColor = UIColor.DarkGray;
label.ShadowOffset = new SizeF (1, 1);
v.Frame = new RectangleF (0, 0, textSize.Width + 10, textSize.Height + 10);
label.Center = new PointF (v.Frame.Size.Width / 2, v.Frame.Height / 2);
v.AddSubview (label);
v.BackgroundColor = UIColor.FromRGBA (0, 0, 0, 0.7f);
v.Layer.CornerRadius = 5;
UIWindow window = UIApplication.SharedApplication.Windows[0];
PointF point = new PointF (window.Frame.Size.Width / 2, window.Frame.Size.Height / 2);
if (theSettings.Gravity == ToastGravity.Top)
{
point = new PointF (window.Frame.Size.Width / 2, 45);
}
else if (theSettings.Gravity == ToastGravity.Bottom)
{
point = new PointF (window.Frame.Size.Width / 2, window.Frame.Size.Height - 45);
}
else if (theSettings.Gravity == ToastGravity.Center)
{
point = new PointF (window.Frame.Size.Width / 2, window.Frame.Size.Height / 2);
}
else
{
point = theSettings.Position;
}
point = new PointF (point.X + offsetLeft, point.Y + offsetTop);
v.Center = point;
window.AddSubview (v);
v.AllTouchEvents += delegate { HideToast (null); };
NSTimer.CreateScheduledTimer (theSettings.DurationSeconds, HideToast);
}
void HideToast ()
{
UIView.BeginAnimations ("");
view.Alpha = 0;
UIView.CommitAnimations ();
}
void RemoveToast ()
{
view.RemoveFromSuperview ();
}
}
}
Check this out:
https://github.com/ecstasy2/toast-notifications-ios
Edit: The project has moved to github so i update the link.
Here's my version: http://github.com/scalessec/toast
I think it's simpler to use because it's implemented as a obj-c category, thereby adding the makeToast methods to any instance of UIView. eg:
[self.view makeToast:#"This is some message as toast."
duration:3.0
position:#"bottom"];
Are you looking for something like UIAlertView?
You can use this link for objective-c code for Toast
http://code.google.com/p/toast-notifications-ios/source/browse/trunk/
While this link for its usage
http://code.google.com/p/toast-notifications-ios/wiki/HowToUse
which could be like any one of the below samples
[[iToast makeText:NSLocalizedString(#"The activity has been successfully saved.", #"")] show];
[[[iToast makeText:NSLocalizedString(#"The activity has been successfully saved.", #"")]
setGravity:iToastGravityBottom] show];
[[[[iToast makeText:NSLocalizedString(#"Something to display a very long time", #"")]
etGravity:iToastGravityBottom] setDuration:iToastDurationLong] show];
You might be after Local Notifications, pretty sure they allow you to set a time, I think in epoch time to be fired off. Don't think there is a way to hide them though. I might be misunderstanding your question though cause I'm unfamiliar with Toast.
Just You can use the following code with uilabel and uianimation to get toast like in android.
It does two works one is toast task and it increases the height of the label according to the text length with wordwrap IOS 7 later link here
CGRect initialFrame = CGRectMake(20, self.view.frame.size.height/2,300, 40);
NSString *message=#"Toast in Iphone as in Android";
UILabel *flashLabel=[[UILabel alloc] initWithFrame:initialFrame];
flashLabel.font=[UIFont fontWithName:#"Optima-Italic" size:12.0];
flashLabel.backgroundColor=[UIColor whiteColor];
flashLabel.layer.cornerRadius=3.0f;
flashLabel.numberOfLines=0;
flashLabel.textAlignment=NSTextAlignmentCenter;
CGSize maxSize = CGSizeMake(flashLabel.frame.size.width, MAXFLOAT);
CGRect labelRect = [message boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:#{NSFontAttributeName:flashLabel.font} context:nil];
//adjust the label the the new height.
CGRect newFrame = flashLabel.frame;
newFrame.size.height = labelRect.size.height;
flashLabel.frame = newFrame;
flashLabel.text=message;
[self.view addSubview:flashLabel];
flashLabel.alpha=1.0;
self.view.userInteractionEnabled=FALSE;
[UIView animateWithDuration:13.0 animations:^
{
flashLabel.alpha=0.0f;
}
completion:^(BOOL finished)
{
self.view.userInteractionEnabled=TRUE;
[flashLabel removeFromSuperview];
}];
I modified John's answer as follows:
Toast.h
#interface Toast : NSObject
+ (void)toast:(NSString *)message
:(UIView *) view
:(int)delay;
#end
Toast.m
#import "Toast.h"
#interface Toast ()
#end
#implementation Toast
+ (void)toast:(NSString *)message
:(UIView *) view
:(int)delay
{
CGRect initialFrame = CGRectMake(10, view.frame.size.height/2, 300, 40);
UILabel *flashLabel=[[UILabel alloc] initWithFrame:initialFrame];
flashLabel.font=[UIFont fontWithName:#"Optima-Italic" size:19.0];
flashLabel.backgroundColor=[UIColor whiteColor];
flashLabel.layer.cornerRadius=9.0f;
flashLabel.clipsToBounds = YES;
flashLabel.numberOfLines=3;
flashLabel.textAlignment=NSTextAlignmentCenter;
CGSize maxSize = CGSizeMake(flashLabel.frame.size.width, MAXFLOAT);
CGRect labelRect = [message boundingRectWithSize:maxSize
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:flashLabel.font}
context:nil];
//adjust the label the the new height.
CGRect newFrame = flashLabel.frame;
newFrame.size.height = labelRect.size.height * 2;
flashLabel.frame = newFrame;
flashLabel.text=message;
[view addSubview:flashLabel];
flashLabel.alpha=1.0;
view.userInteractionEnabled=FALSE;
[UIView animateWithDuration:delay animations:^
{
flashLabel.alpha=0.0f;
}
completion:^(BOOL finished)
{
view.userInteractionEnabled=TRUE;
[flashLabel removeFromSuperview];
}];
}
#end
I have added a little modification to the toast class that handles rotation of the display.
public void Show ()
{
UIButton v = UIButton.FromType (UIButtonType.Custom);
view = v;
UIFont font = UIFont.SystemFontOfSize (16);
SizeF textSize = view.StringSize (text, font, new SizeF (280, 60));
UILabel label = new UILabel (new RectangleF (0, 0, textSize.Width + 5, textSize.Height + 5));
label.BackgroundColor = UIColor.Clear;
label.TextColor = UIColor.White;
label.Font = font;
label.Text = text;
label.Lines = 0;
label.ShadowColor = UIColor.DarkGray;
label.ShadowOffset = new SizeF (1, 1);
v.Frame = new RectangleF (0, 0, textSize.Width + 10, textSize.Height + 10);
label.Center = new PointF (v.Frame.Size.Width / 2, v.Frame.Height / 2);
v.AddSubview (label);
v.BackgroundColor = UIColor.FromRGBA (0, 0, 0, 0.7f);
v.Layer.CornerRadius = 5;
UIWindow window = UIApplication.SharedApplication.Windows[0];
PointF point = new PointF (window.Frame.Size.Width / 2, window.Frame.Size.Height / 2);
if (theSettings.Gravity == ToastGravity.Top)
{
point = new PointF (window.Frame.Size.Width / 2, 45);
}
else if (theSettings.Gravity == ToastGravity.Bottom)
{
point = new PointF (window.Frame.Size.Width / 2, window.Frame.Size.Height - 45);
}
else if (theSettings.Gravity == ToastGravity.Center)
{
point = new PointF (window.Frame.Size.Width / 2, window.Frame.Size.Height / 2);
}
else
{
point = theSettings.Position;
}
point = new PointF (point.X + offsetLeft, point.Y + offsetTop);
v.Center = point;
//handle screen rotation
float orientation=0;
switch(UIApplication.SharedApplication.StatusBarOrientation)
{
case UIInterfaceOrientation.LandscapeLeft:
orientation=-90;
break;
case UIInterfaceOrientation.LandscapeRight:
orientation=90;
break;
case UIInterfaceOrientation.PortraitUpsideDown:
orientation=180;
break;
}
v.Transform=CGAffineTransform.MakeRotation ((float)(orientation / 180f * Math.Pi));
window.AddSubview (v);
v.AllTouchEvents += delegate { HideToast (); };
NSTimer.CreateScheduledTimer (theSettings.DurationSeconds, HideToast);
}
You could try my open source library TSMessages: https://github.com/toursprung/TSMessages
It's really easy to use and looks beautiful on iOS 5/6 and on iOS 7 as well.
I really like MonoTouch solution proposed by Bahai.
The following is not a substitution. Is just a ready-to-go one method the worked for me.
private async Task ShowToast(string message, UIAlertView toast = null)
{
if (null == toast)
{
toast = new UIAlertView(null, message, null, null, null);
toast.Show();
await Task.Delay(2000);
await ShowToast(message, toast);
return;
}
UIView.BeginAnimations("");
toast.Alpha = 0;
UIView.CommitAnimations();
toast.DismissWithClickedButtonIndex(0, true);
}
If the method is called from a background thread (not the main UI thread) then BeginInvokeOnMainThread is required which means just call it like this.
BeginInvokeOnMainThread(() =>
{
ShowToast(message);
});
I created a new repo on github with a class to do iOS toast-style alerts. I didn't like the one on code.google.com, it didn't rotate properly and wasn't pretty.
https://github.com/esilverberg/ios-toast
Enjoy folks.

Categories

Resources