This is a .net web site. I have a list of 100 x,y coordinates.
I need to display 100 octagonal shapes the centre point of which sits at the respective co-ordinate.
I toyed with doing this by passing an array to javascript and dynamically creating and positioning the images. But it looks awful and resizing the browser window causes problems etc.
So, can I create a graphic myself? I saw this code answering a similar question:
using (Bitmap bmp = new Bitmap(10, 10))
{
using (Graphics g = Graphics.FromImage(bmp))
{
g.Clear(Color.White);
g.DrawLine(Pens.Black, new PointF(9.56f, 4.1f),
new PointF(3.456789f, 2.12345f));
}
bmp.Save(#"c:\myimage.jpg", ImageFormat.Jpeg);
}
Can you draw octagons easily enough using this?
However, when I try to run the code above, I am getting this error.
A generic error occurred in GDI+
I don't want to spend a long time working out out to draw octagons etc. if I can't get it to run.
One last thing, I don't need to save the graphic, I just want to display it as though it were an image I'm getting from the images folder.
Edit: Further to suggestion below I have modified the code like this:
using (MemoryStream ms = new MemoryStream())
{
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] buffer = ms.GetBuffer();
HttpContext.Current.Response.OutputStream.Write(buffer, 0, buffer.Length);
}
This is putting my drawing on the screen. Is there anything that should be tweaked?
You probably don't have write access to C:\.
Instead of saving to disk, you should save to a MemoryStream, then render it to the HTTP response. (inside of an ASHX or MVC action)
Related
How can I convert a System.Drawing.Bitmap to GDK# Image so that I can set to the image widget.
I have tried this...
System.Drawing.Bitmap b = new Bitmap (1, 1);
Gdk.Image bmp = new Gdk.Image (b);
UPDATE:
Bitmap bmp=new Bitmap(50,50);
Graphics g=Graphics.FromImage(bmp);
System.Drawing.Font ff= new System.Drawing.Font (System.Drawing.FontFamily.GenericMonospace, 12.0F, FontStyle.Italic, GraphicsUnit.Pixel);
g.DrawString("hello world",ff,Brushes.Red,new PointF(0,0));
MemoryStream ms = new MemoryStream ();
bmp.Save (ms, ImageFormat.Png);
Gdk.Pixbuf pb= new Gdk.Pixbuf (ms);
image1.Pixbuf=pb;
Exception:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> GLib.GException: Unrecognized image file format
at Gdk.PixbufLoader.Close()
at Gdk.PixbufLoader.InitFromStream(Stream stream)
at Gdk.PixbufLoader..ctor(Stream stream)
at Gdk.Pixbuf..ctor(Stream stream)
One ugly, but working, way is to store the bitmap as a PNG in a MemoryStream.
To save the Bitmap, you can use the Save method:
b.Save(myMemoryStream, ImageFormat.Png);
That was easy enough. Loading the PNG data into the Gdk# Pixbuf is also rather easy; you can use the appropriate constructor:
Pixbuf pb = new Gdk.Pixbuf(myMemoryStream);
You may need to reset the memory stream so the reading position is at the start of the stream before creating the Pixbuf.
A word of caution: I do not consider this the best, or even a "good" solution. Transferring data between two object-oriented data structures by serializing and deserializing the data has a certain code smell to it. I genuinely hope someone else can come up with a better solution.
EDIT: As for the used libraries: This answer uses only plain GDI+ (System.Drawing.Bitmap) and Gdk# (Gdk.Pixbuf). Note that a Gtk.Image is a widget that displays a Gdk.Pixbuf. As such, Gtk.Image is the equivalent of Windows Forms' PictureBox, whereas Gdk.Pixbuf is roughly equivalent to Windows Forms' System.Drawing.Bitmap.
EDIT2: After testing your code, I have found that there are three additional preconditions to ensure before you can run your minimum example:
As suspected above, you must reset the stream position to the beginning of the after saving your Bitmap and before loading your Pixbuf: ms.Position = 0;
You must compile the application for x86 CPUs.
You must invoke Gtk.Application.Init(); before you do anything with Pixbuf.
You may draw in Gtk# like in Winforms. For this you must obtain System.Drawing.Graphics object and then you may draw lines, images and text on it. You may do it like this: 1. Create new Widget. 2. Subscribe on ExposeEvent. 3. On event handler write some code:
protected void OnExposeEvent(object o, ExposeEventArgs e)
{
Gdk.Window window = e.Event.Window;
using (System.Drawing.Graphics graphics =
Gtk.DotNet.Graphics.FromDrawable(window))
{
// draw your stuff here...
graphics.DrawLine(new System.Drawing.Pen(System.Drawing.Brushes.Black), 0, 0, 30, 40);
}
}
Also you need to add reference on gtk-dotnet.dll.
try this ....
Gdk.Pixbuf pixbufImage = mew Gdk.Pixbuf(#"images/test.png");
Gtk.Image gtkImage = new Gtk.Image(pixbufImage);
Gdk.Image gdkImage = gtkImage.ImageProp;
Does .NET support PixelFormat conversions? I can't find any methods or constructors to do what I want.
I am allowing the user to choose any image file and I am creating a new Bitmap class from the file.
Then I am drawing the image using custom painting. It's very slow and I am told that the GDI is much faster dealing with images in the 32bppPArgb pixel format.
How do I perform the conversion? Assuming I have a string for the filename which could be a JPEG, TIF, PNG, etc., and I want to load it to a Bitmap class.
Edit:
Here is what I am trying to do, but it's not loading the image properly. The image is not filling the entire bitmap when I draw it.
using (Bitmap tempImage = new Bitmap(filename))
{
Image = new Bitmap(tempImage.Width, tempImage.Height, PixelFormat.Format32bppPArgb);
using (Graphics g = Graphics.FromImage(Image))
{
g.DrawImageUnscaled(tempImage, 0, 0);
}
}
If you have a scaling issue it is not caused by the pixel format. Instead, it is likely caused by DPI settings in the source image file. Try this instead of .DrawImageUnscaled:
g.DrawImage(
tempImage,
new Reactangle( Point.Empty, Image.Size ),
new Reactangle( Point.Empty, Image.Size ),
GraphicsUnit.Pixels );
That's what I always used instead of .DrawImageUnscaled - it has failed me too many times!
I use the following code block with some more code inside the using block:
using (System.Drawing.Bitmap tempImg =
(System.Drawing.Bitmap)tempObj.GetData(System.Windows.Forms.DataFormats.Bitmap))
{
// ...
tempImg.Save("..\\..\\testdata\\tempImg.bmp", ImageFormat.Bmp);
// ...
}
But I still get the error:
A Generic Error occured at GDI+
only after I make some action which is not related to the code inside the using block. In other times this works well.
Also the tempImg.bmp is a temporary file, so I delete the tempImg.bmp within the using block itself.
Since the tempImg is inside the using and this it's disposed, I think the locking problem should be solved.
Can someone please let me know what is the mistake in this code?
Edit:
System.Drawing.Image to System.Drawing.Bitmap as the type of tempImg.
Edit:
I have identified I get this error only after SaveFileDialog is created and user clicks on 'Save'.
Finally I could find what was wrong in my code and would like to mention it here as I think it may be useful to someone....
As I have given a relative path in tempImg.Save, and after the user clicks 'Save' in SaveFileDialog, the actual path for tempImg.Save become :
Path specified by SaveFileDialog + the relative path
automatically.
Thus if the path does not exist, this error occurs.
Thanks every one for the answers.
I also had once this problem- it happens because the bitmap locks and you can't save it( if you want I can find the exact explanation) so anyway a fix around is this:
Create a new bitmap the size of the original bitmap you have- copy the original bitmap to the new created bitmap and then dispose the original bitmap and save the new one.
Bitmap bm3 = new Bitmap(bm2);
And then save.
This is usually an indicator that something else, potentially some other thread in your own application, already has the target file that you're trying to save locked at the file system level. If you look at the inner exception I believe it should mention this. If it's not directly in the InnerException Another way to confirm this (or discover what it might really be instead) is to turn on first chance exceptions in the debugger and watch for what exception is being thrown "underneath" Save and then being turned into this generic exception.
Tried all the solutions given here, but in vain. Found the solution eventually.
Dispose any Graphics applied on image: g.dispose();
Make sure save path exists: System.IO.Directory.Exists(dir);
Is this an ASP.NET application?
A Generic Error occured at GDI+ in asp.net mostly because of missing target folder / access permissions.
Also your code could be simplified to :
using (Image image= dataObject.GetImage())
{
if (image != null)
{
image.Save("test.bmp");
}
}
In my case it was an ASP.NET application in which I replaced a single DLL, and I had to simply re-start the application pool after deployment. Then it worked fine.
This is code sample from Microsoft Forums.
// new image with transparent Alpha layer
using (var bitmap = new Bitmap(330, 18, PixelFormat.Format32bppArgb))
{
using (var graphics = Graphics.FromImage(bitmap))
{
// add some anti-aliasing
graphics.SmoothingMode = SmoothingMode.AntiAlias;
using (var font = new Font("Arial", 14.0f, GraphicsUnit.Pixel))
{
using (var brush = new SolidBrush(Color.White))
{
// draw it
graphics.DrawString(user.Email, font, brush, 0, 0);
}
}
}
// setup the response
Response.Clear();
Response.ContentType = "image/png";
Response.BufferOutput = true;
// write it to the output stream
bitmap.Save(Response.OutputStream, ImageFormat.Png);
Response.Flush();
}
I am trying to save image from resource and it gives me too GDI error when I directly use the method Bitmap.Save(filepath).
I think We can use the same below code for any other bitmap image by cloning it.
Private void SaveResourceImage() {
object resBmpObject = Resource.Image1.Clone();//Bitmap Image from resource file
//object resBmpObject = anyBmpImage.clone(); //for image other than resource image
Bitmap resBmpImage = (Bitmap)resBmpObject;
resBmpImage.Save(destFilePath, System.Drawing.Imaging.ImageFormat.Png);
resBmpImage.dispose();
}
Dispose your bitMap object after save image:
bitMap.Dispose()
oimg.Dispose()
bitMap = Nothing
oimg = Nothing
In my case, i was saving the bitmap file on the same location as the source,
So that's the problem.
I save the bitmap to the new location and all fine now.
I was facing the same issue, by changing image type ".bmp" to ".png" its work form me
I need the easy to learn & fast method for generating image from background image, texts and after that saving as JPEG format.
What you can suggest? Any library or tutorial on this? Important criteria is simpleness.
in .Net 3.5/4 you can also use WPF/Media.Imaging as an alternative to GDI+
First create a DrawingVisual and a DrawingContext:
DrawingVisual visual = new DrawingVisual();
DrawingContext dc = visual.RenderOpen();
Then draw stuff on it:
dc.DrawRectangle(...);
dc.DrawText(...);
etc...
Make sure you close it:
dc.Close();
The great thing about WPF is everything in the GUI is actually a visual too, so if you prefer you don't have to use the code above to draw programatically, you can actually build up your visual in xaml on a window and then just render that straight to the RenderTargetBitmap.
Once you have built your visual you can render it to a file using an encoder (.Net has encoders for Jpeg, Png, Bmp, Gif, Tiff and Wmp).
// Create a render target to render your visual onto. The '96' values are the dpi's, you can set this as required.
RenderTargetBitmap frame = new RenderTargetBitmap((int)visual.ContentBounds.Width, (int)visual.ContentBounds.Height, 96, 96, PixelFormats.Pbgra32);
frame.Render(visual);
// Now encode the rendered target into Jpeg and output to a file.
JpegBitmapEncoder jpeg = new JpegBitmapEncoder();
jpeg.Frames.Add(BitmapFrame.Create(frame));
using (Stream fs = File.Create(#"c:\filename.jpg"))
{
jpeg.Save(fs);
}
There are some good MS Tutorials on Drawing Objects and WPF Graphics Rendering.
I usually do this using GDI+. There are lots of tutorials on this on the net, but basically what you need to do is something like this:
using(Image image = new Bitmap(Width, Height))
using (Graphics g = Graphics.FromImage(image)) {
g.Draw....
g.Draw....
image.Save(filename, ImageFormat.Jpeg);
}
The calls to Draw.... you can draw primitives, images, text and so forth.
Also remember that is text looks jagged, you have methods on the Graphics object to smooth this out. In this case g.TextRenderingHint = TextRenderingHint.AntiAlias;
There are also other options to make it look better, if you feel it is jagged. The default settings is geared more towards performance than quality, so if you want high quality you need to set this yourself. g.SmoothingMode set to for example HighQuality will make your round primitives look much smoother than the default configuration.
It's really easy to use, and to make the final image look like you want it to, so give it a try!
Instead of good old GDI+ you can use the more modern (and often faster) System.Windows.Media.Imaging APIs.
GDI+ and the System.Drawing namespace are what is required to do what you want. A basic example is below but there are many resources on the net detailing more advanced features:
using(Bitmap myBitmap = new Bitmap("C:\\backgroundImage.jpg"))
using(Graphics g = Graphics.FromImage(myBitmap))
{
g.DrawString("Text", new Font("Arial", 10), Brushes.White, new PointF(0, 0));
myBitmap.Save("C:\\newImage.jpg");
}
i have some images..if these images are selected then it should generate another image which is the combination of all the selected images..
can anyone suggest as how to start with?
thanks
Use someting like that:
public void MergeImages(string FirstFileName, string SecondFileName)
{
Image firstImg = Image.FromFile(#"C:\temp\pic1.jpg");
Image secondImg = Image.FromFile(#"C:\temp\pic2.jpg");
Bitmap im1 = new Bitmap(firstImg);
Bitmap im2 = new Bitmap(secondImg);
Bitmap result = new Bitmap(im1.Width + im2.Width, (im1.Height > im2.Height) ? im1.Height : im2.Height);
Graphics gr = Graphics.FromImage(result);
gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
gr.DrawImage(firstImg, 0, 0);
gr.DrawImage(secondImg, im1.Width + 1, 0);
gr.Save();
result.Save(#"C:\test.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
}
this code merges two images in one, systeming them into line.
i used ImageMagick to do these kind of things (http://www.imagemagick.org/Usage/layers/)
It is however a little bit different then using gdi to create images, but it is a very fast (and when you get used to the imagemagick syntax) and powerful way to edit images.
Normally you use gdi to edit images in memory; imagemagick uses a commandline utility to create images.
So for example you want to layer two images on top, you start a new process in your code in which you fire up a imagemagick proces with the right parameters and then the image is created ON DISK.
Then you can server the created image with a response.writebinary.