I am using asp.net mvc3. I am making a bitmap using text by system.drawing. I want
to send that image from my controller to my view in VIEWDATA, but in my view I cannot parse VIEWDATA properly.
This is the controller code:
public ActionResult About( string agha)
{
agha = "asgdjhagsdjgajdga";
Color BackColor = Color.White;
String FontName = "Times New Roman";
int FontSize = 25;
int Height = 50;
int Width = 700;
Bitmap bitmap = new Bitmap(Width, Height);
Graphics graphics = Graphics.FromImage(bitmap);
Color color = Color.Gray; ;
Font font = new Font(FontName, FontSize);
SolidBrush BrushBackColor = new SolidBrush(BackColor);
Pen BorderPen = new Pen(color);
Rectangle displayRectangle = new Rectangle(new Point(0, 0), new Size(Width - 1, Height - 1));
graphics.FillRectangle(BrushBackColor, displayRectangle);
graphics.DrawRectangle(BorderPen, displayRectangle);
graphics.DrawString(agha,font,Brushes.Red, 0, 0);
ViewData["picture"] = bitmap;
return View( );
}
The view calling the viewdata looks like this
<img src="#ViewData["picture"]." />
I'd recommend you writing a custom action result to avoid polluting your controller action with completely useless and boring GDI+ infrastructure code:
public class ImageResult : ActionResult
{
private readonly string _agha;
public ImageResult(string agha)
{
_agha = agha;
}
public override void ExecuteResult(ControllerContext context)
{
Color BackColor = Color.White;
String FontName = "Times New Roman";
int FontSize = 25;
int Height = 50;
int Width = 700;
using (Bitmap bitmap = new Bitmap(Width, Height))
using (Graphics graphics = Graphics.FromImage(bitmap))
{
Color color = Color.Gray;
Font font = new Font(FontName, FontSize);
SolidBrush BrushBackColor = new SolidBrush(BackColor);
Pen BorderPen = new Pen(color);
Rectangle displayRectangle = new Rectangle(new Point(0, 0), new Size(Width - 1, Height - 1));
graphics.FillRectangle(BrushBackColor, displayRectangle);
graphics.DrawRectangle(BorderPen, displayRectangle);
graphics.DrawString(_agha, font, Brushes.Red, 0, 0);
context.HttpContext.Response.ContentType = "image/jpg";
bitmap.Save(context.HttpContext.Response.OutputStream, ImageFormat.Jpeg);
}
}
}
and then simply define a controller action that will return this custom action result:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Image(string agha)
{
return new ImageResult(agha);
}
}
and from within some view (~/Views/Home/Index.cshtml in my example) you could reference the action that will dynamically generate the image for you:
<img src="#Url.Action("Image", new { agha = "foo bar" })" alt="" />
Another possibility if you don't want to create an additional action to build the image is to use the Data URI scheme which basically allows you to embed the image as Base64 data directly into the HTML. One caveat with this is that not all browsers support it and ni addition to that it makes your HTML pages much larger.
If it doesn't need to be in the ViewData (not sure if you will be able to do it in the ViewData because each resource (image, flash, the page itself) has a ContentType that doesn't change in the current request.
However, you can try this in your controller:
public ActionResult GenerateImage() {
FileContentResult result;
using(var memStream = new System.IO.MemoryStream()) {
bitmap.Save(memStream, System.Drawing.Imaging.ImageFormat.Jpeg);
result = this.File(memStream.GetBuffer(), "image/jpeg");
}
return result;
}
In your view, you need to call the Controller/Action:
<img src='#Url.Action("GenerateImage")' alt="" />
Have you tried ContentResult.
You can try something like following ( not verified)
public ContentResult GetImage()
{
var content = new ContentResult();
content.Content = "Image as String";
content.ContentType = "image/jpg";
return content;
}
public ContentResult GetImage()
{
var content = new ContentResult();
content.Content = "Image as String";
content.ContentType = "~image/jpg";
return content;
}
public ActionResult GenerateImage() {
FileContentResult result;
using(var memStream = new System.IO.MemoryStream()) {
bitmap.Save(memStream, System.Drawing.Imaging.ImageFormat.Jpeg);
result = this.File(memStream.GetBuffer(), "image/jpeg");
}
return result;
}
Related
I want to save my label Control, but I have no idea to save it.
I tried draw text in Graphics class, but I can't draw "even allocation".
Is there any good way?
public Label makeLabel(string text, double width, double height, FontFamily fontFamily, FontStyle fontStyle, FontStretch fontStretch)
{
var label = new Label();
label.Width = width;
label.Height = height;
label.FontFamily = fontFamily;
label.FontStyle = fontStyle;
label.FontStretch = fontStretch;
label.Content = text;
return label;
}
public void SavePicture(Label label)
{
var path = "label.png";
// I have no idea to save;
}
public void SavePicture(Label label)
{
var path = "label.png";
var width = label.Width;
var height = label.Height;
var viewBox = new Viewbox();
var renderTargetBitmap = new RenderTargetBitmap((int)width, (int)height, 96, 96, PixelFormats.Pbgra32);
var pngBitmapEncoder = new PngBitmapEncoder();
viewBox.Child = label;
viewBox.Measure(new Size(width, height));
viewBox.Arrange(new Rect(0, 0, width, height));
viewBox.UpdateLayout();
renderTargetBitmap.Render(viewBox);
pngBitmapEncoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
using (var fileStream = File.Create(path))
{
pngBitmapEncoder.Save(fileStream);
}
}
This works without having label displayed on screen.
void SavePicture(FrameworkElement el)
{
RenderTargetBitmap bitmap = new RenderTargetBitmap((int)el.ActualWidth, (int)el.ActualHeight, 96, 96, PixelFormats.Pbgra32);
bitmap.Render(el);
using (FileStream stream = File.Create(#"label.png"))
{
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
encoder.Save(stream);
}
}
But you can call this method only after the Label is displayed.
I use the following method to create some image.
My question is how I can display it in .cshtml page (MVC3)? Which Razor syntax I have to use?
public FileContentResult DisplayFont()
{
int fontSize = 12;
string fontName = "Arial";
System.Drawing.Font rectangleFont = new System.Drawing.Font(fontName, fontSize, FontStyle.Bold);
int height = 150;
int width = 250;
Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb);
Graphics g = Graphics.FromImage(bitmap);
g.SmoothingMode = SmoothingMode.AntiAlias;
Color backgroundColor = Color.White;
g.Clear(backgroundColor);
g.DrawString(fontName, rectangleFont,SystemBrushes.WindowText, new PointF(10, 40));
MemoryStream outputStream = new MemoryStream();
bitmap.Save(outputStream, ImageFormat.Jpeg);
byte[] byteArray = outputStream.ToArray();
g.Dispose();
bitmap.Dispose();
return new FileContentResult(byteArray, "image/jpeg");
}
You can render it using a normal HTML img tag, using the URL of your DisplayFont action:
<img src='#Url.Action("DisplayFont")' />
I add text like this:
TreeNode treeNode = new TreeNode("Person");
String[] str = new string[] {"name", "age"};
this.TreeView.Nodes.Add(treeNode);
this.TreeView.Nodes[0].Tag = str;
Image in .png extension
Another problem is that all icons in one image, it's like an array :
How should I grab this icons from this image ?
you could split images with following manner, update code for your needs
For win forms
private List<Image> GetImages(string imageFile)
{
var images = new List<Image>();
Image rootImage = Image.FromFile(imageFile);
for (int i = 0; i < 6; i++)
{
Image image = CropImage(rootImage, new Rectangle(10 + i * 60, 0, 70, 60));
images.Add(image);
}
return images;
}
private static Image CropImage(Image image, Rectangle area)
{
var bmpImage = new Bitmap(image);
Bitmap bmpCrop = bmpImage.Clone(area, bmpImage.PixelFormat);
return (bmpCrop);
}
for wpf
var image = new Image {Width = 70, Height=60};
var source = new BitmapImage(new Uri(filePath));
var bitmap = new CroppedBitmap(source, new Int32Rect(0, 0, 70, 60));
image.Source = bitmap;
you could fill tag property after creating images
I have a requirement wherein I need to merge two different png/jpeg images resulting into a single image using C#.Net. There will be a particular location defined on the source image wherein I need to insert another image. Can anybody suggest some links ?
This method merge two images one in the top of the other you can modify the code to meet for your needs:
public static Bitmap MergeTwoImages(Image firstImage, Image secondImage)
{
if (firstImage == null)
{
throw new ArgumentNullException("firstImage");
}
if (secondImage == null)
{
throw new ArgumentNullException("secondImage");
}
int outputImageWidth = firstImage.Width > secondImage.Width ? firstImage.Width : secondImage.Width;
int outputImageHeight = firstImage.Height + secondImage.Height + 1;
Bitmap outputImage = new Bitmap(outputImageWidth, outputImageHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
using (Graphics graphics = Graphics.FromImage(outputImage))
{
graphics.DrawImage(firstImage, new Rectangle(new Point(), firstImage.Size),
new Rectangle(new Point(), firstImage.Size), GraphicsUnit.Pixel);
graphics.DrawImage(secondImage, new Rectangle(new Point(0, firstImage.Height + 1), secondImage.Size),
new Rectangle(new Point(), secondImage.Size), GraphicsUnit.Pixel);
}
return outputImage;
}
After all this, I found a new easier method try this ..
It can join multiple photos together:
public static System.Drawing.Bitmap CombineBitmap(string[] files)
{
//read all images into memory
List<System.Drawing.Bitmap> images = new List<System.Drawing.Bitmap>();
System.Drawing.Bitmap finalImage = null;
try
{
int width = 0;
int height = 0;
foreach (string image in files)
{
//create a Bitmap from the file and add it to the list
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(image);
//update the size of the final bitmap
width += bitmap.Width;
height = bitmap.Height > height ? bitmap.Height : height;
images.Add(bitmap);
}
//create a bitmap to hold the combined image
finalImage = new System.Drawing.Bitmap(width, height);
//get a graphics object from the image so we can draw on it
using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(finalImage))
{
//set background color
g.Clear(System.Drawing.Color.Black);
//go through each image and draw it on the final image
int offset = 0;
foreach (System.Drawing.Bitmap image in images)
{
g.DrawImage(image,
new System.Drawing.Rectangle(offset, 0, image.Width, image.Height));
offset += image.Width;
}
}
return finalImage;
}
catch (Exception)
{
if (finalImage != null)
finalImage.Dispose();
//throw ex;
throw;
}
finally
{
//clean up memory
foreach (System.Drawing.Bitmap image in images)
{
image.Dispose();
}
}
}
Disclaimer: I work at Atalasoft
Our DotImage Photo SDK (which is free) can do this.
To open an image
AtalaImage botImage = new AtalaImage("bottomImage.png");
AtalaImage topImage = new AtalaImage("topImage.png");
To overlay one on top of another
Point pos = new Point(0,0); // or whatever you need
OverlayCommand cmd = new OverlayCommand(topImage, pos);
ImageResults res = cmd.Apply(botImage);
If you need the resulting image to be a different size, look at the CanvasCommand. You could also create an AtalaImage of the size you need, then overlay each image onto it.
To save
botImage.Save("newImage.png", new PngEncoder(), null);
String jpg1 = #"c:\images.jpeg";
String jpg2 = #"c:\images2.jpeg";
String jpg3 = #"c:\image3.jpg";
Image img1 = Image.FromFile(jpg1);
Image img2 = Image.FromFile(jpg2);
int width = img1.Width + img2.Width;
int height = Math.Max(img1.Height, img2.Height);
Bitmap img3 = new Bitmap(width, height);
Graphics g = Graphics.FromImage(img3);
g.Clear(Color.Black);
g.DrawImage(img1, new Point(0, 0));
g.DrawImage(img2, new Point(img1.Width, 0));
g.Dispose();
img1.Dispose();
img2.Dispose();
img3.Save(jpg3, System.Drawing.Imaging.ImageFormat.Jpeg);
img3.Dispose();
private void Merge _Click(object sender, EventArgs e)
{
}
DirectoryInfo directory=new DirectoryInfo("D:\\Images");
if(directory!=null)
{
FileInfo[]files = directory.GetFiles();
MergeImages(Image);
}
private void MergeImages(FileInfo[] Image)
{
//change the location to store the final image.
string FImage= #"D:\\Images\\FImage.jpg";
List imageHeights = new List();
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 NewImg = new Bitmap(width, height);
Graphics Gr= Graphics.FromImage(NewImg);
Gr.Clear(SystemColors.AppWorkspace);
foreach (FileInfo file in files)
{
Image img = Image.FromFile(file.FullName);
if (nIndex == 0)
{
Gr.DrawImage(img, new Point(0, 0));
nIndex++;
width = img.Width;
}
else
{
Gr.DrawImage(img, new Point(width, 0));
width += img.Width;
}
img.Dispose();
}
Gr.Dispose();
NewImg .Save(FImage, System.Drawing.Imaging.ImageFormat.Jpeg);
NewImg .Dispose();
imageLocation.Image = Image.FromFile(FImage);
}
I'm using mvc2 and I would like to use action in controller, for example ShowSmallImage) and when I type www.url.com/ShowSmallImage that in browser the output is an image.
I tried something like this:
public Bitmap CreateThumbnail()
{
Image img1 = Image.FromFile(#"C:...\Uploads\Photos\178.jpg");
int newWidth = 100;
int newHeight = 100;
double ratio = 0;
if (img1.Width > img1.Height)
{
ratio = img1.Width / (double)img1.Height;
newHeight = (int)(newHeight / ratio);
}
else
{
ratio = img1.Height / (double)img1.Width;
newWidth = (int)(newWidth / ratio);
}
//a holder for the result
Bitmap result = new Bitmap(newWidth, newHeight);
//use a graphics object to draw the resized image into the bitmap
using (Graphics graphics = Graphics.FromImage(result))
{
//set the resize quality modes to high quality
graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
//draw the image into the target bitmap
graphics.DrawImage(img1, 0, 0, result.Width, result.Height);
}
return result;
}
As a result I get only System.Drawing.Bitmap in browser. I suppose I need to set response/content type of the page but have no idea how to do it...
Thanks,
Ile
Create a fileresult and return the stream to the bitmap & set the content type:
private FileResult RenderImage()
{
MemoryStream stream = new MemoryStream();
var bitmap = CreateThumbnail();
bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp);
Byte[] bytes = stream.ToArray();
return File(bytes, "image/png");
}
In a controller, say ResourceController you could have an Action that returns a FileResult. Like so
public FileResult Thumbnail()
{
var bitmap = // Your method call which returns a Bitmap
var ms = new MemoryStream();
bitmap.Save(ms, ImageFormat.Png);
return new FileStreamResult(ms, "image/png");
}
Then you can call http://www.mysite.com/Resource/Thumbnail.