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);
Related
Someone helped me get this code for taking a picture using xamarin forms labs camera:
picker = DependencyService.Get<IMediaPicker> ();
task = picker.TakePhotoAsync (new CameraMediaStorageOptions {
DefaultCamera = CameraDevice.Rear,
MaxPixelDimension = 800,
});
img.BackgroundColor = Color.Gray;
Device.StartTimer (TimeSpan.FromMilliseconds (250), () => {
if (task != null) {
if (task.Status == TaskStatus.RanToCompletion) {
Device.BeginInvokeOnMainThread (async () => {
//img.Source = ImageSource.FromStream (() => task.Result.Source);
var fileAccess = Resolver.Resolve<IFileAccess> ();
string imageName = "img_user_" + User.CurrentUser().id + "_" + DateTime.Now.ToString ("yy_MM_dd_HH_mm_ss") + ".jpg";
fileName = imageName;
fileAccess.WriteStream (imageName, task.Result.Source);
fileLocation = fileAccess.FullPath(imageName);
FileStream fileStream = new FileStream(fileAccess.FullPath(imageName), FileMode.Open, System.IO.FileAccess.Read);
imageUrl = (string)test[0]["url"];
img.Source = imageUrl;
});
}
return task.Status != TaskStatus.Canceled
&& task.Status != TaskStatus.Faulted
&& task.Status != TaskStatus.RanToCompletion;
}
return true;
});
It saves the image, but the actual size of the phone picture taken is huge, is there a way to resize it.
UPDATE: The original answer is not useful, see below for updated answer. The issue was the PCL library was very slow and consumed too much memory.
ORIGINAL ANSWER (do not use):
I found an image I/O library, ImageTools-PCL, which I forked on github and trimmed down what wouldn't compile in Xamarin, keeping the modifications to minimum and the result seems to work.
To use it download the linked repository, compile it with Xamarin and add the DLLs from Build folder to your Forms project.
To resize an image you can do this (should fit the context of your question)
var decoder = new ImageTools.IO.Jpeg.JpegDecoder ();
ImageTools.ExtendedImage inImage = new ImageTools.ExtendedImage ();
decoder.Decode (inImage, task.Result.Source);
var outImage = ImageTools.ExtendedImage.Resize (inImage, 1024, new ImageTools.Filtering.BilinearResizer ());
var encoder = new ImageTools.IO.Jpeg.JpegEncoder ();
encoder.Encode (outImage, fileAccess.CreateStream (imageName));
ImageSource imgSource = ImageSource.FromFile (fileAccess.FullPath (imageName));
UPDATED ANSWER:
Get Xamarin.XLabs from nuget, learn about using Resolver, create an IImageService interface with Resize method.
Implementation for iOS:
public class ImageServiceIOS: IImageService{
public void ResizeImage(string sourceFile, string targetFile, float maxWidth, float maxHeight)
{
if (File.Exists(sourceFile) && !File.Exists(targetFile))
{
using (UIImage sourceImage = UIImage.FromFile(sourceFile))
{
var sourceSize = sourceImage.Size;
var maxResizeFactor = Math.Min(maxWidth / sourceSize.Width, maxHeight / sourceSize.Height);
if (!Directory.Exists(Path.GetDirectoryName(targetFile)))
Directory.CreateDirectory(Path.GetDirectoryName(targetFile));
if (maxResizeFactor > 0.9)
{
File.Copy(sourceFile, targetFile);
}
else
{
var width = maxResizeFactor * sourceSize.Width;
var height = maxResizeFactor * sourceSize.Height;
UIGraphics.BeginImageContextWithOptions(new CGSize((float)width, (float)height), true, 1.0f);
// UIGraphics.GetCurrentContext().RotateCTM(90 / Math.PI);
sourceImage.Draw(new CGRect(0, 0, (float)width, (float)height));
var resultImage = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
if (targetFile.ToLower().EndsWith("png"))
resultImage.AsPNG().Save(targetFile, true);
else
resultImage.AsJPEG().Save(targetFile, true);
}
}
}
}
}
Implementation of the service for Android:
public class ImageServiceDroid: IImageService{
public void ResizeImage(string sourceFile, string targetFile, float maxWidth, float maxHeight)
{
if (!File.Exists(targetFile) && File.Exists(sourceFile))
{
// First decode with inJustDecodeBounds=true to check dimensions
var options = new BitmapFactory.Options()
{
InJustDecodeBounds = false,
InPurgeable = true,
};
using (var image = BitmapFactory.DecodeFile(sourceFile, options))
{
if (image != null)
{
var sourceSize = new Size((int)image.GetBitmapInfo().Height, (int)image.GetBitmapInfo().Width);
var maxResizeFactor = Math.Min(maxWidth / sourceSize.Width, maxHeight / sourceSize.Height);
string targetDir = System.IO.Path.GetDirectoryName(targetFile);
if (!Directory.Exists(targetDir))
Directory.CreateDirectory(targetDir);
if (maxResizeFactor > 0.9)
{
File.Copy(sourceFile, targetFile);
}
else
{
var width = (int)(maxResizeFactor * sourceSize.Width);
var height = (int)(maxResizeFactor * sourceSize.Height);
using (var bitmapScaled = Bitmap.CreateScaledBitmap(image, height, width, true))
{
using (Stream outStream = File.Create(targetFile))
{
if (targetFile.ToLower().EndsWith("png"))
bitmapScaled.Compress(Bitmap.CompressFormat.Png, 100, outStream);
else
bitmapScaled.Compress(Bitmap.CompressFormat.Jpeg, 95, outStream);
}
bitmapScaled.Recycle();
}
}
image.Recycle();
}
else
Log.E("Image scaling failed: " + sourceFile);
}
}
}
}
#Sten's answer might encounter out-of-memory problem on some android devices. Here's my solution to implement the ResizeImage function
, which is according to google's "Loading Large Bitmaps Efficiently" document:
public void ResizeImage (string sourceFile, string targetFile, int reqWidth, int reqHeight)
{
if (!File.Exists (targetFile) && File.Exists (sourceFile)) {
var downImg = decodeSampledBitmapFromFile (sourceFile, reqWidth, reqHeight);
using (var outStream = File.Create (targetFile)) {
if (targetFile.ToLower ().EndsWith ("png"))
downImg.Compress (Bitmap.CompressFormat.Png, 100, outStream);
else
downImg.Compress (Bitmap.CompressFormat.Jpeg, 95, outStream);
}
downImg.Recycle();
}
}
public static Bitmap decodeSampledBitmapFromFile (string path, int reqWidth, int reqHeight)
{
// First decode with inJustDecodeBounds=true to check dimensions
var options = new BitmapFactory.Options ();
options.InJustDecodeBounds = true;
BitmapFactory.DecodeFile (path, options);
// Calculate inSampleSize
options.InSampleSize = calculateInSampleSize (options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.InJustDecodeBounds = false;
return BitmapFactory.DecodeFile (path, options);
}
public static int calculateInSampleSize (BitmapFactory.Options options, int reqWidth, int reqHeight)
{
// Raw height and width of image
int height = options.OutHeight;
int width = options.OutWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
int halfHeight = height / 2;
int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
You can do this natively for each platform and use an interface. Heres an example for IOS
In your PCL project you need to add an interface
public interface IImageResizer
{
byte[] ResizeImage (byte[] imageData, double width, double height);
}
Then to resize an image in your code, you can load the IOS implementation of that interface using the DependencyService and run the ResizeImage method
var resizer = DependencyService.Get<IImageResizer>();
var resizedBytes = resizer.ResizeImage (originalImageByteArray, 400, 400);
Stream stream = new MemoryStream(resizedBytes);
image.Source = ImageSource.FromStream(stream);
IOS Implementation, add this class to your IOS project.
[assembly: Xamarin.Forms.Dependency (typeof (ImageResizer_iOS))]
namespace YourNamespace
{
public class ImageResizer_iOS : IImageResizer
{
public byte[] ResizeImage (byte[] imageData, double maxWidth, double maxHeight)
{
UIImage originalImage = ImageFromByteArray (imageData);
double width = 300, height = 300;
double maxAspect = (double)maxWidth / (double)maxHeight;
double aspect = (double)originalImage.Size.Width/(double)originalImage.Size.Height;
if (maxAspect > aspect && originalImage.Size.Width > maxWidth) {
//Width is the bigger dimension relative to max bounds
width = maxWidth;
height = maxWidth / aspect;
}else if (maxAspect <= aspect && originalImage.Size.Height > maxHeight){
//Height is the bigger dimension
height = maxHeight;
width = maxHeight * aspect;
}
return originalImage.Scale(new SizeF((float)width,(float)height)).AsJPEG ().ToArray ();
}
public static MonoTouch.UIKit.UIImage ImageFromByteArray(byte[] data)
{
if (data == null) {
return null;
}
MonoTouch.UIKit.UIImage image;
try {
image = new MonoTouch.UIKit.UIImage(MonoTouch.Foundation.NSData.FromArray(data));
} catch (Exception e) {
Console.WriteLine ("Image load failed: " + e.Message);
return null;
}
return image;
}
}
}
An update from the Xamarin Media Plugin allows you to resize the image
https://github.com/jamesmontemagno/MediaPlugin
... barring that, and you need a more generic resize option (say the image comes from a web call, and not the device, then have a look at:
https://github.com/InquisitorJax/Wibci.Xamarin.Images
I found a nice code to down size image on server, to avoid bad image rendering by different browser. This code is for MVC application.
I have no experience in C# would like to know what do I need to change to make this code work in webforms.
<img src="#Url.Action("ResizeImage", "Controller", new { urlImage = "<url_image>", width = 35 })" />
public ActionResult ResizeImage(string imageUrl, int width)
{
WebImage wImage = new WebImage(imageUrl);
wImage = WebImageExtension.Resize(wImage, width);
return File(wImage.GetBytes(), "image/png");
}
public static class WebImageExtension
{
private static readonly IDictionary<string, ImageFormat> TransparencyFormats =
new Dictionary<string, ImageFormat>(StringComparer.OrdinalIgnoreCase) { { "png", ImageFormat.Png }, { "gif", ImageFormat.Gif } };
public static WebImage Resize(this WebImage image, int width)
{
double aspectRatio = (double)image.Width / image.Height;
var height = Convert.ToInt32(width / aspectRatio);
ImageFormat format;
if (!TransparencyFormats.TryGetValue(image.ImageFormat.ToLower(), out format))
{
return image.Resize(width, height);
}
using (Image resizedImage = new Bitmap(width, height))
{
using (var source = new Bitmap(new MemoryStream(image.GetBytes())))
{
using (Graphics g = Graphics.FromImage(resizedImage))
{
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.DrawImage(source, 0, 0, width, height);
}
}
using (var ms = new MemoryStream())
{
resizedImage.Save(ms, format);
return new WebImage(ms.ToArray());
}
}
}
}
UPDATE:
I use this code to resize images
public static void ResizeImageFreeSize(string OriginalFile, string NewFile, int MinWidth, int MinHeight, string FileExtension)
{
var NewHeight = MinHeight;
var NewWidth = MinWidth;
// var OriginalImage = System.Drawing.Image.FromFile(OriginalFile); // THis statlement alon with generate error as file is locked so -->GDI+ keeps a lock on files from which an image was contructed. To avoid the lock, construct the image from a MemorySteam:
MemoryStream ms = new MemoryStream(File.ReadAllBytes(OriginalFile));
var OriginalImage = System.Drawing.Image.FromStream(ms);
if (OriginalImage.Width < MinWidth || OriginalImage.Height < MinHeight)
throw new Exception(String.Format("Invalid Image Dimensions, please upload an image with minmum dimensions of {0}x{1}px", MinWidth.ToString(), MinHeight.ToString()));
// If the image dimensions are the same then make the new dimensions the largest of the two mins.
if (OriginalImage.Height == OriginalImage.Width)
NewWidth = NewHeight = (MinWidth > MinHeight) ? MinWidth : MinHeight;
else
{
if (MinWidth > MinHeight)
NewHeight = (int)(OriginalImage.Height * ((float)MinWidth / (float)OriginalImage.Width));
else
NewWidth = (int)(OriginalImage.Width * ((float)MinHeight / (float)OriginalImage.Height));
}
// Just resample the Original Image into a new Bitmap
var ResizedBitmap = new System.Drawing.Bitmap(OriginalImage, NewWidth, NewHeight);
// Saves the new bitmap in the same format as it's source image
FileExtension = FileExtension.ToLower().Replace(".", "");
ImageFormat Format = null;
switch (FileExtension)
{
case "jpg":
Format = ImageFormat.Jpeg;
Encoder quality = Encoder.Quality;
var ratio = new EncoderParameter(quality, 100L);
var codecParams = new EncoderParameters(1);
codecParams.Param[0] = ratio;
// NewImage.Save(NewFile, GetEncoder(ImageFormat.Jpeg), codecParams);
ResizedBitmap.Save(NewFile, GetEncoder(ImageFormat.Jpeg), codecParams);
break;
case "gif":
Format = ImageFormat.Gif;
ResizedBitmap.Save(NewFile, Format);
break;
case "png":
Format = ImageFormat.Png;
ResizedBitmap.Save(NewFile, Format);
break;
default:
Format = ImageFormat.Png;
ResizedBitmap.Save(NewFile, Format);
break;
}
// ResizedBitmap.Save(NewFile, Format);
// Clear handle to original file so that we can overwrite it if necessary
OriginalImage.Dispose();
ResizedBitmap.Dispose();
}
You can have a HttpHandler for this in C#,
namespace CMSN.Software.Tutorials.HowToDynamicallyResizeImages
{
public class DynamicImage : IHttpHandler
{
/// <summary>
/// Default cache duration
/// </summary>
private static readonly TimeSpan CacheDuration = TimeSpan.FromDays(30);
/// <summary>
/// Gets a value indicating whether another request can use the
/// <see cref="T:System.Web.IHttpHandler"/> instance.
/// </summary>
/// <returns>
/// true if the <see cref="T:System.Web.IHttpHandler"/> instance is reusable; otherwise, false.
/// </returns>
public bool IsReusable
{
get
{
return false;
}
}
/// <summary>
/// Enables processing of HTTP Web requests by a custom HttpHandler that implements the
/// <see cref="T:System.Web.IHttpHandler"/> interface.
/// </summary>
/// <param name="context">An <see cref="T:System.Web.HttpContext"/> object that provides references to the
/// intrinsic server objects (for example, Request, Response, Session, and Server)
/// used to service HTTP requests.
/// </param>
public void ProcessRequest(HttpContext context)
{
string cacheKeyName = context.Request.Url.PathAndQuery;
string imagePath = context.Server.MapPath(context.Request.Url.LocalPath);
string imageExtention = Path.GetExtension(imagePath);
string contentType = string.Empty;
byte[] imageFileContent;
ImageFormat imageFormat = null;
switch (imageExtention)
{
case ".png":
imageFormat = ImageFormat.Png;
contentType = "image/png";
break;
case ".jpg":
case ".jpeg":
case ".jpe":
imageFormat = ImageFormat.Jpeg;
contentType = "image/jpeg";
break;
case ".bmp":
imageFormat = ImageFormat.Bmp;
contentType = "image/bmp";
break;
case ".gif":
imageFormat = ImageFormat.Gif;
contentType = "image/gif";
break;
default:
break;
}
context.Response.ContentType = contentType;
if (context.Cache[CacheKey(cacheKeyName)] != null)
{
imageFileContent = context.Cache[CacheKey(cacheKeyName)] as byte[];
}
else
{
int imageWidth = 0;
int imageHeight = 0;
if (!string.IsNullOrEmpty(context.Request["w"]))
{
if (!int.TryParse(context.Request["w"], out imageWidth))
{
imageWidth = 0;
}
}
if (!string.IsNullOrEmpty(context.Request["h"]))
{
if (!int.TryParse(context.Request["h"], out imageHeight))
{
imageHeight = 0;
}
}
Image originalImage;
if (File.Exists(imagePath))
{
originalImage = Image.FromFile(imagePath);
}
else
{
originalImage = new Bitmap(100, 100);
}
if (imageWidth > 0 || imageHeight > 0)
{
if (imageHeight == 0 && imageWidth > 0)
{
imageHeight = originalImage.Height * imageWidth / originalImage.Width;
}
if (imageWidth == 0 && imageHeight > 0)
{
imageWidth = originalImage.Width * imageHeight / originalImage.Height;
}
}
else
{
imageHeight = originalImage.Height;
imageWidth = originalImage.Width;
}
using (Bitmap newImage = new Bitmap(originalImage, imageWidth, imageHeight))
{
Graphics generatedImage = Graphics.FromImage(newImage);
generatedImage.InterpolationMode = InterpolationMode.HighQualityBicubic;
generatedImage.SmoothingMode = SmoothingMode.AntiAlias;
generatedImage.CompositingQuality = CompositingQuality.HighQuality;
generatedImage.DrawImage(originalImage, 0, 0, newImage.Width, newImage.Height);
// make a memory stream to work with the image bytes
using (MemoryStream imageStream = new MemoryStream())
{
// put the image into the memory stream
newImage.Save(imageStream, imageFormat);
// make byte array the same size as the image
byte[] imageContent = new byte[imageStream.Length];
// rewind the memory stream
imageStream.Position = 0;
// load the byte array with the image
imageStream.Read(imageContent, 0, (int)imageStream.Length);
// return byte array to caller with image type
imageFileContent = imageContent;
using (CacheDependency dependency = new CacheDependency(imagePath))
{
context.Cache.Insert(
CacheKey(cacheKeyName),
imageContent,
dependency,
System.Web.Caching.Cache.NoAbsoluteExpiration,
CacheDuration);
}
}
}
originalImage.Dispose();
}
SetResponseCache(context.Response, new string[1] { imagePath });
context.Response.BinaryWrite(imageFileContent);
}
/// <summary>
/// Generate unique Cache key.
/// </summary>
/// <param name="key">The cache key.</param>
/// <returns>Generated unique Cache key</returns>
protected static string CacheKey(string key)
{
return "DynamicImage." + key;
}
/// <summary>
/// Sets the response cache.
/// </summary>
/// <param name="response">The response.</param>
/// <param name="files">The files.</param>
protected static void SetResponseCache(HttpResponse response, string[] files)
{
response.AddFileDependencies(files);
HttpCachePolicy browserCache = response.Cache;
DateTime modifiedTime = DateTime.Now;
browserCache.SetCacheability(HttpCacheability.ServerAndPrivate);
browserCache.VaryByParams["w"] = true;
browserCache.VaryByParams["h"] = true;
browserCache.VaryByParams["v"] = true;
browserCache.SetOmitVaryStar(true);
browserCache.SetExpires(modifiedTime.AddDays(7));
browserCache.SetValidUntilExpires(true);
browserCache.SetLastModified(modifiedTime);
browserCache.SetETagFromFileDependencies();
browserCache.SetLastModifiedFromFileDependencies();
}
}
}
Web.config
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<httpHandlers>
<add verb="*" path="*.png,*.jpg,*.jpeg,*.gif,*.bmp" type="CMSN.Software.Tutorials.HowToDynamicallyResizeImages.DynamicImage,HowToDynamicallyResizeImages"/>
</httpHandlers>
</system.web>
<system.webServer>
<handlers>
<add verb="*" path="*.png,*.jpg,*.jpeg,*.gif,*.bmp" name="DynamicImage" type="CMSN.Software.Tutorials.HowToDynamicallyResizeImages.DynamicImage,HowToDynamicallyResizeImages"/>
</handlers>
<validation validateIntegratedModeConfiguration="false"/>
</system.webServer>
</configuration>
Usage,
http://localhost/Images/xxxxxxxx.png?w=300&h=149
If you want to see the complete guide for this, please follow the following URL.
http://tutorials.cmsnsoftware.com/2011/09/how-to-dynamically-resize-images.html
I am creating Multimedia components using core service and everything is working fine. But when Metadata schema fields are defined on the Multimedia schema using which I am creating my Multimedia components then I am getting following error:-
Unable to find http://www.tridion.com/ContentManager/5.0/DefaultMultimediaSchema:Metadata.
This message is displayed when I have given Default Multimedia schema's TCM ID for Multimedia component. As metadata fields are saved in Tridion Database so I first have to retrieve these fields from broker or what is the best solution for this, please suggest. Below is the sample code. Please modify it if someone have any idea for providing default value for metadatafields and how to retrieve them (with/without querying broker DB):-
public static string UploadMultiMediaComponent(string folderUri, string title, string schemaID)
{
core_service.ServiceReference1.SessionAwareCoreService2010Client client = new SessionAwareCoreService2010Client();
client.ClientCredentials.Windows.ClientCredential.UserName = "myUserName";
client.ClientCredentials.Windows.ClientCredential.Password = "myPassword"; client.Open();
ComponentData multimediaComponent = (ComponentData)client.GetDefaultData(
ItemType.Component, folderUri);
multimediaComponent.Title = title;
multimediaComponent.ComponentType = ComponentType.Multimedia;
multimediaComponent.Schema.IdRef =schemaID;
//multimediaComponent.Metadata = "";
StreamUpload2010Client streamClient = new StreamUpload2010Client();
FileStream objfilestream = new FileStream(#"\My Documents\images.jpg",
FileMode.Open, FileAccess.Read);
string tempLocation = streamClient.UploadBinaryContent("images.jpg",
objfilestream);
BinaryContentData binaryContent = new BinaryContentData();
binaryContent.UploadFromFile = tempLocation;
binaryContent.Filename = "images.jpg";
binaryContent.MultimediaType = new LinkToMultimediaTypeData()
{
// for jpg file
IdRef = "tcm:0-2-65544"
};
multimediaComponent.BinaryContent = binaryContent;
IdentifiableObjectData savedComponent = client.Save(multimediaComponent,
new ReadOptions());
client.CheckIn(savedComponent.Id, null);
streamClient.Close();
client.Close();
Console.WriteLine(savedComponent.Id);
//}
}
I don't know why your code not working but following code is working for me
public static ComponentData GenerateMultiMediaComponent(TridionGeneration tridionGeneration, XmlData newsArticle, string componentName)
{
try
{
Dictionary<string, object> dicTridion = Common.GetTridionObject(tridionGeneration.client, ItemType.Component, tridionGeneration.Settings.ComponentFolderUri, componentName);
int objectCount = (int)dicTridion["count"];
SchemaFieldsData schemaFields = tridionGeneration.client.ReadSchemaFields(tridionGeneration.Settings.SchemaUri, true, new ReadOptions());
ComponentData componentData = (ComponentData)tridionGeneration.client.GetDefaultData(ItemType.Component, tridionGeneration.Settings.ComponentFolderUri);
if (schemaFields.Fields != null)
{
var fields = Fields.ForContentOf(schemaFields);
Helper.FillSchemaFields(tridionGeneration, fields);
componentData.Content = fields.ToString();
}
if (schemaFields.MetadataFields != null)
{
var metafields = Fields.ForMetadataOf(schemaFields, componentData);
Helper.FillSchemaFields(tridionGeneration, metafields);
componentData.Metadata = metafields.ToString();
}
componentData.Title = (objectCount == 0) ? componentName : componentName + " " + (objectCount + 1).ToString();
componentData.ComponentType = ComponentType.Multimedia;
StreamUpload2010Client streamClient = new StreamUpload2010Client();
FileStream objfilestream = new FileStream(#"[IMAGE_PATH]", FileMode.Open, FileAccess.Read);
string tempLocation = streamClient.UploadBinaryContent("images.jpg", objfilestream);
BinaryContentData binaryContent = new BinaryContentData();
binaryContent.UploadFromFile = tempLocation;
binaryContent.Filename = "[IMAGE_NAME]";
componentData.BinaryContent = binaryContent;
binaryContent.MultimediaType = new LinkToMultimediaTypeData()
{
IdRef = "tcm:0-2-65544"
};
componentData = (ComponentData)tridionGeneration.client.Create(componentData, new ReadOptions());
return componentData;
}
catch (Exception ex)
{
return null;
}
}
Here is the Helper class:
public static class Helper
{
public static void FillSchemaFields(TridionGeneration tridionGeneration, Fields fields)
{
List<XmlData> data = XmlHelper.xmlData;
var ofield = fields.GetEnumerator();
while (ofield.MoveNext())
{
Field f = ofield.Current;
FillFieldValue(tridionGeneration, fields, f, data[0]);
}
}
private static void FillFieldValue(TridionGeneration tridionGeneration, Fields fields, Field f, XmlData data)
{
if (f.Type == typeof(MultimediaLinkFieldDefinitionData))
{
fields[f.Name].Value = tridionGeneration.Settings.DefaultImageUri;
}
else if (f.Type != typeof(EmbeddedSchemaFieldDefinitionData))
{
foreach (XmlData fieldvalue in data.Attributes)
{
if (f.Type == typeof(DateFieldDefinitionData))
{
if (fieldvalue.text.ToLower() == f.Name.ToLower())
{
fields[f.Name].Value = Convert.ToDateTime(fieldvalue.value).ToString("yyyy-MM-ddTHH:mm:ss");
}
else
{
string val = FindSchemaValue(tridionGeneration, fieldvalue.Attributes, f.Name);
if (!string.IsNullOrEmpty(val))
{
fields[f.Name].Value = Convert.ToDateTime(val).ToString("yyyy-MM-ddTHH:mm:ss");
}
}
}
else
{
if (fieldvalue.text.ToLower() == f.Name.ToLower())
{
fields[f.Name].Value = System.Net.WebUtility.HtmlEncode(fieldvalue.value);
}
else
{
string val = FindSchemaValue(tridionGeneration, fieldvalue.Attributes, f.Name);
if (!string.IsNullOrEmpty(val))
{
fields[f.Name].Value = System.Net.WebUtility.HtmlEncode(val);
}
}
}
}
}
else
{
Fields fs = f.GetSubFields();
var ofield = fs.GetEnumerator();
while (ofield.MoveNext())
{
Field ff = ofield.Current;
FillFieldValue(tridionGeneration, fs, ff, data);
}
}
}
private static string FindSchemaValue(TridionGeneration tridionGeneration, List<XmlData> data, string fieldname)
{
foreach (XmlData fieldvalue in data)
{
if (fieldvalue.text.ToLower() == fieldname.ToLower())
{
return fieldvalue.value;
}
else
{
FindSchemaValue(tridionGeneration, fieldvalue.Attributes, fieldname);
}
}
return "";
}
}
and the Fields class:
public class Fields
{
private ItemFieldDefinitionData[] definitions;
private XmlNamespaceManager namespaceManager;
private XmlElement root; // the root element under which these fields live
// at any point EITHER data OR parent has a value
private SchemaFieldsData data; // the schema fields data as retrieved from the core service
private Fields parent; // the parent fields (so we're an embedded schema), where we can find the data
public Fields(SchemaFieldsData _data, ItemFieldDefinitionData[] _definitions, string _content = null, string _rootElementName = null)
{
data = _data;
definitions = _definitions;
var content = new XmlDocument();
if (!string.IsNullOrEmpty(_content))
{
content.LoadXml(_content);
}
else
{
content.AppendChild(content.CreateElement(string.IsNullOrEmpty(_rootElementName) ? _data.RootElementName : _rootElementName, _data.NamespaceUri));
}
root = content.DocumentElement;
namespaceManager = new XmlNamespaceManager(content.NameTable);
namespaceManager.AddNamespace("custom", _data.NamespaceUri);
}
public Fields(Fields _parent, ItemFieldDefinitionData[] _definitions, XmlElement _root)
{
definitions = _definitions;
parent = _parent;
root = _root;
}
public static Fields ForContentOf(SchemaFieldsData _data)
{
return new Fields(_data, _data.Fields);
}
public static Fields ForContentOf(SchemaFieldsData _data, ComponentData _component)
{
return new Fields(_data, _data.Fields, _component.Content);
}
public static Fields ForMetadataOf(SchemaFieldsData _data, RepositoryLocalObjectData _item)
{
return new Fields(_data, _data.MetadataFields, _item.Metadata, "Metadata");
}
public string NamespaceUri
{
get { return data != null ? data.NamespaceUri : parent.NamespaceUri; }
}
public XmlNamespaceManager NamespaceManager
{
get { return parent != null ? parent.namespaceManager : namespaceManager; }
}
internal IEnumerable<XmlElement> GetFieldElements(ItemFieldDefinitionData definition)
{
return root.SelectNodes("custom:" + definition.Name, NamespaceManager).OfType<XmlElement>();
}
internal XmlElement AddFieldElement(ItemFieldDefinitionData definition)
{
var newElement = root.OwnerDocument.CreateElement(definition.Name, NamespaceUri);
XmlNodeList nodes = root.SelectNodes("custom:" + definition.Name, NamespaceManager);
XmlElement referenceElement = null;
if (nodes.Count > 0)
{
referenceElement = (XmlElement)nodes[nodes.Count - 1];
}
else
{
// this is the first value for this field, find its position in the XML based on the field order in the schema
bool foundUs = false;
for (int i = definitions.Length - 1; i >= 0; i--)
{
if (!foundUs)
{
if (definitions[i].Name == definition.Name)
{
foundUs = true;
}
}
else
{
var values = GetFieldElements(definitions[i]);
if (values.Count() > 0)
{
referenceElement = values.Last();
break; // from for loop
}
}
} // for every definition in reverse order
} // no existing values found
root.InsertAfter(newElement, referenceElement); // if referenceElement is null, will insert as first child
return newElement;
}
public IEnumerator<Field> GetEnumerator()
{
return (IEnumerator<Field>)new FieldEnumerator(this, definitions);
}
public Field this[string _name]
{
get
{
var definition = definitions.First<ItemFieldDefinitionData>(ifdd => ifdd.Name == _name);
if (definition == null) throw new ArgumentOutOfRangeException("Unknown field '" + _name + "'");
return new Field(this, definition);
}
}
public override string ToString()
{
return root.OuterXml;
}
}
public class FieldEnumerator : IEnumerator<Field>
{
private Fields fields;
private ItemFieldDefinitionData[] definitions;
// Enumerators are positioned before the first element until the first MoveNext() call
int position = -1;
public FieldEnumerator(Fields _fields, ItemFieldDefinitionData[] _definitions)
{
fields = _fields;
definitions = _definitions;
}
public bool MoveNext()
{
position++;
return (position < definitions.Length);
}
public void Reset()
{
position = -1;
}
object IEnumerator.Current
{
get
{
return Current;
}
}
public Field Current
{
get
{
try
{
return new Field(fields, definitions[position]);
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
public void Dispose()
{
}
}
public class Field
{
private Fields fields;
private ItemFieldDefinitionData definition;
public Field(Fields _fields, ItemFieldDefinitionData _definition)
{
fields = _fields;
definition = _definition;
}
public string Name
{
get { return definition.Name; }
}
public Type Type
{
get { return definition.GetType(); }
}
public string Value
{
get
{
return Values.Count > 0 ? Values[0] : null;
}
set
{
if (Values.Count == 0) fields.AddFieldElement(definition);
Values[0] = value;
}
}
public ValueCollection Values
{
get
{
return new ValueCollection(fields, definition);
}
}
public void AddValue(string value = null)
{
XmlElement newElement = fields.AddFieldElement(definition);
if (value != null) newElement.InnerText = value;
}
public void RemoveValue(string value)
{
var elements = fields.GetFieldElements(definition);
foreach (var element in elements)
{
if (element.InnerText == value)
{
element.ParentNode.RemoveChild(element);
}
}
}
public void RemoveValue(int i)
{
var elements = fields.GetFieldElements(definition).ToArray();
elements[i].ParentNode.RemoveChild(elements[i]);
}
public IEnumerable<Fields> SubFields
{
get
{
var embeddedFieldDefinition = definition as EmbeddedSchemaFieldDefinitionData;
if (embeddedFieldDefinition != null)
{
var elements = fields.GetFieldElements(definition);
foreach (var element in elements)
{
yield return new Fields(fields, embeddedFieldDefinition.EmbeddedFields, (XmlElement)element);
}
}
}
}
public Fields GetSubFields(int i = 0)
{
var embeddedFieldDefinition = definition as EmbeddedSchemaFieldDefinitionData;
if (embeddedFieldDefinition != null)
{
var elements = fields.GetFieldElements(definition);
if (i == 0 && !elements.Any())
{
// you can always set the first value of any field without calling AddValue, so same applies to embedded fields
AddValue();
elements = fields.GetFieldElements(definition);
}
return new Fields(fields, embeddedFieldDefinition.EmbeddedFields, elements.ToArray()[i]);
}
else
{
throw new InvalidOperationException("You can only GetSubField on an EmbeddedSchemaField");
}
}
// The subfield with the given name of this field
public Field this[string name]
{
get { return GetSubFields()[name]; }
}
// The subfields of the given value of this field
public Fields this[int i]
{
get { return GetSubFields(i); }
}
}
Can you try this?
multimediaComponent.Metadata = "<Metadata/>";
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%
}
}
}
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.