Opening an image file to a Bitmap class as 32bppPArgb - c#

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!

Related

Save .jpg image in grayscale using C# [duplicate]

We have a system that provides images in 8-bit grayscale either tiff or jpg formats. However, the component we have to process the images expects image to be in 8-bit jpg format.
When I use .Net to save the tiff images as jpg it convets it to 24-bit image.
Is there a way, hopefully simple and fast, to convert 8-bit grayscale tiff images to equivalent jpg?
I tried and tried just to conclude that I'm sorry: .Net library's Bitmap class DOES NOT save JPEG as 8bpp even when explicitly stated and data is in grayscale.
(note: although stated in some places, JPEG format DOES support 8bpp).
At Convert an image to grayscale you may find code snipet to convert to grayscale any Image.
Using that code, I was able to save a 8bpp grayscale Image instance with '.jpeg' extension, but stating ImageFormat.Gif... that's a cheat...
My findings show as solution an entirely different approach.
The FreeImage library offers powerful APIs, including the feature needed to solve your problem.
It's home page is at http://freeimage.sourceforge.net/faq.html
But, I could not easily compile it in my Win2008 + VS 2010 machine.
One ought to sweat a lot to make it run on modern environments.
Some hints on how to accomplish that are found at http://www.sambeauvois.be/blog/2010/05/freeimage-and-x64-projects-yes-you-can/
Good luck!
Image img = Image.FromFile(filePathOriginal);
Bitmap bmp = ConvertTo8bpp(img);
EncoderParameters parameters = new EncoderParameters();
parameters.Param[0] = new EncoderParameter(Encoder.ColorDepth, 8);
bmp.Save(filePathNew, jpgCodec, parameters);
bmp.Dispose();
img.Dispose();
...
private static Bitmap ConvertTo8bpp(Image img) {
var bmp = new Bitmap(img.Width, img.Height, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
using (var gr = Graphics.FromImage(bmp))
{
gr.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height));
}
return bmp;
}

Create a graphic image dynamically using C#

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)

Image manipulation

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");
}

C# Convert indexed pixel to new file bit32

Does anybody have a sample code on how i could open a tif file, copy it out to a new locate from indexed pixel to new bitmap 32?
I found this http://fci-h.blogspot.com/2008/02/c-indexed-pixel-problem.html But i'm to new to piece it together. Is there a possible way to just read this all in memory without actually creating a new file?
What I mean is this. I have to find the original file (which i already got). Copy the file to a temp location (which I got). What I don't understand is how when I copy that new file I need to keep the original size and give the new file a bitmap of 32.
I can't draw an image over the picturebox because C# doesnt really support indexed pixels.
Bitmap newImage = new Bitmap(original);
This will make your newImage start with the contents of original. The difference will be that you will end up with newImage.PixelFormat == PixelFormat.Format32bppArgb, regardless of original.PixelFormat.
This does what you want I think...
If you dont need to save it, just work with 'bm' after you do the DrawImage, that is your image as a Bitmap...
Bitmap bm = (Bitmap)System.Drawing.Image.FromFile("TifFilePath.tif", true);
Bitmap tmp = new Bitmap(bm.Width, bm.Height);
Graphics grPhoto = Graphics.FromImage(tmp);
grPhoto.DrawImage(bm, new Rectangle(0, 0, tmp.Width, tmp.Height), 0, 0, tmp.Width, tmp.Height, GraphicsUnit.Pixel);
bm.Save("JPGFilePath.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
grPhoto.Dispose();

Basics in Resizing Pictures or What happened to Picture Size?

I am writing a program that resizes pictures like this:
Image originalImage = Image.FromFile(pathToOriginalPicture);
Bitmap b = new Bitmap(newWidth, newHeight);
Graphics g = Graphics.FromImage(b);
g.DrawImage(originalImage, 0, 0, newWidth, newHeight);
g.Dispose();
b.Save(pathToOutputPicture, ImageFormat.Jpeg);
I tried to set:
newWidth = originalImage.Width;
newHeight = originalImage.Height;
The result was that the rezised picture file became ~900K while the original file was ~4M.
Why this is happening ?
Is the quality of the original picture better than the resized one ? How?
I opened both pictures in Photoshop and I see that the original picture was 72ppi, while the resized one became 96ppi. Why is that ? Can I control this ?
Thanks a lot for your time !
You're not telling us the original format of your picture but you're saving as a JPEG:
b.Save(pathToOutputPicture, ImageFormat.Jpeg);
JPEG is a lossy compression format.
In addition to being lossy, JPEG also can output different quality (which is configurable).
This is what is happening to your file size: it is shrinking because you went, say, from a lossless format to the lossy JPEG or because you went from JPEG to JPEG-with-a-lower-quality.
Hence the size reduction.
Besides the format you need to set DPI, compression level settings etc. Check your Save function for overloads that will accept this type of input. See this documentation.

Categories

Resources