Save an Image with superimposed Label on the device - c#

I have some images in my ftp web space, and through this method I can view them on the screen, and above them I insert a Label.
var ImageUrl = "ftp://xxxxxxxxx.jpg";
//Download Image
byte[] ImgByte1 = WebClient.DownloadData(ImageUrl);
MemoryStream mStream1 = new MemoryStream(ImgByte1);
ObservableCollection<FraseClass> listFrasi = new ObservableCollection<FraseClass>
{
new FraseClass{Source=ImageSource.FromStream(() => mStream1)},
}
XAML
<Image
Source="{Binding Source}"/>
<Label
Text="Hello"/>
I am looking for a way to be able to save the image on the device with the text superimposed. I tried to search but couldn't find anything to fix my problem

I am looking for a way to be able to save the image on the device with the text superimposed. I tried to search but couldn't find anything to fix my problem
According to your description, you want to save image that downloadind from url into local storage, am I right?
If yes, I suggest you can use Xamarin.Forms DependencyService to do this.
Firstly, create an interface in shared code.
public interface IImageFile
{
void SaveImage(string name, byte[] data, string location = "temp");
}
Then implement the interface on Android platform. Don't forget to register the platform implementations.
[assembly: Dependency(typeof(ImageFile))]
namespace FormsSample.Droid
{
public class ImageFile : IImageFile
{
public void SaveImage(string name, byte[] data, string location = "temp")
{
var documentsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
documentsPath = System.IO.Path.Combine(documentsPath, "Orders", location);
Directory.CreateDirectory(documentsPath);
string filePath = System.IO.Path.Combine(documentsPath, name);
using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate))
{
int length = data.Length;
fs.Write(data, 0, length);
}
}
}
}
Finally, resolving platform implementations with the DependencyService
private void btn1_Clicked(object sender, EventArgs e)
{
var ImageUrl = "ftp://xxxxxxxxx.jpg";
//Download Image
byte[] ImgByte1 = WebClient.DownloadData(ImageUrl);
DependencyService.Get<IImageFile>().SaveImage("ImageName.jpg", ImgByte1, "imagesFolder");
}
you need to add permission WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE in AndroidMainfeast.xml, then you also need to Runtime Permission Checks in Android 6.0. Using the following code in Mainactivity.cs to request permissions.
private void checkpermission()
{
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.WriteExternalStorage) == (int)Permission.Granted)
{
// We have permission, go ahead and use the writeexternalstorage.
}
else
{
// writeexternalstorage permission is not granted. If necessary display rationale & request.
}
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.ReadExternalStorage) == (int)Permission.Granted)
{
// We have permission, go ahead and use the ReadExternalStorage.
}
else
{
// ReadExternalStorage permission is not granted. If necessary display rationale & request.
}
}
Detailed info about IOS platform, you can take a look:
How to download image and save it in local storage using Xamarin-Forms.?
Update:
If you want to add text watermark on image, you need to convert byte[] to bitmap to add text firstly.
Android.Graphics.Bitmap mutableBitmap;
Android.Graphics.Bitmap bitmap;
public void ConvertImage(byte[] imageArray)
{
bitmap = BitmapFactory.DecodeByteArray(imageArray, 0, imageArray.Length);
}
public void Watermark()
{
mutableBitmap = bitmap.Copy(Android.Graphics.Bitmap.Config.Argb8888, true);
Canvas canvas = new Canvas(mutableBitmap);
// Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.Color = Android.Graphics.Color.Black;
paint.TextSize = 50;
canvas.DrawText("hellod world", 50, 50, paint);
}
Then convert bitmap into byte[] to save image into local storage.
public void convertbitmap(Bitmap bitmap)
{
bitmap = mutableBitmap;
MemoryStream stream = new MemoryStream();
bitmap.Compress(Bitmap.CompressFormat.Png, 0, stream);
byte[] bitmapData = stream.ToArray();
}

Related

Can't retrieve image from web in Xamarin forms

