I'm using the following code to get a picture from the the MediaLibrary on the phone and resize it. In the emulator it is working fine but it is rotating it -90 degrees when I try it on a real phone.
The 4th parameter for SaveJpeg is orientation and the tooltip says
"This parameter is not currently used by this method. Use a value of 0 as a placeholder."
The same thing happens if I pass 0,1,-1. Seems like it might actually be implemented on the phone and not in the emulator, but I don't know what to pass.
public byte[] GetPhoto(string photoName, int width, int height)
{
using (var ml = new Microsoft.Xna.Framework.Media.MediaLibrary())
{
using(Stream stream = (from p in ml.Pictures where p.Name == photoName select p).FirstOrDefault().GetImage())
{
//load the stream into a WriteableBitmap so it can be resized
using(MemoryStream outstream = new MemoryStream())
{
PictureDecoder.DecodeJpeg(stream).SaveJpeg(outstream, width, height, 0, 85);
return outstream.ToArray();
}
}
}
}
Also I just noticed that the sample pictures on the phone are not having this problem, just the ones I've taken.
I don't think the EXIF data for orientation is read by WP7 (happy to be corrected as I've only tried when the CTP SDK was out). However, you can manually rotate your picture using this method. An alternative, which I haven't tried, could be to get the image's rotate transform and rotate it 90 degrees. Transform rotations may work out to be quicker than manually shifting all the pixels of the writeable bitmap.
Related
I've got a strange problem. There is an image. Unfortunately it's too big to show it in question. But you can download it. If you can't do it from OneDrive this is another way.
This image seems to be ordinary, but it's not.
When we open properties we will see this:
We need to keep in mind dimensions of this picture: Width is 3000px and Height is 4000px. It looks correct because image is portret.
Then lets try to read it with C#:
private static void TestImage()
{
using (FileStream file1 = new FileStream("DSC_2446.JPG", FileMode.Open))
{
Console.WriteLine("DSC_2446.JPG :");
using (var img1 = System.Drawing.Image.FromStream(file1))
{
Console.WriteLine($" Width = {img1.Width}");
Console.WriteLine($" Height = {img1.Height}");
}
}
Console.Read();
}
And in results we see some magic!!!
So I've got completely wrong values. Values are switched between properties.
Does someone know why it can happens and how to detect/fix this behavior?
The problem is the EXIF version. You can use this site to get the real data https://exif.tools/meta/Exif-Version/0231 and you will see
Also according to this Post you can get your image's orientation by
var orientation = (int)img1.GetPropertyItem(274).Value[0];
//orientation = 6
the value 6 means rotate 90 degrees.
There is the reference of the value 6. https://exiftool.org/TagNames/EXIF.html
Im editing a pdf. The client wants the image inside pdf to be resize and rotated.
so what i did is to extract the image inside the pdf to be able to manipulate the image then insert it again to the the pdf(replacing the old one)
here is the code where i got the code for extracting image
https://psycodedeveloper.wordpress.com/2013/01/10/how-to-extract-images-from-pdf-files-using-c-and-itextsharp/
but when i extract the image to image is rotated 180 degree
i even used the free Spire.PDF to extract the image but the extracted image of the spire.pdf is rotated 90 degree. so how can i get the image orientation of the pdf. so that i can make the image to its original orientation. thank you
There are two relevant factors deciding on the effective rotation of an image, the current transformation matrix at the time the image is drawn (which also fixes the dimensions of the image) and the page rotation.
You can determine these values as shown below in the code you refer to:
...
public static Dictionary<string, System.Drawing.Image> ExtractImages(string filename)
{
var images = new Dictionary<string, System.Drawing.Image>();
using (var reader = new PdfReader(filename))
{
var parser = new PdfReaderContentParser(reader);
ImageRenderListener listener = null;
for (var i = 1; i <= reader.NumberOfPages; i++)
{
// v-- Determine clockwise rotation of page
Console.WriteLine("Page {1} is rotated by {0}°.\n", reader.GetPageRotation(i), i);
// ^-- Determine clockwise rotation of page
parser.ProcessContent(i, (listener = new ImageRenderListener()));
var index = 1;
[...]
}
return images;
}
}
...
public void RenderImage(ImageRenderInfo renderInfo)
{
// v-- Determine transformation matrix of image
Matrix ctm = renderInfo.GetImageCTM();
Console.WriteLine("Found image with transformation matrix:\n{0}\n", ctm);
// ^-- Determine transformation matrix of image
PdfImageObject image = renderInfo.GetImage();
PdfName filter = (PdfName)image.Get(PdfName.FILTER);
[...]
}
...
The output in your case:
Page 1 is rotated by 270°.
Found image with transformation matrix:
792,0001 0 0
0 612 0
0 0 1
Found 1 images on page 1.
Thus, the transformation matrix obviously only scales the image to the appropriate dimensions without rotating it but the page itself is defined to be shown rotated by 270°.
This corresponds to my observations. In particular in contrast to what you said:
but when i extract the image to image is rotated 180 degree
I get an image from your code which has to be rotated by 270° clockwise to be upright.
If you indeed get an image rotated by 180°, you should check the version of iTextSharp you use. The archive on the web site you refer to contains a fairly old version, 5.3.5.0, and bugs might have been fixed in the meantime.
I am trying to capture a part of my screen.
The problem is even if I use png to save the image the quality still worse than if I would just use normal print screen.
Here is the code I use:
//display a save file dialog for the user to set the file name
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.Filter = "PNG (*.png)|*.png";
saveFileDialog.FilterIndex = 0;
saveFileDialog.RestoreDirectory = true;
//if the user proceed saving the picture
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
//simplify code with constant numbers for demo
//get the width of the panel we need the screenshoot off
int x = 10;
//get the height of the panel we need the screenshoot off
int y = 10;
//create the ractangle of the screenshoot panel
Rectangle rect = new Rectangle(x, y, 5, 5);
//create new bitmap
Bitmap bmp = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(bmp);
//get the screenshoot of the panel
g.CopyFromScreen(rect.Left, rect.Top, 0, 0, bmp.Size, CopyPixelOperation.SourceCopy);
string fileName = saveFileDialog.FileName;
if (!fileName.Contains(".png"))
fileName += ".png";
bmp.Save(fileName, ImageFormat.Png);
}
EDIT:
Example image form what I take with code:
Normal screenshot:
It does not look so different here, but it is worst.
The top image in your question was rescaled, smaller than the original. This is noticeable in images that contain fine detail, like the ClearType anti-aliasing pixels used to make the text more readable. When they get rescaled, the visual effect is ruined and text looks a lot worse.
It is entirely unclear why the image was rescaled, nothing in your code could cause that. Double-check by using the debugger to inspect the bmp.HorizontalResolution property, it should match the DPI of your video adapter. Simplest explanation that it was done by whatever image viewing program you used, perhaps to make the image fit the window. Try zooming out.
If it's possible to use a external library I suggest you FMUtils.Screenshot. Its available as a NuGet-package.
I just tried it and the quality is like the standard screenshot from windows. Here's a shortexample:
new ComposedScreenshot(new Rectangle(0, 0, 100, 100)).ComposedScreenshotImage.Save(#"PATH_TO_FILE\example-screenshot.png", ImageFormat.Png);
Hope this helps!
The pixel format you use only uses 8 bits each for the different color channels. You could try using PixelFormat64bppARGB to get 16 bits per color.
Resource on the PixelFormat enumeration: http://msdn.microsoft.com/en-us/library/system.drawing.imaging.pixelformat%28v=vs.110%29.aspx
I'm using the Cairo bindings for C#, and I wanted to be able to crop an ImageSurface and put it into a new ImageSurface variable, which I will then use in a seperate subroutine. The question is how would I do this properly.
Here's my code as it stands:
ImageSurface OutputImage = new ImageSurface (Format.Rgb24, (int)RectangleToCropTo.Width, (int)RectangleToCropTo.Height);
using (Cairo.Context cr = new Cairo.Context(OutputImage)) {
cr.SetSource (originalImage);
cr.Rectangle (RectangleToCropTo);
cr.Clip ();
cr.Paint ();
}
As it stands, it does actually crop the image down, and it appears to start at the correct point - but the OutputImage is offset in the x and y axis by the amount of pixels from 0,0 that the top left of the selection is. The area that the image doesn't populate is transparent.
I also tried the following:
ImageSurface OutputImage = new ImageSurface (Format.Rgb24, (int)RectangleToCropTo.Width, (int)RectangleToCropTo.Height);
using (Cairo.Context cr = new Cairo.Context(OutputImage)) {
cr.SetSource (originalImage, RectangleToCropTo.X, RectangleToCropTo.Y);
cr.Rectangle (RectangleToCropTo);
cr.Clip ();
cr.Paint ();
}
This additional two parameters supposedly mark from which point the 'source' should be stored (from my understanding, '40, 40' would mean that 'painting' the image would result in the image from 40, 40 and whatever is to the right of and below it).
However, this neither provides me with a cropped image, but instead includes the troublesome offset and starts drawing from the top left of the image.
I also figured that maybe this would be the solution:
ImageSurface OutputImage = new ImageSurface (Format.Rgb24, (int)RectangleToCropTo.Width, (int)RectangleToCropTo.Height);
using (Cairo.Context cr = new Cairo.Context(OutputImage)) {
cr.SetSource (originalImage, RectangleToCropTo.X, RectangleToCropTo.Y);
cr.Clip ();
cr.Paint ();
}
But to no avail, this simply produces identical results to the previous code chunk.
If any of you could tell me what I'm doing wrong (and it's probably the dumbest of mistakes), I'd appreciate it.
I'm use the Cairo-Sharp that comes with Gtk3.
Thanks :)
You almost got it. Try this:
ImageSurface OutputImage = new ImageSurface (Format.Rgb24, (int)RectangleToCropTo.Width, (int)RectangleToCropTo.Height);
using (Cairo.Context cr = new Cairo.Context(OutputImage)) {
cr.SetSource (originalImage, -RectangleToCropTo.X, -RectangleToCropTo.Y);
cr.Paint ();
}
The important difference is the negative arguments to SetSource. This places the source image so that the (x, y) pixel from the source falls onto the (0, 0) pixel on the target.
Since you target covers all the pixels needed, your rectangle() and clip() calls aren't needed anymore.
clip does not resize the surface, it just masks out anything fur future drawing operations.
Create a new surface of proper size and copy the content of the desired (clipped or not) region.
What is the best way to rotate a image in asp.net
I did use matrix.rotateAt but i can't get it to work so please tell me what is the best way?
I should write out that hate to rotate a image with the image object.
Image myImage = Image.FromFile("myimage.png");
myImage.RotateFlip(RotateFlipType.Rotate180FlipNone);
http://msdn.microsoft.com/en-us/library/system.drawing.image.rotateflip.aspx
Here is some sample code (not written by me - found some time ago here ) that worked for me, as long as you edit some details.
private Bitmap rotateImage(Bitmap b, float angle)
{
//create a new empty bitmap to hold rotated image
Bitmap returnBitmap = new Bitmap(b.Width, b.Height);
//make a graphics object from the empty bitmap
using (Graphics g = Graphics.FromImage(returnBitmap))
{
//move rotation point to center of image
g.TranslateTransform((float)b.Width / 2, (float)b.Height / 2);
//rotate
g.RotateTransform(angle);
//move image back
g.TranslateTransform(-(float)b.Width / 2, -(float)b.Height / 2);
//draw passed in image onto graphics object
g.DrawImage(b, new Point(0, 0));
}
return returnBitmap;
}
Please note, that this may not work "out of the box" - there are some issues with the new bitmap. When you rotate it, it may not fit comfortably in the rectangle of the old bitmap (rectangle bounds b.Width, B.Height).
Anyway this is just to give you an idea. If you choose to do it this way, I'm sure you will be able to work out all the details. I'd post my final code, however I don't have it on me right now...
I would suggest this is the best way
// get the full path of image url
string path = Server.MapPath(Image1.ImageUrl) ;
// creating image from the image url
System.Drawing.Image i = System.Drawing.Image.FromFile(path);
// rotate Image 90' Degree
i.RotateFlip(RotateFlipType.Rotate90FlipXY);
// save it to its actual path
i.Save(path);
// release Image File
i.Dispose();
// Set Image Control Attribute property to new image(but its old path)
Image1.Attributes.Add("ImageUrl", path);
for more