How to add watermark image while uploading image in asp.net mvc.
I am using jquery.uploadfile.min.js multiple file upload for uploading image.
Want to add automatically stored logo image (watermark) to append in my image file that i am going to upload.
IN VIEW:
var errorOccured = false;
$(function () {
var uploadObj = $("#multipleupload").uploadFile({
url: "./Handler.ashx",
multiple: true,
fileName: "myfile",
maxFileSize: 1024 * 5000,
allowedTypes: "jpg,jpeg,gif,png",
autoSubmit: false,
formData: { "FunctionName": "UploadProductImage", "ProductID": '#clsEncrypt.Encrypt(ViewBag.ProductID.ToString())' }, //"ImgResizeOption": ImgResizeOption
afterUploadAll: function () {
if (!errorOccured) {
window.location.href = 'ProductImage?Product=#(clsEncrypt.Encrypt(ViewBag.ProductID.ToString()))';
}
},
onError: function (files, status, errMsg) {
alert('file(s) could not be uploaded. Error: ' + errMsg);
errorOccured = true;
}
});
$("#startUpload").click(function () {
uploadObj.startUpload();
});
});
IN HANDLER :
public void UploadProductImage()
{
int ProductID = Convert.ToInt32(clsEncrypt.Decrypt(HttpContext.Current.Request["ProductID"]));
string PhysicalFolderPath = "~/Images/Product/";
for (int j = 0; j < HttpContext.Current.Request.Files.Count; j++)
{
HttpPostedFile uploadFile = HttpContext.Current.Request.Files[j];
string extention = System.IO.Path.GetExtension(uploadFile.FileName);
UploadPic(uploadFile, j++, PhysicalFolderPath, ProductID);
}
}
protected void UploadPic(HttpPostedFile FUPhoto, int sort, string RemotePath, int ProductID)
{
if (FUPhoto.FileName != "")
{
string ImgUploadResponse = "";
string strExt = Path.GetExtension(FUPhoto.FileName).Trim().ToLower();
string ImageName = DateTime.Now.ToFileTimeUtc() + strExt;
string OriginalImageFullPath = "~/Images/Product/" + ImageName;
if (Directory.Exists(HttpContext.Current.Server.MapPath("~/Images/Product/")).Equals(false))
Directory.CreateDirectory(HttpContext.Current.Server.MapPath("~/Images/Product/"));
FUPhoto.SaveAs(HttpContext.Current.Server.MapPath(OriginalImageFullPath));
ProductImageEntity objProdImage = new ProductImageEntity();
objProdImage.ProductID = ProductID;
if (ImgUploadResponse != "")
objProdImage.Image = "";
else
objProdImage.Image = ImageName;
if (!String.IsNullOrEmpty(objProdImage.Image))
new ProductImageBLL().InsertUpdateProductImage(objProdImage);
}
}
Please refer the below code for watermark logo to add from code side.
using (Image image = Image.FromFile(#"C:\Users\Public\Pictures\Sample Pictures\Desert.jpg"))
using (Image watermarkImage = Image.FromFile(#"C:\Users\Public\Pictures\Sample Pictures\watermark.png"))
using (Graphics imageGraphics = Graphics.FromImage(image))
using (TextureBrush watermarkBrush = new TextureBrush(watermarkImage))
{
int x = (image.Width / 2 - watermarkImage.Width / 2);
int y = (image.Height / 2 - watermarkImage.Height / 2);
watermarkBrush.TranslateTransform(x, y);
imageGraphics.FillRectangle(watermarkBrush, new Rectangle(new Point(x, y), new Size(watermarkImage.Width+1, watermarkImage.Height)));
image.Save(#"C:\Users\Public\Pictures\Sample Pictures\Desert_watermark.jpg");
}
I have installed and tried your dll. Everything is good but one issue. The watermark text is added vertically to vertical images (images whose height is bigger than width). Better solution is to add watermark in a horizantal line to vertical images as well as horizantal images. Thanks anyway.
--Edit--
I have solved the problem within this code, which checks and changes the orientation of the image in need. (uploadedImage is the image that i read from stream)
if (uploadedImage.PropertyIdList.Contains(0x0112))
{
PropertyItem propOrientation = uploadedImage.GetPropertyItem(0x0112);
short orientation = BitConverter.ToInt16(propOrientation.Value, 0);
if (orientation == 6)
{
uploadedImage.RotateFlip(RotateFlipType.Rotate90FlipNone);
}
else if (orientation == 8)
{
uploadedImage.RotateFlip(RotateFlipType.Rotate270FlipNone);
}
else
{
// Do nothing
}
}
Recently I've published a nugget package that do add image water mark with control over opacity and target spot to place the watermark in. Additionally you can add text watermark and do image crop/resize as well.
install via nugget:
Install-Package LazZiya.ImageResize
then you can use the code as below:
//get image from local path
var img = Image.FromFile("wwwroot\\images\\lum3n-358833-unsplash.jpg");
//scale and crop, 600x250 center focus
var newImg = ImageResize.ScaleAndCrop(img, 600, 250, TargetSpot.Center);
//watermark image path
var imgWatermark = "wwwroot\\images\\icon.png";
//add image watermark
newImg.ImageWatermark(imgWatermark,
TargetSpot.TopRight, //define target spot
10, //margin
37); //opacity (0-100)
//save new image
newImg.SaveAs("wwwroot\\images\\600x250-image-watermark.jpg");
//dispose to free up memory
img.Dispose();
newImg.Dispose();
[UPDATE]
The package is updated and some methods has been changed, and better support for more image formats is available (including animated gif).
See the docs for more details.
see live demo page.
Related
In in powerpoint i have placed some diagrams diagrams, where each diagram contains different guid.And i have set the GUID as their hyperlink. when the refresh button is clicked what i do is ,will find the shape and then will get the guid which i have saved as hyperlink for each image , from each image and using that GUID will replace the recent image with the old image in that shape.
foreach (var shape in presentation.Slides[slideno].Shapes)
{
var slide = (PPT.Slide)item;
if (j <= shapeCount)
{
string[] address = new string[] { };
string dskj = slide.Shapes[j].Name;
if (slide.Shapes[j].Name.Equals("DIAGRAM")//, StringComparison.InvariantCultureIgnoreCase)
&& slide.Shapes[j].ActionSettings[PPT.PpMouseActivation.ppMouseClick].Hyperlink.Address != null)
{
address = slide.Shapes[j].ActionSettings[PPT.PpMouseActivation.ppMouseClick].Hyperlink.Address.Split('*');
string Type = address[0];
string Guid = address[1];
if (Type == "D")
{
Session.path = presentation.Path;
if (Session.path != "")
Session.Repository.GetProjectInterface().PutDiagramImageToFile(address[1], Session.path + "\\" + address[1] + ".jpg", 1);
bool diagrm = false;
try
{
EA.Diagram diag = Session.Repository.GetDiagramByGuid(Guid);
diagrm = true;
}
catch
{
continue;
}
if (diagrm)
{
float Shapeleft = slide.Shapes[j].Left;
float Shapetop = slide.Shapes[j].Top;
float Shapewidth = slide.Shapes[j].Width;
float Shapeheight = slide.Shapes[j].Height;
slide.Shapes[j].Delete();
PPT.Shape pic = slide.Shapes.AddPicture(Session.path + "\\" + Guid + ".jpg", Microsoft.Office.Core.MsoTriState.msoFalse,
Microsoft.Office.Core.MsoTriState.msoTrue, Shapeleft, Shapetop, Shapewidth, Shapeheight);
pic.Name = "DIAGRAM";
pic.ActionSettings[PPT.PpMouseActivation.ppMouseClick].Hyperlink.Address = "D*" + Guid;
}
}
}
}
using this above code everything works great.
address = slide.Shapes[j].ActionSettings[PPT.PpMouseActivation.ppMouseClick].Hyperlink.Address
in address i will get the hyperlink address of that current image,but now my problem is if i have two images in a same single slide , then both the time when it loops inside the shapes it only gives the same hyperlink for both the images.
**NOTE:**If i have only one image in a slide then everything works properly.
Its because you're deleting the previous shape and inserting a new shape at the same place , but each shape contains a ZOrderPosition , where because of you deleted the previous and inserted a new shape the Zorderposition get changed for the new shape and it will be included in the next iteration.So if more than one image is inserted in a shape it only refrsh some images .
SOLUTION:
After deleting the existing and when inserting a new shape set its ZorderPosition also.
pic.ZOrder(MsoZOrderCmd.msoSendToBack);
Hope it works..!!
Here is my Code, I am trying to stitch two pictures together and as soon as I get to line 42 "Image img = Image.FromFile(file.FullName);" I get an out of memory error. What should I do?
namespace Practicing_Stiching
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void cmdCombine_Click(object sender, EventArgs e)
{
//Change the path to location where your images are stored.
DirectoryInfo directory = new DirectoryInfo(#"C:\Users\Elder Zollinger\Desktop\Images");
if (directory != null)
{
FileInfo[] files = directory.GetFiles();
CombineImages(files);
}
}
private void CombineImages(FileInfo[] files)
{
//change the location to store the final image.
string finalImage = #"C:\Users\Elder Zollinger\Desktop\Images";
List<int> imageHeights = new List<int>();
int nIndex = 0;
int width = 0;
foreach (FileInfo file in files)
{
Image img = Image.FromFile(file.FullName);
imageHeights.Add(img.Height);
width += img.Width;
img.Dispose();
}
imageHeights.Sort();
int height = imageHeights[imageHeights.Count - 1];
Bitmap img3 = new Bitmap(width, height);
Graphics g = Graphics.FromImage(img3);
g.Clear(SystemColors.AppWorkspace);
foreach (FileInfo file in files)
{
Image img = Image.FromFile(file.FullName);
if (nIndex == 0)
{
g.DrawImage(img, new Point(0, 0));
nIndex++;
width = img.Width;
}
else
{
g.DrawImage(img, new Point(width, 0));
width += img.Width;
}
img.Dispose();
}
g.Dispose();
img3.Save(finalImage, System.Drawing.Imaging.ImageFormat.Jpeg);
img3.Dispose();
imageLocation.Image = Image.FromFile(finalImage);
}
}
}
That's likely GDI playing tricks on you.
You see, when GDI encounters an unknown file, it will quite likely cause an OutOfMemoryException. Since you're not filtering the input images at all, I'd expect that you're simply grabbing a non-image file (or an image type that GDI doesn't understand).
Oh, and a bit sideways - make sure you set JPEG quality when saving JPEGs - the default is something like 75, which is rather bad for a lot of images. And please, do use using - it's very handy to ensure proper and timely clean-up :)
Get more memory!
But seriously, you don't appear to be filtering out files that are not image files. There are some hidden files in folders that you may be trying to open as an image accidentally, such as "Thumbs.db". Make sure that the file is an image with something like if (Path.GetExtension(file.FullPath) != ".png") continue;.
Also, on objects that you are calling .Dispose() on, consider wrapping them in a using() instead. For example:
using(var img = Image.FromFile(file.FullPath))
{
// ...
}
I am using FILE Upload-er in the Grid-view, then i find the ID of fileuploader Dynamically. but the problem is iam getting the value 0 of height & width.
Below the code which iam using .
function validateFileSize() {
debugger;
for (var i = 1; i < document.getElementById('<%=gvDocuments.ClientID %>').rows.length; i++) {
var uploadControl = document.getElementById('<%=gvDocuments.ClientID %>').rows[i].cells[3].getElementsByTagName('INPUT')[0].id; //** here i find the ID of File Uploader
if (document.getElementById('<%=gvDocuments.ClientID %>').rows[i].cells[1].getElementsByTagName('SELECT')[0].value == "18")//** here i find the ID of DropDownlist
{
var newImg = new Image();
newImg.src = document.getElementById(uploadControl).value;
var height = newImg.height;
var width = newImg.width;
alert('The Image Dimension is ' + height + ' X ' + width + '');
}
}
}
If you are using jQuery and you are requesting image sizes like this
check this example
http://jsbin.com/oTAtIpA/3/edit
You just need to check the image dimensions inside of the image onload function.
e.g
newImg.onload = function()
{
var height = this.height;
var width = this.width;
// do stuff with image dimensions
}
Also see https://stackoverflow.com/a/626505/53241
LittleDragon's example is also using pure JavaScript to get the dimensions, not jQuery
<script type="text/javascript">
$(function () {
$("#upload").bind("click", function () {
//Get reference of FileUpload.
var fileUpload = $("#fileUpload")[0];
//Check whether HTML5 is supported.
if (typeof (fileUpload.files) != "undefined") {
//Initiate the FileReader object.
var reader = new FileReader();
//Read the contents of Image File.
reader.readAsDataURL(fileUpload.files[0]);
reader.onload = function (e) {
//Initiate the JavaScript Image object.
var image = new Image();
//Set the Base64 string return from FileReader as source.
image.src = e.target.result;
image.onload = function () {
//Determine the Height and Width.
var height = this.height;
var width = this.width;
if (height > 100 || width > 100) {
alert("Height and Width must not exceed 100px.");
return false;
}
alert("Uploaded image has valid Height and Width.");
return true;
};
}
} else {
alert("This browser does not support HTML5.");
return false;
}
});
});
</script>
<input type="file" id="fileUpload" />
<input id="upload" type="button" value="Upload" />
TRY THIS>
I've got an image upload page that works just fine when I only upload the files.
I added a 'Create Thumbnail' function. It looks like the file system has a handle on the images when the thumbnail process starts.
I get the 'unspecified GDI+ error' only when the image is over about 250K. When the files are below 250K, thumbnails are created as expected.
What are my options? Is there an elegant solution here? I want something not hacky.
Also, I am using HttpFileCollection so we can upload multiple images at one time. I've tried to use .Dispose on the Thumbnail creation, but it fails before we get to this point.
public void Upload_Click(object Sender, EventArgs e)
{
string directory = Server.MapPath(#"~\images\");
HttpFileCollection hfc = Request.Files;
for (int i = 0; i < hfc.Count; i++)
{
HttpPostedFile hpf = hfc[i];
if (hpf.ContentLength > 0)
{
string fileName = hpf.FileName;
fileName = fileName.Replace(" ", "");
hpf.SaveAs(fileName);
createThumbnail(fileName);
}
}
}
private void createThumbnail(string filename)
{
Image image = Image.FromFile(filename);
Image thumb = image.GetThumbnailImage(100,100, () => false, IntPtr.Zero);
thumb.Save(filename);
image.Dispose();
thumb.Dispose();
}
Please let me know if this works any better:
public string ImageDirectory { get { return Server.MapPath(#"~\images\"); } }
public void OnUploadClick(object sender, EventArgs e)
{
var files = HttpContext.Request.Files.AllKeys.AsEnumerable()
.Select(k =>HttpContext.Request.Files[k]);
foreach(var file in files)
{
if(file.ContentLength <= 0)
continue;
string savePath = GetFullSavePath(file);
var dimensions = new Size(100, 100);
CreateThumbnail(file,savePath,dimensions);
}
}
private void CreateThumbnail(HttpPostedFile file,string savePath, Size dimensions)
{
using (var image = Image.FromStream(file.InputStream))
{
using (var thumb = image.GetThumbnailImage(dimensions.Width, dimensions.Height, () => false, IntPtr.Zero))
{
thumb.Save(savePath);
}
}
}
private string GetFullSavePath(HttpPostedFile file)
{
string fileName = System.IO.Path.GetFileName(file.FileName).Replace(" ", "");
string savePath = System.IO.Path.Combine(this.ImageDirectory, fileName);
return savePath;
}
Edit -
The foreach should have followed more to this pattern:
var files = HttpContext.Request.Files.AllKeys.AsEnumerable()
.Select(k =>HttpContext.Request.Files[k]);
foreach(var file in files)
{
}
You can try this code to create your thumbnails.
MemoryStream ms = new MemoryStream(File.ReadAllBytes(path));
Bitmap originalBMP = new Bitmap(ms);
int maxWidth = 200;
int maxHeight = 200;
// Calculate the new image dimensions
int origWidth = originalBMP.Width;
int origHeight = originalBMP.Height;
double sngRatio = Convert.ToDouble(origWidth) / Convert.ToDouble(origHeight);
// New dimensions
int newWidth = 0;
int newHeight = 0;
try
{
// max 200 by 200
if ((origWidth <= maxWidth && origHeight <= maxHeight) || origWidth <= maxWidth)
{
newWidth = origWidth;
newHeight = origHeight;
}
else
{
// Width longer (shrink width)
newWidth = 200;
newHeight = Convert.ToInt32(Convert.ToDouble(newWidth) / sngRatio);
}
// Create a new bitmap which will hold the previous resized bitmap
Bitmap newBMP = new Bitmap(originalBMP, newWidth, newHeight);
// Create a graphic based on the new bitmap
Graphics oGraphics = Graphics.FromImage(newBMP);
// Set the properties for the new graphic file
oGraphics.SmoothingMode = SmoothingMode.AntiAlias;
oGraphics.InterpolationMode = InterpolationMode.High;
// Draw the new graphic based on the resized bitmap
oGraphics.CompositingQuality = CompositingQuality.HighSpeed;
oGraphics.DrawImage(originalBMP, 0, 0, newWidth, newHeight);
// Save the new graphic file to the server
EncoderParameters p = new EncoderParameters(1);
p.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, 70); // Percent Compression
MemoryStream savedBmp = new MemoryStream();
newBMP.Save(savedBmp, ImageCodecInfo.GetImageEncoders()[1], p);
// Once finished with the bitmap objects, we deallocate them.
originalBMP.Dispose();
newBMP.Dispose();
oGraphics.Dispose();
savedBmp.Dispose();
Certainly a bit more work but it does give you greater control.
I'm writing a CSS sprite engine in C#, however I'm having a few issues. I create the master image, set all the properties to that then iterate the sprites and draw those to the master image. However when I come to save the master image it only appears to be just the empty master image with transparent background and none of the sprites. I'm very confused at where I'm going wrong.
The code I'm using is:
// Work out the width/height required
int max_width = 0;
int max_height = 0;
foreach(SpriteInformation sprite in sprites) {
if (max_width < (sprite.Left + greatest_width)) max_width = sprite.Left + greatest_width;
if (max_height < (sprite.Top + greatest_height)) max_height = sprite.Top + greatest_height;
}
// Create new master bitmap
Bitmap bitmap = new Bitmap(max_width,max_height,PixelFormat.Format32bppArgb);
Graphics graphics = Graphics.FromImage(bitmap);
// Set background color
SolidBrush brush;
if (cbxBackground.Checked) {
if (txtColor.Text == "") {
brush = new SolidBrush(Color.Black);
} else {
brush = new SolidBrush(pnlColor.BackColor);
}
} else {
if (txtColor.Text == "") {
brush = new SolidBrush(Color.White);
} else {
brush = new SolidBrush(pnlColor.BackColor);
}
}
//graphics.FillRectangle(brush,0,0,bitmap.Width,bitmap.Height);
bitmap.MakeTransparent(brush.Color);
graphics.Clear(brush.Color);
// Copy images into place
ImageAttributes attr = new ImageAttributes();
//attr.SetColorKey(brush.Color,brush.Color);
foreach(SpriteInformation sprite in sprites) {
Rectangle source = new Rectangle(0,0,sprite.Width,sprite.Height);
Rectangle dest = new Rectangle(sprite.Left,sprite.Top,sprite.Width,sprite.Height);
graphics.DrawImage(sprite.Sprite,dest,0,0,sprite.Width,sprite.Height,GraphicsUnit.Pixel,attr);
}
// Save image
string format = ddlFormat.Items[ddlFormat.SelectedIndex].ToString();
if (format == "PNG") {
dlgSave.Filter = "PNG Images|*.png|All Files|*.*";
dlgSave.DefaultExt = ",png";
if (dlgSave.ShowDialog() == DialogResult.OK) {
bitmap.Save(dlgSave.FileName,ImageFormat.Png);
}
} else if (format == "JPEG") {
} else {
}
What are sprite.Left and Top? If they aren't 0 that may be a problem. I think you have dest and source the wrong way round?
http://msdn.microsoft.com/en-us/library/ms142045.aspx
Try a simpler DrawImage variant if you haven't already.
e.g. DrawImage(sprite.Sprite,0,0)
You draw to "graphics", but then then you save "bitmap"? I'm not sure if that graphics internally works with your original "bitmap" object...