using (var mem = new MemoryStream())
using (var bmp = new Bitmap(85, 54))
using (var gfx = Graphics.FromImage((Image)bmp))
{
// gfx.SmoothingMode = SmoothingMode.AntiAlias;
gfx.PageUnit = GraphicsUnit.Millimeter;
gfx.FillRectangle(Brushes.Red, new Rectangle(0, 0, bmp.Width, bmp.Height));
//add question
gfx.DrawString(captcha, new Font("Arial", 5), Brushes.Blue, bmp.Width / 2, bmp.Height/2);
//render as Jpeg
bmp.Save(mem, System.Drawing.Imaging.ImageFormat.Jpeg);
img = this.File(mem.GetBuffer(), "image/Jpeg");
}
return img;
this not work.
I need 85x54 millimeter
how do this?
I need draw for print
The size of this Bitmap is in pixels.
When you display a bitmap on a regular display a single pixel will be 1/96th of an inch. Other displays might have other DPI's (Dots Per Inch) - such as Retina displays
Most printers support at least 300 DPI.
So what you need to do is get the DPI of the screen or printer and size the bitmap accordingly or use a image format (vector?) that allows you to specify the DPI. Some bitmap formats also allow you to specify the intended DPI
Digital images are always in pixels. Never in millimeters or inches. Depending on the DPI (dots per inch) you'll use when printing, the pixels are translated to millimeters or inches.
For screen, use 72 pixels per inch, for print use 300.
For your picture (85x54mm = 3.34x2.12in) use (3.34 * 300) x (2.12 * 300) = 1002 x 637 pixels for print.
Related
I have bitmap residing in memory (coming from my webcam but I don't think that this makes a difference.
It is 960x540 120dpi
you see that the picture in the lower part gets till the point where my shirt begins.
I know the bmp dimensions since I put this code prior resize
using (var fileStream = new FileStream(#"C:\temp\3.bmp", FileMode.Create))
{
BitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(source));
encoder.Save(fileStream);
}
and the result is the picture above.
Then I resize it with that:
var resizedImage = new RenderTargetBitmap(
width, height, // Resized dimensions 200x112
source.DpiX, source.DpiY,// Default DPI values
PixelFormats.Default); // Default pixel format
and the result is the bmp below which is properly 200x112 but it cuts out in part of the image in the lower and right part.
I have seen that the problem is related with the dpi value in the RenderTargetBitmap instruction. If I divide the dpi by 1.25 everything gets fine but why 1.25???????
Thank you in advance for any help
Patrick
--ADD--
There is something additional that I can't understand: I know the initial bitmap size for I have saved it to filesytem with the instructions above.
But if I look at the properties by putting a breakpoint I see:
BITMAP BEFORE RESIZE
width,height = 768, 432
pixelwidth, pixelheight = 960, 540
dpiX, dpiY= 120, 120
BITMAP AFTER RESIZE
width,height = 160, 89
pixelwidth, pixelheight = 200, 112
dpiX, dpiY= 120, 120
now I know that what counts here is pixelwidth, pixelheight so that's correct.
If I do 960/786 I get 1.25! So that's my number but why? Can I correct the code as to make it a general solution???
Instead of a RenderTargetBitmap you should simply use a TransformedBitmap with an appropriate ScaleTransform:
var scale = 200d / 960d;
var resizedImage = new TransformedBitmap(source, new ScaleTransform(scale, scale));
I am drawing the text using Graphics.DrawString() method, But the text height drawn is not same as which i gave.
For Eg:
Font F=new Font("Arial", 1f,GraphicUnit.Inch);
g.DrawString("M", F,Brushes.red,new Point(0,0));
By using the above code, i'm drawing the text with height 1 inch, but the text drawn is not exactly in 1 inch.
I need to Draw the text in Exact height which i'm giving. Thanks in advance..
The simplest solution will be to use a GraphicsPath. Here are the steps necessary:
Calculate the height you want in pixels: To get 1.0f inches at, say 150 dpi you need 150 pixels.
Then create a GraphicsPath and add the character or string in the font and font style you want to use, using the calculated height
Now measure the resulting height, using GetBounds.
Then scale the height up to the necessary number of pixels
Finally clear the path and add the string again with the new height
Now you can use FillPath to output the pixels..
Here is a code example. It writes the test string to a file. If you want to write it to a printer or a control using their Graphics objects, you can do it the same way; just get/set the dpi before you calculate the first estimate of the height..
The code below creates this file; the Consolas 'x' is 150 pixels tall as is the 2nd character (ox95) from the Wingdings font. (Note that I did not center the output):
// we are using these test data:
int Dpi = 150;
float targetHeight = 1.00f;
FontFamily ff = new FontFamily("Consolas");
int fs = (int) FontStyle.Regular;
string targetString = "X";
// this would be the height without the white space
int targetPixels = (int) targetHeight * Dpi;
// we write to a Btimpap. I make it large enough..
// Instead you can write to a printer or a Control surface..
using (Bitmap bmp = new Bitmap(targetPixels * 2, targetPixels * 2))
{
// either set the resolution here
// or get and use it above from the Graphics!
bmp.SetResolution(Dpi, Dpi);
using (Graphics G = Graphics.FromImage(bmp))
{
// good quality, please!
G.SmoothingMode = SmoothingMode.AntiAlias;
G.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
// target position (in pixels)
PointF p0 = new PointF(0, 0);
GraphicsPath gp = new GraphicsPath();
// first try:
gp.AddString(targetString, ff, fs, targetPixels, p0,
StringFormat.GenericDefault);
// this is the 1st result
RectangleF gbBounds = gp.GetBounds();
// now we correct the height:
float tSize = targetPixels * targetPixels / gbBounds.Height;
// and if needed the location:
p0 = new PointF(p0.X - gbBounds.X, p0.X - gbBounds.Y);
// and retry
gp.Reset();
gp.AddString(targetString, ff, fs, tSize, p0, StringFormat.GenericDefault);
// this should be good
G.Clear(Color.White);
G.FillPath(Brushes.Black, gp);
}
//now we save the image
bmp.Save("D:\\testString.png", ImageFormat.Png);
}
You may want to try using the correction factor to scale up a Font size and use DrawString after all.
There is also a way to calculate the numbers ahead using FontMetrics, but I understand the link to mean that such an approach could be font-dependent..
What i have:
A JPEG image with 96dpi, size: 540 X 700
What i Want:
JPEG image with 300dpi, size: 771 X 1000
Problem:
When i resize the image first and then try to change the resolution, through the following code it doesnt work
/// <summary>
/// Changes the resolution of the image
/// </summary>
/// <param name="imgPath">Image Path</param>
/// <param name="xResolution">x Resolution</param>
/// <param name="yResolution">y Resolution</param>
/// <returns>Modified Image Path</returns>
private string ChangeResolution(string imgPath, int xResolution, int yResolution)
{
string fullFileName = Path.GetFileNameWithoutExtension(imgPath);
string extension = Path.GetExtension(imgPath);
string tmpFileSavedPath = outputDir + "\\" + fullFileName + "_." + extension + "_tmp";
Image original = Bitmap.FromFile(imgPath);
original.Save(tmpFileSavedPath);
Bitmap bmSmall = new Bitmap(tmpFileSavedPath);
bmSmall.SetResolution(xResolution, yResolution);
string modifiedOverLayImagePath = tmpFileSavedPath.TrimEnd("_tmp".ToCharArray());
bmSmall.Save(modifiedOverLayImagePath);
bmSmall.Dispose();
//Deleting temp file
System.IO.File.Delete(tmpFileSavedPath);
return modifiedOverLayImagePath;
}
means it does nothing to the image, the resolution remains the same, if i go other way round, i.e. change resolution first and then change the size, surprisingly the size gets changed but the resolution is reduced back to 96dpi.
Here is the resizing code:
public static System.Drawing.Bitmap ResizeImage(System.Drawing.Image image, int width, int height)
{
//a holder for the result
Bitmap result = new Bitmap(width, height);
//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(image, 0, 0, result.Width, result.Height);
}
//return the resulting bitmap
return result;
}
Can anybody help me out, i am wondering if 771 X 1000 supports 300dpi resolution, but when i do this in photoshop it works perfectly, thanks
Following is my main function in which i am changing resolution first and resizing afterwards:
string imgPath = #"D:\abc\background.jpg";
string newResPath = ChangeResolution(imgPath, 300, 300);
Image oldImage = Bitmap.FromFile(newResPath);
//Image newImage = ImageResize.ConstrainProportions(oldImage, 771, ImageResize.Dimensions.Width);
Image newImage = ImageUtilities.ResizeImage(oldImage, 771, 1000);
string savedPath = "D:\\abc\\saved.jpg";
try
{
newImage.Save(savedPath, ImageFormat.Jpeg);
}
catch
{
MessageBox.Show("error");
}
newImage.Dispose();
private static Bitmap _resize(Image image, int width, int height)
{
Bitmap newImage = new Bitmap(width, height);
//this is what allows the quality to stay the same when reducing image dimensions
newImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (Graphics gr = Graphics.FromImage(newImage))
{
gr.SmoothingMode = SmoothingMode.HighQuality;
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
gr.DrawImage(image, new Rectangle(0, 0, width, height));
}
return newImage;
}
JPEG actual resolution is certain width by height pixels - this is what really matters. So the real important step is ImageUtilities.ResizeImage to newer resolution.
DPI resolution field is informational only and provides a sort of a hint for how large the original pixel was in first place. So, after resizing pixels you are to update DPI field to whatever value you think it should be.
In short, DPI is not important in this case
Nicely explained on this answer.
DPI stands for Dots Per Inch. One clue as to the 96dpi reset comes from wikipedia:
... many Windows software programs have been written since the 1980s to assume that the screen provides 96 PPI
In reality, your screen will display your image at it's resolution, the DPI (or PPI, Pixels Per Inch) is determined by your screen size. DPI really only comes into play when printing your image.
Depending on which device you are printing on the DPI will vary.
I am trying to save an image from string.
so I want to know how I can set image height and width in inches at the time of saving the image.
my code follows for image saving :
private void Base64ToImage(string base64String)
{
Image fullSizeImg = null;
byte[] imageBytes = Convert.FromBase64String(base64String);
MemoryStream ms = new MemoryStream(imageBytes);
fullSizeImg = Image.FromStream(ms, true);
System.Drawing.Image.GetThumbnailImageAbort dummyCallBack = new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
System.Drawing.Image thumbNailImg = fullSizeImg.GetThumbnailImage(700, 800, dummyCallBack, IntPtr.Zero);
thumbNailImg.Save(ImagePath, System.Drawing.Imaging.ImageFormat.Png);
fullSizeImg.Dispose();
thumbNailImg.Dispose();
}
That doesn't work. We save in pixels because an inch/cm/mile does not convert to on-screen real estate. The reason for this is that we all use different DPI settings, albeit 92 DPI seems to be one of the more common settings nowadays.
There are also varying DPI settings for printers...
To calculate the pixels from inches, you could try:
pixels = inches * someDpiSetting
but bear in mind this will not result in inches on every screen, every printout, etc.
EDIT: If you take a look at WPF you'll find that it has fantastic support for DPI, and will translate a form to the same (give or take) size regardless of DPI. Maybe that helps?
Bitmaps don't have a size in inches, their size is measured in pixels. That said most modern bitmat formats have a piece of metadata called DPI (dots per inch) that is used to translate a size in pixels to a size in inches via the simple formula:
inches = pixels / dpi
For the Image class you set metadata using the SetPropertyItem Method where the pieces of metadata we are interested in are:
PropertyTagResolutionUnit - set this to "2" for inches
PropertyTagXResolution - Essentially the X DPI as long as PropertyTagResolutionUnit is in inches.
PropertyTagYResolution - The Y DPI as long as PropertyTagResolutionUnit is in inches
See Property Item Descriptions for details.
(Actually, I realised half way through writing this that the setting of property metadata using SetPropertyItem looks really complicated - you might just be better off using Bitmat instead, which has resolution properties making the whole thing a lot easier)
As a contrast to those imperial measures and formula-only's:
// inches = pixels / dpi
// pixel = inches * dpi
// 1 centimeter = 0.393700787 inch
// pixel = cm * 0.393700787 * dpi
single sngWidth = 2.25; //cm
single sngHeight = 1.0; //cm
sngWidth *= 0.393700787 * bmpImage.HorizontalResolution; // x-Axis pixel
sngHeight *= 0.393700787 * bmpImage.VerticalResolution; // y-Axis pixel
Like so:
public static int Cm2Pixel(double WidthInCm)
{
double HeightInCm = WidthInCm;
return Cm2Pixel(WidthInCm, HeightInCm).Width;
} // End Function Cm2Pixel
public static System.Drawing.Size Cm2Pixel(double WidthInCm, double HeightInCm)
{
float sngWidth = (float)WidthInCm; //cm
float sngHeight = (float)HeightInCm; //cm
using (System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(1, 1))
{
sngWidth *= 0.393700787f * bmp.HorizontalResolution; // x-Axis pixel
sngHeight *= 0.393700787f * bmp.VerticalResolution; // y-Axis pixel
}
return new System.Drawing.Size((int)sngWidth, (int)sngHeight);
} // End Function Cm2Pixel
If you are using a Bitmap then it has the method SetResolution (http://msdn.microsoft.com/en-us/library/system.drawing.bitmap.setresolution.aspx) that allows you to set the x and y dpi which can be easily derived from your knowledge of the height and width of the image in pixels and inches that you already have.
I'm hoping here that using a Bitmap instead of an Image shouldn't be a problem. Its a subclass so I would imagine it is likely you can.
MemoryStream ms = new MemoryStream();
new FileStream(Afiladdress, FileMode.Open).CopyTo(ms);
Bitmap myimage = new Bitmap(ms);
float Width = myimage.Width / myimage.HorizontalResolution;//in INCHES
float Height= myimage.Height/ myimage.VerticalResolution;//in INCHES
Pls. suggest how to set an image's width & Height Property while saving Images
If you want to save bitmap with some specific width and height (which differ from the Width and Height properties of the bitmap), you need to create a new Bitmap of corresponding size and draw the initial bitmap in needed size on it.
Like this:
using (Bitmap bmpToSave = new Bitmap(1000, 500)) {
using (Graphics g = Graphics.FromImage(bmpToSave)) {
g.DrawImage(bmp, 0, 0, 1000, 500);
}
bmpToSave.Save(#"bitmap.bmp");
}
Where bmp is your original bitmap.
Also, read up on some options that affect the quality of resampling if you need the high quality result.