Is it possible to write 3D text on image. I am using asp.net with c#. If possible then kindly give me some Idea.
here is my method to write text on image
private readonly string _textOnImage = ConfigurationManager.AppSettings["textOnImage"];
private readonly int _opacity = Int32.Parse(ConfigurationManager.AppSettings["opicity"]);
private readonly int _red = Int32.Parse(ConfigurationManager.AppSettings["red"]);
private readonly int _green = Int32.Parse(ConfigurationManager.AppSettings["green"]);
private readonly int _blue = Int32.Parse(ConfigurationManager.AppSettings["blue"]);
private int _fontSize = Int32.Parse(ConfigurationManager.AppSettings["fontSize"]);
private readonly String _fontName = ConfigurationManager.AppSettings["fontName"];
private bool _havException { get; set; }
private string _exceptionMessage { get; set; }
private Bitmap SourceImage { get; set; }
private Bitmap DestinationImage { get; set; }
public ImageMethods()
{
_havException = false;
_exceptionMessage = string.Empty;
}
public void AddWatermarkText(Image img, String TextOnImage)
{
TextOnImage = TextOnImage ?? _textOnImage;
try
{
var lobFromImage = Graphics.FromImage(img);
FindFontSize(lobFromImage, img, TextOnImage);
var lobFont = new Font(_fontName, _fontSize, FontStyle.Regular);
var lintTextHw = lobFromImage.MeasureString(TextOnImage, lobFont);
var lintTextOnImageWidth = (int)lintTextHw.Width;
var lintTextOnImageHeight = (int)lintTextHw.Height;
var lobSolidBrush = new SolidBrush(Color.FromArgb(_opacity, Color.FromArgb(_red, _green, _blue)));
var posLeft = (img.Width - lintTextOnImageWidth) / 2;
posLeft = posLeft > 0 ? posLeft : 5;
var lobPoint = new Point(posLeft, (img.Height / 2) - (lintTextOnImageHeight / 2));
// var lobPoint = new Point(RandomNumber(0, img.Width - lintTextOnImageWidth), RandomNumber(0, img.Height - lintTextOnImageHeight));
lobFromImage.DrawString(TextOnImage, lobFont, lobSolidBrush, lobPoint, StringFormat.GenericTypographic);
lobFromImage.Dispose();
lobSolidBrush.Dispose();
lobFont.Dispose();
}
catch (Exception ex)
{
_havException = true;
_exceptionMessage = ex.Message;
}
return;
}
private void FindFontSize(Graphics lobGraphics, Image lobImage ,String textOnImage )
{
var lobFont = new Font(_fontName, _fontSize, FontStyle.Regular);
var lintTextHw = lobGraphics.MeasureString(textOnImage, lobFont);
var lintTextOnImageWidth = (int)lintTextHw.Width;
var lintImageWidth = lobImage.Width ;
while (lintImageWidth < lintTextOnImageWidth)
{
lobFont = new Font(_fontName, _fontSize--, FontStyle.Regular);
lintTextOnImageWidth = (int)lobGraphics.MeasureString(textOnImage, lobFont).Width;
}
}
Yes this is possible, but you'll have to draw it manually.
Please refer to this to get started drawing on an image.
Next, explore the System.Drawing namespace, in particular the Graphics class that has draw methods and is used in the above-mentioned post too.
I found a great article regrading it here.
Although, the author is using e.Graphics mostly inside of OnPaint(...) event. But you can create your own graphics as well something like:
var image = Image.FromFile(path);
// or
var image = Image.FromStream(stream);
// or
var width = 100;
var height= 100;
var image = new Bitmap(width, height);
var graphics = Graphics.FromBitmap(image);
and do the rest like in article explained.
Related
I am working on a xamarin forms app using xamarin forms maps for Android at the moment that tracks my location and depending on my proximity to a custom pin i have placed on the map will change in size depending on my proximity.
Basically if within a few meters the icon is 32x32 and farther away its 24x24.
Ive created a custom map renderer that places my pins from a JSON file and this is ok.
When my map form page loads in both my simulator and an actual android device the methods run and get my proximity based on my location and appropriately alter the size of the map pin.
However, this does not work as i move around.
For some reason my overridden CreateMarker method does not trigger when my location changes unless i call Content=customMap. Doing this only causes my map to load over and over and basically will not work.
I have a method in my about page called UpdateMap3() that is called when the users location changes. However, as stated i cant get the pins to update their size as i get nearer the pins while the app is running.
Ive included my forms page code behind below and markup below that and finally my map renderer below that.
Any help would be hugely appreciated.
Thanls
using System;
using System.IO;
using System.Reflection;
using Xamarin.Forms;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using Xamarin.Forms.Maps;
using Xamarin.Essentials;
using Distance = Xamarin.Forms.Maps.Distance;
using Google.Protobuf.WellKnownTypes;
using static Google.Protobuf.Reflection.FieldDescriptorProto.Types;
namespace MAPS.Views
{
public partial class AboutPage : ContentPage
{
IlocationUpdateService loc;
public AboutPage()
{
InitializeComponent();
// Task.Delay(2000);
UpdateMap();
}
async void OnActionSheetCancelDeleteClicked()
{
bool answer = await DisplayAlert("Location Request", "Please enable location services to use this app", "Settings", "Cancel");
if (answer == true)
{
DependencyService.Get<ILocSettings>().OpenSettings();
}
}
protected override void OnAppearing()
{
base.OnAppearing();
bool gpsStat = DependencyService.Get<ILocSettings>().isGpsAvailable();
if (gpsStat == false)
{
OnActionSheetCancelDeleteClicked();
}
loc = DependencyService.Get<IlocationUpdateService>();
loc.LocationChanged += (object sender, ILocationEventArgs args) =>
{
String lat1 = args.Latitude.ToString();
String lng1 = args.Longitude.ToString();
//String lat1 = "55.099300";
// String lng1 = "-8.279740";
UpdateMap3(lat1, lng1); ;
};
loc.GetUsedLocation();
}
protected override void OnDisappearing()
{
base.OnDisappearing();
loc = null;
}
List<Place> placesList = new List<Place>();
private async void UpdateMap()
{
var assembly = IntrospectionExtensions.GetTypeInfo(typeof(AboutPage)).Assembly;
Stream stream = assembly.GetManifestResourceStream("MAPS.Places.json");
string text = string.Empty;
using (var reader = new StreamReader(stream))
{
text = reader.ReadToEnd();
}
var resultObject = JsonConvert.DeserializeObject<Places>(text);
var request = new Xamarin.Essentials.GeolocationRequest(GeolocationAccuracy.Best, TimeSpan.FromSeconds(30));
var location = await Geolocation.GetLocationAsync(request);
CustomMap customMap = new CustomMap()
{
IsShowingUser = true
};
customMap.CustomPins = new List<CustomPin>(); // put this before the foreach
foreach (var place in resultObject.results)
{
Location location1 = new Location(place.geometry.location.lat,place.geometry.location.lng);
// string color = getDist(location1, location);
string color = "purple";
if (color == "purple")
{
CustomPin pin = new CustomPin()
{
Type = PinType.Place,
Position = new Position(place.geometry.location.lat, place.geometry.location.lng),
Label = place.id,
Address = place.vicinity+"*",
Name = "Xamarin",
icon = "icon.png",
Url = "http://xamarin.com/about/"
};
customMap.Pins.Add(pin);
}
else
{
CustomPin pin = new CustomPin()
{
Type = PinType.Place,
Position = new Position(place.geometry.location.lat, place.geometry.location.lng),
Label = place.id,
Address = place.vicinity,
Name = "Xamarin",
icon = "pin.png",
Url = "http://xamarin.com/about/"
};
customMap.Pins.Add(pin);
}
}
customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(location.Latitude, location.Longitude), Distance.FromKilometers(0.15))); ;
Content = customMap;
}
public string getDist(Location loc, Xamarin.Essentials.Location currentLoc)
{
string color = "red";
// bool geo = false;
double latEnd = loc.lat;
double lngEnd = loc.lng;
/// Position(currentLoc.lat, currentLoc.lng);
double dist = currentLoc.CalculateDistance(latEnd, lngEnd, DistanceUnits.Kilometers);
if (dist < 0.05) //5m distance
{
color = "purple";
}
else
{
color = "red";
}
return color;
}
public void getNewPins()
{
InitializeComponent();
}
public void getPin()
{
var pr = new PopUp();
}
private async void UpdateMap3(String lat, String lng)
{
var assembly = IntrospectionExtensions.GetTypeInfo(typeof(AboutPage)).Assembly;
Stream stream = assembly.GetManifestResourceStream("MAPS.Places.json");
string text = string.Empty;
using (var reader = new StreamReader(stream))
{
text = reader.ReadToEnd();
}
var resultObject = JsonConvert.DeserializeObject<Places>(text);
CustomMap customMap = new CustomMap()
{
IsShowingUser = true
};
customMap.CustomPins = new List<CustomPin>(); // put this before the foreach
foreach (var place in resultObject.results)
{
Location location1 = new Location(place.geometry.location.lat, place.geometry.location.lng);
Xamarin.Essentials.Location location = new Xamarin.Essentials.Location(Convert.ToDouble(lat), Convert.ToDouble(lng));
string color = getDist(location1, location);
if (color == "purple")
{
CustomPin pin2 = new CustomPin()
{
Type = PinType.Place,
Position = new Position(place.geometry.location.lat, place.geometry.location.lng),
Label = place.id,
Address = place.vicinity,
Name = "Xamarin",
icon = "icon.png",
Url = "http://xamarin.com/about/"
};
customMap.CustomPins = new List<CustomPin> {pin2};
customMap.Pins.Add(pin2);
}
else
{
CustomPin pin2 = new CustomPin()
{
Type = PinType.Place,
Position = new Position(place.geometry.location.lat, place.geometry.location.lng),
Label = place.id,
Address = place.vicinity+"*",
Name = "Xamarin",
icon = "pin.png",
Url = "http://xamarin.com/about/"
};
customMap.CustomPins = new List<CustomPin> { pin2 };
customMap.Pins.Add(pin2);
// Content.IsEnabled = true;
// customMap.CustomPins.Remove(pin);
}
}
// customMap.Pins.Clear();
// customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(Convert.ToDouble(lat), Convert.ToDouble(lng)), Distance.FromKilometers(0.15))); ;
// Content = customMap;
// customMap.Pins.Add(pins);
}
}
}
Below is my forms page markup.
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MAPS;assembly=MAPS"
x:Class="MAPS.Views.AboutPage" Title="Explore">
<StackLayout>
<local:CustomMap x:Name="customMap" IsShowingUser="True"
MapType="Street" />
</StackLayout>
</ContentPage>
Below is my Android custom renderer
using Android.Content;
using Android.Gms.Maps;
using Android.Gms.Maps.Model;
using Android.Widget;
using MAPS;
using MAPS.Droid;
using MAPS.Views;
using Newtonsoft.Json;
using Rg.Plugins.Popup;
using Rg.Plugins.Popup.Animations;
using Rg.Plugins.Popup.Contracts;
using Rg.Plugins.Popup.Enums;
using Rg.Plugins.Popup.Services;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
using Xamarin.Forms.Maps.Android;
using static MAPS.Droid.CustomMapRenderer;
[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace MAPS.Droid
{
public class CustomMapRenderer : Xamarin.Forms.Maps.Android.MapRenderer, GoogleMap.IInfoWindowAdapter
{
List<CustomPin> customPins;
public string popInfo;
public CustomMapRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Map> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
NativeMap.InfoWindowClick -= OnInfoWindowClick;
}
if (e.NewElement != null)
{
var formsMap = (CustomMap)e.NewElement;
customPins = formsMap.CustomPins;
Control.GetMapAsync(this);
}
}
protected override void OnMapReady(GoogleMap map)
{
base.OnMapReady(map);
NativeMap.InfoWindowClick += OnInfoWindowClick;
NativeMap.SetInfoWindowAdapter(this);
}
protected override MarkerOptions CreateMarker(Pin pin)
{
var marker = new MarkerOptions();
// CustomPin p = new CustomPin();
//foreach (var cp in customPins)
//{
// if (cp.Position == pin.Position)
// {
// p = cp;
// }
//}
marker.SetPosition(new LatLng(pin.Position.Latitude, pin.Position.Longitude));
marker.SetTitle(pin.Label);
// marker.SetIcon(BitmapDescriptorFactory.FromFile(p.icon));
if (pin.Address.Contains('*'))
{
marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.pin2));
}
else
{
marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.pin));
}
marker.Visible(true);
var a = NativeMap.AddMarker(marker);
a.ShowInfoWindow();
// marker.SetSnippet(pin.Address.Replace("*", " "));
return marker;
}
void OnInfoWindowClick(object sender, GoogleMap.InfoWindowClickEventArgs e)
{
getPlaceData(markerdata.markerData.title, markerdata.markerData.lat, markerdata.markerData.lng);
showPopUp();
}
public Android.Views.View GetInfoContents(Marker marker)
{
return null;
}
public void myMod(Marker marker)
{
}
public Android.Views.View GetInfoWindow(Marker marker)
{
markerdata.markerData.title = marker.Title;
markerdata.markerData.lat = marker.Position.Latitude.ToString("0.#####");
markerdata.markerData.lng = marker.Position.Longitude.ToString("0.#####");
// ds.Id = marker.Id;
// getPlaceData(marker.Title, marker.Position.Latitude.ToString("0.#####"), marker.Position.Longitude.ToString("0.#####"));
// showPopUp();
return null;
}
public string Number;
private async void showPopUp()
{
var Pr = new Views.PopUp();
var scaleAnimation = new ScaleAnimation
{
PositionIn = MoveAnimationOptions.Right,
PositionOut = MoveAnimationOptions.Left
};
Pr.Animation = scaleAnimation;
await PopupNavigation.PushAsync(Pr);
}
CustomPin GetCustomPin(Marker annotation)
{
return null;
}
private void getPlaceData(String name, String Lat, String Lng)
{
var assembly = IntrospectionExtensions.GetTypeInfo(typeof(AboutPage)).Assembly;
Stream stream = assembly.GetManifestResourceStream("MAPS.Places.json");
string text = string.Empty;
using (var reader = new StreamReader(stream))
{
text = reader.ReadToEnd();
}
var resultObject = JsonConvert.DeserializeObject<Places>(text);
foreach (var place in resultObject.results)
{
if((name==place.id)&&(Lat ==place.geometry.location.lat.ToString("0.#####"))&&(Lng ==place.geometry.location.lng.ToString("0.#####")))
{
getData.Instance.Id = place.id;
getData.Instance.lat = place.geometry.location.lat.ToString("0.#####");
getData.Instance.lng = place.geometry.location.lng.ToString("0.#####");
getData.Instance.marker2 = place.name;
getData.Instance.family = place.family;
getData.Instance.origin = place.Origin;
getData.Instance.date = place.Date;
getData.Instance.commonName = place.CommonName;
// getData.Instance.title = marker.Title;
}
}
}
}
}
Hi I am new to programming, but currently I encounter xamarin forms cannot implicitly convert type 'system.threading.tasks.task> to system.collections.generic.List as I am trying to use global variable upon launching the app to optimized the app when I am trying to set the List of menu items into the global variable which will be access by the other pages, it gave me that error. I have no idea how to solve that issue so someone please help me
Here is my App.cs
private static int globalVariable = 1;
public static List<MenuItemModel> foodList = new List<MenuItemModel>();
private static List<MenuItemModel> beverageList = new List<MenuItemModel>();
public static int GlobalVariable
{
get { return globalVariable; }
set { globalVariable = value; }
}
public static List<MenuItemModel> FoodList
{
get { return foodList; }
set { foodList = value; }
}
public static List<MenuItemModel> BeverageList
{
get { return beverageList; }
set { beverageList = value; }
}
public App()
{
GlobalVariable = 10;
BeverageList = getBeverageList();
FoodList = getFoodList();
}
public async Task<List<MenuItemModel>> getBeverageList()
{
ConstantCS constant = new ConstantCS();
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://172.20.129.44/");
// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = new HttpResponseMessage();
response = client.GetAsync("WebServices/menu.svc/GetBeveragesJSON").Result;
if (response.IsSuccessStatusCode)
{
string jsonString = await response.Content.ReadAsStringAsync();
dynamic dynamicObject = JsonConvert.DeserializeObject(jsonString);
int itemId_;
string itemName_;
string itemCategory_;
string itemSubCategory_;
string itemDescription_;
string itemImage_;
int itemQuantity_;
double itemPrice_;
string itemStatus_;
string itemAddOn_;
for (int i = 0; i < dynamicObject.d.Count; i++)
{
itemId_ = dynamicObject.d[i]["itemID"];
itemName_ = dynamicObject.d[i]["itemName"].ToString();
itemCategory_ = dynamicObject.d[i]["itemCategory"].ToString();
itemSubCategory_ = dynamicObject.d[i]["itemSubCategory"].ToString();
itemDescription_ = dynamicObject.d[i]["itemDesc"].ToString();
itemImage_ = dynamicObject.d[i]["itemImg"].ToString();
itemQuantity_ = int.Parse(dynamicObject.d[i]["itemQty"].ToString());
itemPrice_ = double.Parse(dynamicObject.d[i]["itemPrice"].ToString());
itemStatus_ = dynamicObject.d[i]["itemStatus"].ToString();
itemAddOn_ = dynamicObject.d[i]["itemRequest"].ToString();
string itemURL_ = constant.PhotoBaseURL + itemImage_;
beverageList.Add(new MenuItemModel(itemId_, itemName_, itemCategory_, itemSubCategory_, itemDescription_, itemURL_, itemQuantity_, itemPrice_, itemStatus_, itemAddOn_));
}
}
else
{
//Debug.WriteLine("It entered else not if");
}
return beverageList;
}
The error that was shown
Warp an extra async Method into your constructor:
public App()
{
Initialize(); //no need to await this
}
public async Task Initialize()
{
GlobalVariable = 10;
BeverageList = await getBeverageList(); //use await here!
FoodList = await getFoodList(); //use await here!
}
now you can await the results of getFoodList() and getBeverageList().
Otherwise the Task itself is returned. Which leads to your error:
Cannot implicitly convert type 'System.Threading.Tasks.Task' to
'System.Collections.Generic.List< MenuItemModel >.
I just want to re-size image without losing quality
can I use this ?
[HttpPost]
public ActionResult Index(HttpPostedFileBase file)
{
WebImage img = new WebImage(file.InputStream);
if (img.Width > 1000)
img.Resize(1000, 1000);
img.Save("path");
return View();
}
or WebImage resize but loss image quality ?
thanks
Here is a code I use. Call ResizeImage method in your action.
public class Size
{
public Size(int width, int height)
{
Width = width;
Height = height;
}
public int Width { get; set; }
public int Height { get; set; }
}
public static bool ResizeImage(string orgFile, string resizedFile, ImageFormat format, int width, int height)
{
try
{
using (Image img = Image.FromFile(orgFile))
{
Image thumbNail = new Bitmap(width, height, img.PixelFormat);
Graphics g = Graphics.FromImage(thumbNail);
g.CompositingQuality = CompositingQuality.HighQuality;
g.SmoothingMode = SmoothingMode.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
Rectangle rect = new Rectangle(0, 0, width, height);
g.DrawImage(img, rect);
thumbNail.Save(resizedFile, format);
}
return true;
}
catch (Exception)
{
return false;
}
}
Taken from http://www.codeproject.com/Tips/481015/Rename-Resize-Upload-Image-ASP-NET-MVC.
It is say to firstly create a class for image to save (I have just copy and paste)
public class ImageResult
{
public bool Success { get; set; }
public string ImageName { get; set; }
public string ErrorMessage { get; set; }
}
then you need another class with method to save (i have just copy and paste)
public class ImageUpload
{
// set default size here
public int Width { get; set; }
public int Height { get; set; }
// folder for the upload, you can put this in the web.config
private readonly string UploadPath = "~/Images/Items/";
public ImageResult RenameUploadFile(HttpPostedFileBase file, Int32 counter = 0)
{
var fileName = Path.GetFileName(file.FileName);
string prepend = "item_";
string finalFileName = prepend + ((counter).ToString()) + "_" + fileName;
if (System.IO.File.Exists
(HttpContext.Current.Request.MapPath(UploadPath + finalFileName)))
{
//file exists => add country try again
return RenameUploadFile(file, ++counter);
}
//file doesn't exist, upload item but validate first
return UploadFile(file, finalFileName);
}
private ImageResult UploadFile(HttpPostedFileBase file, string fileName)
{
ImageResult imageResult = new ImageResult { Success = true, ErrorMessage = null };
var path =
Path.Combine(HttpContext.Current.Request.MapPath(UploadPath), fileName);
string extension = Path.GetExtension(file.FileName);
//make sure the file is valid
if (!ValidateExtension(extension))
{
imageResult.Success = false;
imageResult.ErrorMessage = "Invalid Extension";
return imageResult;
}
try
{
file.SaveAs(path);
Image imgOriginal = Image.FromFile(path);
//pass in whatever value you want
Image imgActual = Scale(imgOriginal);
imgOriginal.Dispose();
imgActual.Save(path);
imgActual.Dispose();
imageResult.ImageName = fileName;
return imageResult;
}
catch (Exception ex)
{
// you might NOT want to show the exception error for the user
// this is generally logging or testing
imageResult.Success = false;
imageResult.ErrorMessage = ex.Message;
return imageResult;
}
}
// you can also create an Mvc dataannotation to validate the extension of image in both server side and client side
// don't forget to add (.JPG, .JPEG or .PNG on these extension, because you can facing this type of problem
private bool ValidateExtension(string extension)
{
extension = extension.ToLower();
switch (extension)
{
case ".jpg":
return true;
case ".png":
return true;
case ".gif":
return true;
case ".jpeg":
return true;
default:
return false;
}
}
private Image Scale(Image imgPhoto)
{
float sourceWidth = imgPhoto.Width;
float sourceHeight = imgPhoto.Height;
float destHeight = 0;
float destWidth = 0;
int sourceX = 0;
int sourceY = 0;
int destX = 0;
int destY = 0;
// force resize, might distort image
if (Width != 0 && Height != 0)
{
destWidth = Width;
destHeight = Height;
}
// change size proportially depending on width or height
else if (Height != 0)
{
destWidth = (float)(Height * sourceWidth) / sourceHeight;
destHeight = Height;
}
else
{
destWidth = Width;
destHeight = (float)(sourceHeight * Width / sourceWidth);
}
Bitmap bmPhoto = new Bitmap((int)destWidth, (int)destHeight,
PixelFormat.Format32bppPArgb);
bmPhoto.SetResolution(imgPhoto.HorizontalResolution, imgPhoto.VerticalResolution);
Graphics grPhoto = Graphics.FromImage(bmPhoto);
grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;
//you can also add these properties to improve the quality of saved image
grPhoto.SmoothingMode = SmoothingMode.HighQuality;
grPhoto.CompositingQuality = CompositingQuality.HighQuality;
grPhoto.PixelOffsetMode = PixelOffsetMode.HighQuality;
grPhoto.DrawImage(imgPhoto,
new Rectangle(destX, destY, (int)destWidth, (int)destHeight),
new Rectangle(sourceX, sourceY, (int)sourceWidth, (int)sourceHeight),
GraphicsUnit.Pixel);
grPhoto.Dispose();
return bmPhoto;
}
//you can also create another method to verify if a saved image with similar name exist and use it in som method of controller like (Modify your account
public ImageResult VerifyUploadFile(HttpPostedFileBase file)
{
var fileName = Path.GetFileName(file.FileName);
string finalFileName = UploadPath + fileName;
// si une telle image existe déjà, renvoyer le nom du fichier et dire que le succes est faux
if (System.IO.File.Exists
(HttpContext.Current.Request.MapPath(UploadPath + finalFileName)))
{
//file exists => sucess is false
return new ImageResult { Success = false, ErrorMessage = null, ImageName =finalFileName };
}
//file doesn't exist, upload item but validate first
return RenameUploadFile(file);
}
}
You can use it after in the controller depending of your need
[HttpPost]
public ActionResult Index(FormCollection formCollection)
{
foreach (string item in Request.Files)
{
HttpPostedFileBase file = Request.Files[item] as HttpPostedFileBase;
if (file.ContentLength == 0)
continue;
if (file.ContentLength > 0)
{
// width + height will force size, care for distortion
//Exmaple: ImageUpload imageUpload = new ImageUpload { Width = 800, Height = 700 };
// height will increase the width proportionally
//Example: ImageUpload imageUpload = new ImageUpload { Height= 600 };
// width will increase the height proportionally
ImageUpload imageUpload = new ImageUpload { Width= 600 };
// rename, resize, and upload
//return object that contains {bool Success,string ErrorMessage,string ImageName}
ImageResult imageResult = imageUpload.RenameUploadFile(file);
if (imageResult.Success)
{
//TODO: write the filename to the db
Console.WriteLine(imageResult.ImageName);
}
else
{
// use imageResult.ErrorMessage to show the error
ViewBag.Error = imageResult.ErrorMessage;
}
}
}
return View();
}
You can use verifyupload at your need.
var imagePhysicalPath = #"c://image.jpg";
var newImagePhysicalPath = #"c://new-image.jpg";
var image = new System.Web.Helpers.WebImage(imagePhysicalPath)
.Resize(width + 1, height + 1, false, true)//+1 because webimage use 1px for border
.Crop(1, 1) //remove border
.Save(newImagePhysicalPath);
Can anyone help me to take a full page screenshot using Selenium webdriver. I am using c#/Nunit. The current method i am using is not taking the full browser page.
I am using the code below to take the screenshot.
public void TakeScreenShot(IWebDriver webDriver,string testName,string className)
{
string folderName = String.Format("{0}.{1}", className, testName);
// Create Screenshot folder
string createdFolderLocation = CreateFolder(folderName);
// Take the screenshot
Screenshot ss = ((ITakesScreenshot)webDriver).GetScreenshot();
string screenshot = ss.AsBase64EncodedString;
byte[] screenshotAsByteArray = ss.AsByteArray;
// Save the screenshot
ss.SaveAsFile((string.Format("{0}\\{1}",createdFolderLocation,testName + ".Jpeg")), System.Drawing.Imaging.ImageFormat.Jpeg);
ss.ToString();
}
You can use this package https://www.nuget.org/packages/Noksa.WebDriver.ScreenshotsExtensions/
In order to take a screenshot of the entire page, use the VerticalCombineDecorator:
var vcs = new VerticalCombineDecorator(new ScreenshotMaker());
var screen = _driver.TakeScreenshot(vcs);
"Full-page" screenshots are defined by WebDriver to include the entirety of the page displayed in the browser, not the browser chrome (URL bar, toolbar, window resizing handles, and so on). If you don't care about getting the full DOM in your screenshot, you don't need to use WebDriver to get your screenshot. You can use the API of your operating system to handle that instead.
This one I used in our solution:
public byte[] TakeScreenshot()
{
try
{
var getMaxSide = "return Math.max(document.body.scroll{0}, document.body.offset{0}, document.documentElement.client{0}, document.documentElement.scroll{0}, document.documentElement.offset{0})";
var scrollHeight = (Driver as IJavaScriptExecutor).ExecuteScript(string.Format(getMaxSide, "Height"));
var scrollWidth = (Driver as IJavaScriptExecutor).ExecuteScript(string.Format(getMaxSide, "Width"));
Driver.Manage().Window.Size = new Size(int.Parse(scrollWidth.ToString()), int.Parse(scrollHeight.ToString()));
return (Driver as ITakesScreenshot).GetScreenshot().AsByteArray;
}
catch
{
return Array.Empty<byte>();
}
}
Then you can use the result to attach it to e.g. Allure or NUnit test results:
private void AttachScreenshot()
{
var screenshot = _browser?.TakeScreenshot();
if (screenshot.Length > 0)
{
// add screenshot to test results
var path = DateTime.Now.Ticks.ToString() + ".png";
File.WriteAllBytes(path, screenshot);
TestContext.AddTestAttachment(path, "screenshot");
// attach screenshot to Allure report
AllureLifecycle.Instance.AddAttachment("screenshot", "image/png", screenshot);
}
}
Try changing the size of the browser window to something huge before taking your screen shot. I have the size to 10 less than the width, and 10 less than the height. Try adding rather than subtracting.
driver = new FirefoxDriver(firefoxProfile);
if (Config.MAXIMIZE_BROWSER_WINDOW)
{
driver.Manage().Window.Size = new System.Drawing.Size(System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Width - 10, System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height - 10);
}
you may try this
IWebDriver driver = new PhantomJSDriver();
driver.Navigate().GoToUrl("http://www.google.com");
((ITakesScreenshot)driver).GetScreenshot().SaveAsFile("image.png", ImageFormat.Png);
Greetings from 2017))!
If the page size is larger than the screen size - you can use the PhantomJS driver (PhantomJS download page)
var fileName = "test.png";
var size = new Size(800, 2000);
var url = "https://stackoverflow.com/";
using (var driver = new PhantomJSDriver())
{
driver.Manage().Window.Size = size;
driver.Navigate().GoToUrl(url);
((ITakesScreenshot)driver)
.GetScreenshot()
.SaveAsFile(fileName, ImageFormat.Png);
driver.Close();
}
I remeber that ((ITakesScreenshot)webDriver).GetScreenshot(); takes full page screenshot but if you have some ajax request and other loading elements you can add scrolling and at the end to wait some seconds, after that you will know that it took full loaded page screenshot.
for (int second = 0;; second++)
{
if (second >= 4)
{
break;
}
((IJavaScriptExecutor)Global.Driver).ExecuteScript("window.scrollBy(0,800)", string.Empty);
Thread.Sleep(500);
}
Thread.Sleep(3000);
Try this hope it will work fine for u.
public void TakeScreenshot(string SSName)
{
try
{
string path = "D:\\WorkSpace\\Screenshot\\";
Screenshot ss = ((ITakesScreenshot)driver).GetScreenshot();
ss.SaveAsFile((path + SSName), System.Drawing.Imaging.ImageFormat.Jpeg);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
throw;
}
}
Changing browser height doesn't always work. This is the solution I used. It scrolls through the page and composes the full-page screenshot.
public static Image TakeFullPageScreenshot(this RemoteWebDriver driver, int maxHeight = 10000)
{
Bitmap fullPageScreenshot = null;
using (var fullMs = new MemoryStream((driver.GetScreenshot()).AsByteArray)) {
fullPageScreenshot = Image.FromStream(fullMs) as Bitmap;
}
var originalPageOffset = driver.GetPageOffset();
var prevPageOffset = 0;
var currentPageOffset = 0;
var scrollLength = (int)(driver.Manage().Window.Size.Height / 1.5);
while (fullPageScreenshot.Height < maxHeight)
{
prevPageOffset = driver.GetPageOffset().Y;
driver.ScrollPageBy(0, scrollLength);
System.Threading.Thread.Sleep(500);
currentPageOffset = driver.GetPageOffset().Y;
if (prevPageOffset == currentPageOffset)
{
break;
}
var pageMovedBy = currentPageOffset - prevPageOffset;
using (var ms = new MemoryStream(driver.GetScreenshot().AsByteArray))
{
using (var viewPortScreenshot = Image.FromStream(ms) as Bitmap)
{
var croppedScreenshot = CropBitmapAtRect(viewPortScreenshot, new Rectangle(0, viewPortScreenshot.Height - pageMovedBy, viewPortScreenshot.Width, pageMovedBy));
var newFullPage = AppendBitmap(fullPageScreenshot, croppedScreenshot);
fullPageScreenshot.Dispose();
fullPageScreenshot = newFullPage;
}
}
}
driver.ScrollPageTo(originalPageOffset.X, originalPageOffset.Y);
return fullPageScreenshot;
}
public static Bitmap CropBitmapAtRect(Bitmap b, Rectangle r)
{
Bitmap nb = new Bitmap(r.Width, r.Height);
using (Graphics g = Graphics.FromImage(nb))
{
g.DrawImage(b, -r.X, -r.Y);
return nb;
}
}
public static Bitmap AppendBitmap(Bitmap source, Bitmap target, int spacing = 0)
{
int w = Math.Max(source.Width, target.Width);
int h = source.Height + target.Height + spacing;
Bitmap bmp = new Bitmap(w, h);
using (Graphics g = Graphics.FromImage(bmp))
{
g.DrawImage(source, 0, 0);
g.DrawImage(target, 0, source.Height + spacing);
}
return bmp;
}
public static void ScrollPageBy(this RemoteWebDriver driver, int x = 0, int y = 0)
{
driver.ExecuteScript(#"window.scroll(window.pageXOffset + arguments[0], window.pageYOffset + arguments[1]);", x, y);
}
public static void ScrollPageTo(this RemoteWebDriver driver, int x = 0, int y = 0)
{
driver.ExecuteScript(#"window.scroll(arguments[0], arguments[1]);", x, y);
}
public static Point GetPageOffset(this RemoteWebDriver driver)
{
var offsetArray = driver.ExecuteScript(#"return [window.pageXOffset, window.pageYOffset];") as ReadOnlyCollection<object>;
var x = (long)offsetArray[0];
var y = (long)offsetArray[1];
return new Point((int)x, (int)y);
}
based on the answer from #Michal Kalous I created an etension class.
This also takes into account the font size currently set in widows and the real viewport size and removes the vertical scrollbar by setting body.style.overflowY to hidden.
Usage
RemoteWebDriver driver = new EdgeDriver();
driver.SetViewportSize(1200, 1200);
driver.Navigate().GoToUrl("https://www.bikereview.info/en/ktm-1290-super-duke-rr-innerhalb-von-48-minuten-ausverkauft.html");
Image tempImage = driver.TakeFullPageScreenshot();
tempImage.Save(#"c:\full.png", ImageFormat.Png);
driver.Close();
driver.Quit();
Extension-Class
using System;
using System.Drawing;
using System.IO;
using OpenQA.Selenium.Remote;
using System.Collections.ObjectModel;
using System.Runtime.InteropServices;
using OpenQA.Selenium;
namespace TestRenderHtmlToPng
{
public static class RemoteWebDriverExtensions
{
public static Image TakeFullPageScreenshot(this RemoteWebDriver driver, int maxHeight = 10000)
{
//Screenshots depend on fontscaleing-property in windows
double DpiScalingFactor = GetDpiScalingFactor();
Bitmap fullPageScreenshot = null;
using (var fullMs = new MemoryStream((driver.GetScreenshotOverflowHidden()).AsByteArray))
{
fullPageScreenshot = Image.FromStream(fullMs) as Bitmap;
}
var originalPageOffset = driver.GetPageOffset();
var prevPageOffset = 0;
var currentPageOffset = 0;
var scrollLength = driver.GetWindowInnerHeight();
while (fullPageScreenshot.Height < maxHeight)
{
prevPageOffset = driver.GetPageOffset().Y;
driver.ScrollPageBy(0, scrollLength);
System.Threading.Thread.Sleep(100);
currentPageOffset = driver.GetPageOffset().Y;
if (prevPageOffset == currentPageOffset)
{
break;
}
var pageMovedBy = currentPageOffset - prevPageOffset;
pageMovedBy = (int)(pageMovedBy * DpiScalingFactor);
using (var ms = new MemoryStream(driver.GetScreenshotOverflowHidden().AsByteArray))
{
Bitmap fullPageScreenshot1 = Image.FromStream(ms) as Bitmap;
using (var viewPortScreenshot = Image.FromStream(ms) as Bitmap)
{
var s = driver.Manage().Window.Size;
var croppedScreenshot = CropBitmapAtRect(viewPortScreenshot, new Rectangle(0, viewPortScreenshot.Height - pageMovedBy, viewPortScreenshot.Width, pageMovedBy));
var newFullPage = AppendBitmap(fullPageScreenshot, croppedScreenshot);
fullPageScreenshot.Dispose();
fullPageScreenshot = newFullPage;
}
}
}
driver.ScrollPageTo(originalPageOffset.X, originalPageOffset.Y);
return fullPageScreenshot;
}
private static Bitmap CropBitmapAtRect(Bitmap b, Rectangle r)
{
Bitmap nb = new Bitmap(r.Width, r.Height);
using (Graphics g = Graphics.FromImage(nb))
{
g.DrawImage(b, -r.X, -r.Y);
return nb;
}
}
private static Bitmap AppendBitmap(Bitmap source, Bitmap target, int spacing = 0)
{
int w = Math.Max(source.Width, target.Width);
int h = source.Height + target.Height + spacing;
Bitmap bmp = new Bitmap(w, h);
using (Graphics g = Graphics.FromImage(bmp))
{
g.DrawImage(source, 0, 0);
g.DrawImage(target, 0, source.Height + spacing);
}
return bmp;
}
private static Screenshot GetScreenshotOverflowHidden(this RemoteWebDriver driver)
{
driver.ExecuteScript(#" document.body.style.overflowY = ""hidden"";");
var s = driver.GetScreenshot();
driver.ExecuteScript(#" document.body.style.overflowY = """";");
return s;
}
private static void ScrollPageBy(this RemoteWebDriver driver, int x = 0, int y = 0)
{
driver.ExecuteScript(#"window.scroll(window.pageXOffset + arguments[0], window.pageYOffset + arguments[1]);", x, y);
}
private static void ScrollPageTo(this RemoteWebDriver driver, int x = 0, int y = 0)
{
driver.ExecuteScript(#"window.scroll(arguments[0], arguments[1]);", x, y);
}
public static void SetViewportSize(this RemoteWebDriver driver, int width, int height)
{
var jsGetPadding = #"return [ window.outerWidth - window.innerWidth,window.outerHeight - window.innerHeight ];";
var paddingArray = driver.ExecuteScript(jsGetPadding) as ReadOnlyCollection<object>;
driver.Manage().Window.Size = new Size(width + int.Parse(paddingArray[0].ToString()), height + int.Parse(paddingArray[1].ToString()));
}
private static Point GetPageOffset(this RemoteWebDriver driver)
{
var offsetArray = driver.ExecuteScript(#"return [window.pageXOffset, window.pageYOffset];") as ReadOnlyCollection<object>;
var x = int.Parse(offsetArray[0].ToString());
var y = int.Parse(offsetArray[1].ToString().Split(',')[0]);
return new Point((int)x, (int)y);
}
private static int GetWindowInnerHeight(this RemoteWebDriver driver)
{
var Value = driver.ExecuteScript(#"return [window.innerHeight];") as ReadOnlyCollection<object>;
return int.Parse(Value[0].ToString());
}
[DllImport("gdi32.dll")]
private static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
public enum DeviceCap
{
VERTRES = 10,
DESKTOPVERTRES = 117,
// http://pinvoke.net/default.aspx/gdi32/GetDeviceCaps.html
// https://stackoverflow.com/questions/5977445/how-to-get-windows-display-settings#answer-21450169
}
private static float GetDpiScalingFactor()
{
Graphics g = Graphics.FromHwnd(IntPtr.Zero);
IntPtr desktop = g.GetHdc();
int LogicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.VERTRES);
int PhysicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.DESKTOPVERTRES);
float ScreenScalingFactor = (float)PhysicalScreenHeight / (float)LogicalScreenHeight;
return ScreenScalingFactor; // 1.25 = 125%
}
}
}
I am using the blitting technique that Jeff from 8bitrocket.com uses for creating tiles. I am trying to paint 2 layers of bitmapdata onto a bitmap. One the first layer is the background ( 1 image). and the second layer is the tiles. In that class below. the updateMap is the method that gets called in the loop to repaint the image.
package com.eapi
{
/**
* ...
* #author Anthony Gordon
*/
import com.objects.XmlManager;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.*;
import flash.display.BitmapData;
import flash.display.Bitmap
import flash.geom.Rectangle;
import flash.geom.Point;
import flash.display.DisplayObject;
public class EngineApi extends MovieClip
{
public var images:Array;
public var world:Array;
//w stands for world, how big it is in columns and rows
private var wCols:Number = 50;
private var wRows:Number = 16;
public var wWidth:Number;
public var wHeight:Number;
//v stands for view, which means your field of view
public var vRows:Number;
public var vCols:Number;
public var vWidth:Number = 540;
public var vHeight:Number = 360;
//how big your indivual tile is
public var tileW:Number = 80;
public var tileH:Number = 80;
public var offsX:Number = 0;
public var offsY:Number = 0;
public var xEnd:Number = 0;
public var yEnd:Number = 0;
public var tilex:int;
public var tiley:int;
public var scrollx:Number = 0;
public var scrolly:Number = 0;
private var screen:Bitmap;
private var canvas:BitmapData;
private var buffer:BitmapData;
public var mapHolder:Array;
private var scrollLoop:Boolean;
private var minLoop:Number;
private var maxLoop:Number;
public var currentMap:Number = 0;
private var queue:Array;
public var currentCol:Number = 0;
public var currentRow:Number = 0;
public var enviroment:Array;
public var currentTileSheet:Number = 0;
private var layer1:Sprite;
private var layer2:Sprite;
private var layer3:Sprite;
private var layer4:Sprite;
private var layer5:Sprite;
public var background:BitmapData
protected var stageObject:Array;
protected var gameObjects:Array;
public function EngineApi(w:Number = 540,h:Number = 360, tw:Number = 50, th:Number = 50)
{
stageObject = new Array();
gameObjects = new Array();
//Add Layers
layer1 = new Sprite();
layer2 = new Sprite();
layer3 = new Sprite();
layer4 = new Sprite();
layer5 = new Sprite();
//end
images = new Array();
vWidth = w;
vHeight = h;
tileW = tw;
tileH = th;
queue = new Array();
mapHolder = new Array();
vCols = Math.floor(vWidth/tileW);
vRows = Math.floor(vHeight/tileH);
wWidth = wCols * tileW;
wHeight = wRows * tileH;
canvas = new BitmapData(vWidth,vHeight,true,0x000000);
buffer = new BitmapData(vWidth + 2 * tileW, vHeight + 2 * tileH ,false,0x000000);
screen = new Bitmap(canvas);
addChild(screen);
addChild(layer1);
addChild(layer2);
addChild(layer3);
addChild(layer4);
addChild(layer5);
}
public function addGameChild(object:IGameObject, layer:Number):void
{
switch(layer)
{
case 1:
layer1.addChild(DisplayObject(object));
break;
case 2:
layer2.addChild(DisplayObject(object));
break;
case 3:
layer3.addChild(DisplayObject(object));
break;
case 4:
layer4.addChild(DisplayObject(object));
break;
case 5:
layer5.addChild(DisplayObject(object));
break;
default:
}
if (object.IsDisplay == true)
gameObjects.push(object);
stageObject.push(object);
}
public function UpDateMap():void
{
offsX += scrollx;
offsY += scrolly;
tilex = int(offsX/tileW);
tiley = int(offsY/tileH);
xEnd = tilex + vWidth;
yEnd = tiley + vHeight;
var tileNum:int;
var tilePoint:Point = new Point(0,0);
var tileRect:Rectangle = new Rectangle(0, 0, tileW, tileH);
var rowCtr:int=0;
var colCtr:int=0;
for (rowCtr=0; rowCtr <= vRows; rowCtr++) {
for (colCtr = 0; colCtr <= vCols; colCtr++) {
currentCol = colCtr+tilex;
currentRow = rowCtr+tiley;
tileNum = mapHolder[currentMap][rowCtr+tiley][colCtr+tilex];
tilePoint.x = colCtr * tileW;
tilePoint.y = rowCtr * tileH;
tileRect.x = int((tileNum % 100))* tileW;
tileRect.y = int((tileNum / 100))* tileH;
buffer.copyPixels(images[currentTileSheet],tileRect,tilePoint);
}
}//End Loop
var bgRect:Rectangle = new Rectangle(0, 0, 544, 510);
var bgPoint:Point = new Point(0, 0);
var bufferRect:Rectangle = new Rectangle(0,0,vWidth,vHeight);
var bufferPoint:Point = new Point();
bufferRect.x = offsX % tileW;
bufferRect.y = offsY % tileH;
canvas.copyPixels(background,bgRect,bgPoint);
canvas.copyPixels(buffer,bufferRect,bufferPoint);
}//End UpdateMap
public function StartRender():void
{
addEventListener(Event.ENTER_FRAME, loop);
}
protected function loop(e:Event):void
{
UpDateMap();
UpdateObjects();
}
protected function UpdateObjects():void
{
for (var i:Number = 0; i < stageObject.length; i++)
{
stageObject[i].UpdateObject();
}
for (var g:Number = 0; g < stageObject.length; g++)
{
if (stageObject[g].Garbage && stageObject[g].IsDisplay)
{
removeChild(DisplayObject(stageObject[g]));
stageObject[g] = null;
}
else if (stageObject[g].Garbage == true && stageObject[g].IsDisplay == false)
{
stageObject[g] = null;
}
}
}
public function StopRender():void
{
removeEventListener(Event.ENTER_FRAME, loop);
}
}
}
It's not the complete code, but if I remove canvas.copyPixels(background,bgRect,bgPoint); or canvas.copyPixels(buffer,bufferRect,bufferPoint); I can see either or. If I paint them both then I can only see the one that painted last. My tile image is 128 x 32. 0 - 3. array 3 is transparent image. I used that hoping that I could see through the image and see the background. I was wrong.
At first it was an all black background, but then I changed the transparent constructor to true on the buffer variable. Now it shows a white background (like the stage), but still no background image.
I'm not sure I completely understand the example, but it looks like the issue is that you're using copyPixels--this should replace the old pixels in the canvas bmp with new values.
Try using draw for the foreground instead:
canvas.copyPixels(background, bgRect, bgPoint);
canvas.draw(buffer, transform, null, null, clipRect);
Also, I'm not sure why you're drawing the background image to a different rect than the foreground? There may be something there.
I took a seperate movieclip and used it as a parallax behind the blitting tiles.