In the viewmodel of my page, I try to get an image to show. This image I get from one of our webservice. The image source is stored in ProductImage
string path = $#"http://www.MyCompany.be/cdn-cgi/image/width=150,quality=75/images/products/{CurrentProduct.Image}".Replace($"\\", $"/");
ProductImage = ImageSource.FromUri(new Uri(path));
I of course make sure when I update the Image source for the view when I change it
public ImageSource ProductImage
{
get
{
return _productImage;
}
set
{
if (_productImage != value)
{
_productImage = value;
OnPropertyChanged();
}
}
}
Sadly, for some reason it doesn't work. I checked the URL called and it does lead to an image.
It used to work when I was using streams instead of calling an URL. I know I haven't put the safety checks around yet to make sure the image exist, but other than that nothing has changed. I save the image the exact same way, i just use fromUri rather than fromStream.
//Get target's SmbFile.
var file = new SmbFile(path, auth);
try
{
if (file.Exists())
{
// Get readable stream.
var readStream = file.GetInputStream();
//Create reading buffer.
MemoryStream memStream = new MemoryStream();
//Get bytes.
((Stream)readStream).CopyTo(memStream);
var stream1 = new MemoryStream(memStream.ToArray());
if (stream1.Length < 30000000)
{
//Save image
//ProductImage = ImageSource.FromStream(() => stream1);
//Dispose readable stream.
readStream.Dispose();
InfoColSpan = 1;
}
else
{
Common.AlertError("Image trop lourde pour l'affichage");
}
}
}
catch (Exception ex)
{
Common.AlertError(ex, "Impossible de charger l'image");
}
Since I changed my method, I no longer load anything.

Unity Resources.load() won't work with external dll

I'm trying to load an asset using Resources.load() but it always returns null.
Here is my folder structure: https://imgur.com/a/z8KObW1
When I use Resources.load() in my unity project, it works without any problem.
But when I create a seperate project in visual studio with the unityengine dll's, and use Resources.load() in one of the .cs files under the Source folder it always seems to return null, no matter what I try.
When I placed the Assets folder inside of the Source folder it returned null and when I placed the .cs files in the Asset folder it also returned null. I can't seem to figure out why. I also tried to fetch the path that the Resources.load() starts at, but I can't seem to figure it out. Does it start from the .dll or from the .cs file under the Source?
public static void Create_Manager() {
GameObject networkManagerObj = new GameObject();
networkManagerObj.name = "_NetworkManager";
networkManager = networkManagerObj.AddComponent<NetworkManager>();
networkManager.playerPrefab = Resources.Load("Player") as GameObject;
networkManager.dontDestroyOnLoad = true;
networkManager.runInBackground = true;
networkManager.autoCreatePlayer = true;
}
All I need is for the Resources.load() to work with my seperate project/dll. Does anyone know how to do so?
Here's the code that a coworker of mine wrote and mostly explained to me. I've omitted a lot of the code that dealt with what this class was for (handling touch input), leaving only the sections related to loading an image (used to display a touch point on screen).
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using UnityEngine;
using HedgehogTeam.EasyTouch;
namespace TouchControls
{
/// <summary>Helper to control touch-based input.</summary>
public static class Utility
{
const string imageNamespace = "TouchControls.";
const string imageResourceFolder = "TouchControls/Images/";
/// <summary>Static helper to contain texture resources.</summary>
public static class Texture
{
/// <summary>The texture used to represent a second finger when simulating touches.</summary>
public static Texture2D SecondFinger
{
get
{
if (null == secondFinger)
secondFinger = LoadImage(secondFingerFilename);
return secondFinger;
}
}
static Texture2D secondFinger = null;
const string secondFingerFilename = "secondFinger.png";
}
static Assembly ExecutingAssembly
{
get
{
if (null == executingAssembly)
{
executingAssembly = Assembly.GetExecutingAssembly();
}
return executingAssembly;
}
}
static Assembly executingAssembly = null;
static Stream GetImageStream(string imageName) { return ExecutingAssembly.GetManifestResourceStream(imageName); }
static Texture2D LoadImage(string filename, TextureWrapMode wrapMode = TextureWrapMode.Clamp, FilterMode filterMode = FilterMode.Bilinear, bool useMipMaps = true, TextureFormat format = TextureFormat.ARGB32)
{
Texture2D texture = Resources.Load<Texture2D>(imageResourceFolder + Path.GetFileNameWithoutExtension(!string.IsNullOrEmpty(filename) ? filename : string.Empty));
try
{
// Didn't find it in resources in the project so try to find it in the library manifest....
if (null == texture)
{
using (Stream stream = GetImageStream(imageNamespace + filename))
{
texture = new Texture2D(0, 0, format, useMipMaps);
if (!texture.LoadImage(GetImageBuffer(stream)))
throw new NotSupportedException(filename);
texture.wrapMode = wrapMode;
texture.filterMode = filterMode;
}
}
else // ensure it is read/write enabled...
{
Texture2D invertedTexture = new Texture2D(texture.width, texture.height, texture.format, 1 < texture.mipmapCount);
invertedTexture.SetPixels32(texture.GetPixels32());
invertedTexture.Apply(true);
texture = invertedTexture;
}
}
catch
{
// Something went wrong so make a magenta 4 pixel texture.
texture = new Texture2D(2, 2, TextureFormat.ARGB32, false);
texture.SetPixels(0, 0, 2, 2, Enumerable.Repeat(Color.magenta, 4).ToArray());
}
texture.Apply(true);
return texture;
}
static byte[] GetImageBuffer(Stream stream)
{
stream.Seek(0, SeekOrigin.Begin);
byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, (int)stream.Length);
return buffer;
}
}
}
It first attempts to load an image out of the Resources folder (as you're familiar with) at a given location: this allows the image to be overridden by the local project, if desired. If that image isn't found, then it loads one out of the DLL. I am not sure where this image is located, but as the path reference is in the code, I'm sure it works out sensibly enough (the key part he had informed me was how to insure that the file got included in the DLL, rather than where it was located).
The important chunk for loading it out of the DLL is this section:
static Stream GetImageStream(string imageName) { return ExecutingAssembly.GetManifestResourceStream(imageName); }
//...
using (Stream stream = GetImageStream(imageNamespace + filename))
{
texture = new Texture2D(0, 0, format, useMipMaps);
if (!texture.LoadImage(GetImageBuffer(stream)))
throw new NotSupportedException(filename);
texture.wrapMode = wrapMode;
texture.filterMode = filterMode;
}
//...
texture.Apply(true);
return texture;

Get Exif info from photo

I want to read exif info from Photo using ExifLib, first way is finished because I used PhotoChooserTask and photoChooserTask.Completed += (s, e) => {PhotoConverter.GetMetaData(e);}
and method for get exif info
public static void GetMetaDate(PhotoResult e)
{
ExifLib.JpegInfo info = ExifLib.ExifReader.ReadJpeg(e.ChosenPhoto);
var img = new BitmapImage();
img.SetSource(e.ChosenPhoto);
App.MainViewModel.MetaDate = ReadExif(info);
}
private static string ReadExif(JpegInfo info)
{
JsonObject metaDate = new JsonObject();
metaDate.Add("FNumber", info.FNumber);
return metaDate.ToString();
}
and it is work great, but the problem is when I want to share picture from phone's gallery. My way to get picture looks like this
if (queryStrings.ContainsKey("FileId"))
{
MediaLibrary library = new MediaLibrary();
Picture photoFromLibrary = library.GetPictureFromToken(queryStrings["FileId"]);
BitmapImage bitmapFromPhoto = new BitmapImage();
bitmapFromPhoto.SetSource(photoFromLibrary.GetImage());
}
So, how I should change my GetMetaDate to read photoFromLibrary.GetImage
Ok, I find easy way
public static void GetMetaData(Stream photo)//change to stream
{
ExifLib.JpegInfo info = ExifLib.ExifReader.ReadJpeg(photo);
var img = new BitmapImage();
img.SetSource(photo);
App.MainViewModel.MetaDate = ReadExif(info);
}
and in place with MediaLiblary add stream
if (queryStrings.ContainsKey("FileId"))
{
// Retrieve the photo from the media library using the FileID passed to the app.
MediaLibrary library = new MediaLibrary();
Picture photoFromLibrary = library.GetPictureFromToken(queryStrings["FileId"]);
//Get metadate
Stream stream = photoFromLibrary.GetImage();
PhotoConverter.GetMetaData(stream);
}

How to take a screenshot of the iPhone/iPad programmatically with Xamarin.iOS (C#)?

How can I take a screenshot with Xamarin.iOS and stored this image in UIImage.
I have seen several examples of Obj-C, but no C #
Even more elegant:
UIScreen.MainScreen.Capture ();
from Craig Dunn's site:
public void ScreenCapture()
{
var documentsDirectory = Environment.GetFolderPath
(Environment.SpecialFolder.Personal);
Console.WriteLine("start capture of frame: " + this.View.Frame.Size);
UIGraphics.BeginImageContext(View.Frame.Size);
var ctx = UIGraphics.GetCurrentContext();
if (ctx != null)
{
View.Layer.RenderInContext(ctx);
UIImage img = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
// Set to display in a UIImage control _on_ the view
imageLogo.Image = img;
// Save to Photos
img.SaveToPhotosAlbum(
(sender, args)=>{Console.WriteLine("image saved to Photos");}
);
// Save to application's Documents folder
string png = Path.Combine (documentsDirectory, "Screenshot.png");
// HACK: overwrite the splash screen. iSOFlair is the application name
//string png = Path.Combine (documentsDirectory, "../iSOFlair.app/Default.png");
NSData imgData = img.AsPNG();
NSError err = null;
if (imgData.Save(png, false, out err))
{
Console.WriteLine("saved as " + png);
} else {
Console.WriteLine("NOT saved as" + png +
" because" + err.LocalizedDescription);
}
}
else
{
Console.WriteLine("ctx null - doesn't seem to happen");
}
}
More elegant:
public static class UIViewExtensions {
public static UIImage AsImage(this UIView view) {
UIGraphics.BeginImageContextWithOptions(view.Bounds.Size, view.Opaque, 0);
view.Layer.RenderInContext(UIGraphics.GetCurrentContext());
UIImage img = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
return img;
}
public static UIImage TakeScreenshot() {
return UIApplication.SharedApplication.KeyWindow.AsImage();
}
}
Call UIViewExtensions.TakeScreenshot() to take a screenshot of the whole screen or you can call AsImage() to any view to get an UIImage representation of the view. It would be better to put the TakeScreenshot() method somewhere else as it is not an extension of the UIView class.
This code will take a screenshot and save the photo into the camera roll.
UIGraphics.BeginImageContext(UIScreen.MainScreen.Bounds.Size);
try
{
var mainLayer = UIApplication.SharedApplication.KeyWindow.Subviews[0].Layer;
mainLayer.RenderInContext(UIGraphics.GetCurrentContext());
var img = UIGraphics.GetImageFromCurrentImageContext();
img.SaveToPhotosAlbum((iRef, status) =>
{
if (status != null)
{
new UIAlertView("Problem", status.ToString(), null, "OK", null).Show();
}
else
{
new UIAlertView("Saved", "Saved", null, "OK", null).Show();
}
});
}
finally
{
UIGraphics.EndImageContext();
}
But to make sure your app didn't crash is to ask the user for the permission to save the images to the camera roll.
Add this into info.plist
<key>NSPhotoLibraryAddUsageDescription</key>
<string>This app requires read and write permission from the user.</string>
if you're adding it from the generic editor then "Privacy - Photo Library Additions Usage Description" will be the given option you will find out instead of "NSPhotoLibraryAddUsageDescription".

Imagestream to file resulting in partially gray image (sometimes)

I having an issue uploading / sending images from a stream to a generic handler in ASP.NET. I’ve build a windows phone app that can take an image and send it to the generic handler on my website.
Unfortunately in some occasions the image turns out to be (partially) gray. I think it might have something to to with a lost/bad internet connection of the mobile device. This problem happens every 50 images or so.
When the faulty image is send I do not get an error of any kind. I’m looking for two possible solutions.
How do i prevent the windows phone uploading a partially gray image to the generic handler.
How do i check if an image is partially gray on the server so can send a error message back to the phone.
to make this question more compleet I included the code of the generic handler and an example image. Second I’m very curious why this occus. TCPIP has an handshake so above isseu should not be possible ?
public class UploadImages : IHttpHandler
{
private IWorkOrderRepository _workOrderRepository;
private IDigitalFileRepository _digitalFileRepository;
private IUserRepository _userRepository;
public UploadImages()
{
_workOrderRepository = ((Global)HttpContext.Current.ApplicationInstance).Kernel.Get<IWorkOrderRepository>();
_digitalFileRepository = ((Global)HttpContext.Current.ApplicationInstance).Kernel.Get<IDigitalFileRepository>();
_userRepository = ((Global)HttpContext.Current.ApplicationInstance).Kernel.Get<IUserRepository>();
}
public void ProcessRequest(HttpContext context)
{
var cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
var user = (Domain.Users.User)HttpContext.Current.User;
string WorkOrderId = context.Request.QueryString["workOrderId"];
string latitude = context.Request.QueryString["LATITUDE"];
string Longitude = context.Request.QueryString["LONGITUDE"];
if (latitude != "0" && Longitude != "0")
{
string file = "Filename.jpg";
string uploadPath = context.Server.MapPath("~/Temp/");
using (var stream = new MemoryStream())
{
var image = ImageResizer.Resize(Image.FromStream(context.Request.InputStream), 700);
image.Save(stream, ImageFormat.Jpeg);
stream.Position = 0;
var workOrder = _workOrderRepository.GetAll(x => x.Id == Convert.ToInt32(WorkOrderId)).FirstOrDefault();
workOrder.AddPhoto(_workOrderRepository, _digitalFileRepository, new AuditInfo((Domain.Users.User)user), stream, file, "image/jpeg", Convert.ToDouble(latitude), Convert.ToDouble(Longitude));
}
}
else
{
string file = "Filename.jpg";
string uploadPath = context.Server.MapPath("~/Temp/");
using (var stream = new MemoryStream())
{
var image = ImageResizer.Resize(Image.FromStream(context.Request.InputStream), 700);
image.Save(stream, ImageFormat.Jpeg);
stream.Position = 0;
var workOrder = _workOrderRepository.GetAll(x => x.Id == Convert.ToInt32(WorkOrderId)).FirstOrDefault();
workOrder.AddPhoto(_workOrderRepository, _digitalFileRepository, new AuditInfo((Domain.Users.User)user), stream, file, "image/jpeg");
}
}
}
public bool IsReusable
{
get
{
return false;
}
}
}

Categories