I'm trying to upload an image with an ASP fileupload control but crop it into a square from the middle. this is my code,
public void CropImage(string imagePath)
{
//string imagePath = #"C:\Users\Admin\Desktop\test.jpg";
Bitmap croppedImage;
int x, y;
// Here we capture the resource - image file.
using (var originalImage = new Bitmap(imagePath))
{
if (originalImage.Width > originalImage.Height) {
x = 0;
y = (originalImage.Width / 2) - (originalImage.Height / 2);
}
else if (originalImage.Width < originalImage.Height)
{
y = 0;
x = (originalImage.Height / 2) - (originalImage.Width / 2);
}
else {
y=x=0;
}
int sqrWidth = (originalImage.Width >= originalImage.Height) ? originalImage.Height : originalImage.Width;
Rectangle crop = new Rectangle(x, y, sqrWidth, sqrWidth);
// Here we capture another resource.
croppedImage = originalImage.Clone(crop, originalImage.PixelFormat);
} // Here we release the original resource - bitmap in memory and file on disk.
// At this point the file on disk already free - you can record to the same path.
croppedImage.Save(imagePath, ImageFormat.Jpeg);
// It is desirable release this resource too.
croppedImage.Dispose();
}
//Updates an agent in the database.
protected void BtnUpdate_Click(object sender, EventArgs e)
{
AgentController agentController = new AgentController();
AgentContactController agentContactController = new AgentContactController();
CityController cityController = new CityController();
DistrictController districtController = new DistrictController();
ProvinceController provinceController = new ProvinceController();
CountryController countryController = new CountryController();
InsurancePortalContext context = new InsurancePortalContext();
string folderPath = Server.MapPath("~/AdvisersImages/");
//Check whether Directory (Folder) exists.
if (!Directory.Exists(folderPath))
{
//If Directory (Folder) does not exists. Create it.
Directory.CreateDirectory(folderPath);
}
//Save the File to the Directory (Folder).
string FilePath = folderPath + Path.GetFileName(ImageUploadUpdate.PostedFile.FileName);
if (!File.Exists(FilePath))
{
ImageUploadUpdate.SaveAs(FilePath);
CropImage(FilePath);
}
but I'm getting the out of memory exception at,
croppedImage = originalImage.Clone(crop, originalImage.PixelFormat);
If I don't use the x,y value setting conditional block in CropImage function and/or only save the uploaded image as is, this exception doesn't come.
thanks in advance
As I mentioned in the comments. .Clone() throw an OutOfMemoryException if your crop rect is out of the image's bounds. You can read it up right here:
https://msdn.microsoft.com/de-de/library/ms141944(v=vs.110).aspx
Consider your code with the input image that has the following size:
width: 5px
height: 10px
This is your code.
if(originalImage.Width > originalImage.Height)
{
x = 0;
y = (originalImage.Width / 2) - (originalImage.Height / 2);
}
else if(originalImage.Width < originalImage.Height)
{
y = 0;
x = (originalImage.Height / 2) - (originalImage.Width / 2);
}
else
{
y = x = 0;
}
int sqrWidth = (originalImage.Width >= originalImage.Height) ? originalImage.Height : originalImage.Width;
Rectangle crop = new Rectangle(x, y, sqrWidth, sqrWidth);
The 5x10 image would fall into the else if case.
There y gets set to 0 and x gets set to ((10 / 2) = 5) - (5 / 2) = 2) = 3.
Then sqrWidth gets set to 10.
Next you try to clone the following rect:
x = 3, y = 0, w = 10, h = 10
And voila your rectangle is out of the image's bounds. You need to fix your cropping logic.
Related
I have Bitmap Images that are usually smaller than 500x500 pixels.
But sometimes one or both dimensions can exceed 500 pixels.
If the height is >500 I want to crop the image at the bottom and if the width is >500 I want to crop it on both sides equally.
If the Image is <500 in any dimension I want to pad it with white pixels on each side equally to make it 500x500.
I'm not familliar with .NET but I understand there's a lot that'S already been done for you (I'm a C++ developer).
I appreciate any help! Thanks!
This is what I have so far, which puts the image in the center of a white 500x500 rectangular image. It's just that I cant wrap my head around the cases where one dimension of the original image exceeds 500 pixels. (See the two lines with ??)
public static System.Drawing.Bitmap PadImage(System.Drawing.Bitmap originalImage)
{
if (originalImage.Height > 500)
??
if (originalImage.Width > 500)
??
Size squareSize = new Size(500, 500);
System.Drawing.Bitmap squareImage = new System.Drawing.Bitmap(squareSize.Width, squareSize.Height);
using (Graphics graphics = Graphics.FromImage(squareImage))
{
graphics.FillRectangle(System.Drawing.Brushes.White, 0, 0, squareSize.Width, squareSize.Height);
graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
graphics.DrawImage(originalImage, (squareSize.Width / 2) - (originalImage.Width / 2), (squareSize.Height / 2) - (originalImage.Height / 2), originalImage.Width, originalImage.Height);
}
return squareImage;
}
Bitmap PadCropImage(Bitmap original)
{
if (original.Width == 500 && original.Height == 500)
return original;
if (original.Width > 500 && original.Height > 500)
{
int x = (original.Width - 500) / 2;
int y = (original.Height - 500) / 2;
return original.Clone(new Rectangle(x, y, 500, 500), original.PixelFormat);
}
Bitmap square = new Bitmap(500, 500);
var g = Graphics.FromImage(square);
if (original.Width > 500)
{
int x = (original.Width - 500) / 2;
int y = (500 - original.Height) / 2;
g.DrawImageUnscaled(original, -x, y);
}
else if (original.Height > 500)
{
int x = (500 - original.Width) / 2;
int y = (original.Height - 500) / 2;
g.DrawImageUnscaled(original, x, -y);
}
else
{
int x = (500 - original.Width) / 2;
int y = (500 - original.Height) / 2;
g.DrawImageUnscaled(original, x, y);
}
return square;
}
Here is an old method I have used many times
public static Image ThumbnailImage(Image sourceImage, int imageSize, bool maintainAspectRatio, bool maintainImageSize, Color backgroundColor)
{
try
{
int thumbnailWidth = imageSize;
int thumbnailHeight = imageSize;
if (maintainAspectRatio)
{
float aspectRatio = (float) sourceImage.Width/sourceImage.Height;
float targetAspectRatio = (float) thumbnailWidth/thumbnailHeight;
if (aspectRatio < targetAspectRatio)
{
thumbnailWidth = (int) (thumbnailHeight*aspectRatio);
}
else if (aspectRatio > targetAspectRatio)
{
thumbnailHeight = (int) (thumbnailWidth/aspectRatio);
}
}
Image thumbnail = sourceImage.GetThumbnailImage(thumbnailWidth, thumbnailHeight, null, new IntPtr());
if (maintainImageSize)
{
var offset = new Point(0, 0);
if (thumbnailWidth != imageSize)
{
offset.X = ((imageSize - thumbnailWidth)/2);
}
if (thumbnailHeight != imageSize)
{
offset.Y = ((imageSize - thumbnailHeight)/2);
}
var bmpImage = new Bitmap(imageSize, imageSize, PixelFormat.Format32bppArgb);
using (Graphics graphics = Graphics.FromImage(bmpImage))
{
graphics.Clear(backgroundColor);
graphics.DrawImage(thumbnail, new Rectangle(offset.X, offset.Y, thumbnailWidth, thumbnailHeight), new Rectangle(0, 0, thumbnailWidth, thumbnailHeight), GraphicsUnit.Pixel);
}
thumbnail.Dispose();
return Image.FromHbitmap(bmpImage.GetHbitmap());
}
return thumbnail;
}
catch (Exception exception)
{
const string strExMsg = "Error Creating Thumbnail";
throw new Exception(Assembly.GetExecutingAssembly().GetName().Name + " - " + strExMsg + " Msg : " + exception.Message);
}
}
how to rotate image through put in angle value in textbox using graphics in asp.net c#?
I take a textbox and image and button.I want to give value in angle in textbox and image will be rotate according to given value.so,i can only doing a simple button_click event ,but it is not proper for textbox.so,give simple code ...
protected void Button2_Click(object sender, EventArgs e)
{
string path = Server.MapPath(Image1.ImageUrl);
////create an image object from the image in that path
System.Drawing.Image img = System.Drawing.Image.FromFile(path);
////rotate the image
img.RotateFlip(RotateFlipType.Rotate90FlipXY);
////save the image out to the file
img.Save(path);
////release image file
img.Dispose();
}
Following code save the rotated image into newfile.png in current project folder path
Try This:
protected void Button2_Click1(object sender, EventArgs e)
{
string path = Server.MapPath(Image1.ImageUrl);
string newpath =Server.MapPath(#"~/filename.png");
////create an image object from the image in that path
System.Drawing.Bitmap img =new System.Drawing.Bitmap(path);
Bitmap map = RotateBitmap(COnvert.ToSingle(textBox1.Text), img);
map.Save(newpath);
////release image file
img.Dispose();
}
public Bitmap RotateBitmap(float Angle, Bitmap bm_in)
{
try
{
float wid = bm_in.Width;
float hgt = bm_in.Height;
Point[] corners = { new Point(0, 0), new Point(int.Parse(wid.ToString()), 0), new Point(0, int.Parse(hgt.ToString())), new Point(int.Parse(wid.ToString()), int.Parse(hgt.ToString())) };
int cx = int.Parse(wid.ToString()) / 2;
int cy = int.Parse(hgt.ToString()) / 2;
long i;
for (i = 0; i <= 3; i++)
{
corners[i].X -= Convert.ToInt32(cx.ToString());
corners[i].Y -= Convert.ToInt32(cy.ToString());
}
float theta = (float)(Angle * Math.PI / 180.0);
float sin_theta = (float)Math.Sin(theta);
float cos_theta = (float)Math.Cos(theta);
float X;
float Y;
for (i = 0; i <= 3; i++)
{
X = corners[i].X;
Y = corners[i].Y;
corners[i].X = (int)(X * cos_theta + Y * sin_theta);
corners[i].Y = (int)(-X * sin_theta + Y * cos_theta);
}
float xmin = corners[0].X;
float ymin = corners[0].Y;
for (i = 1; i <= 3; i++)
{
if (xmin > corners[i].X)
xmin = corners[i].X;
if (ymin > corners[i].Y)
ymin = corners[i].Y;
}
for (i = 0; i <= 3; i++)
{
corners[i].X -= int.Parse(xmin.ToString());
corners[i].Y -= int.Parse(ymin.ToString());
}
Bitmap bm_out = new Bitmap((int)(-2 * xmin), (int)(-2 * ymin));
Graphics gr_out = Graphics.FromImage(bm_out);
// ERROR: Not supported in C#: ReDimStatement
Point[] temp = new Point[3];
if (corners != null)
{
Array.Copy(corners, temp, Math.Min(corners.Length, temp.Length));
}
corners = temp;
gr_out.DrawImage(bm_in, corners);
return bm_out;
}
catch (Exception ex)
{
string s = ex.Message;
return bm_in;
}
}
I have large 500MB size image I want to show this image like map with zoom and pan features in ASP.net. I found OpenLayers for this but anyone can share any working example using any framework/library to achieve this functionality in ASP.net
i found one answer which i like to share with you. here is the code
private static void Split(string fileName, int width, int height)
{
using (Bitmap source = new Bitmap(fileName))
{
bool perfectWidth = source.Width % width == 0;
bool perfectHeight = source.Height % height == 0;
int lastWidth = width;
if (!perfectWidth)
{
lastWidth = source.Width - ((source.Width / width) * width);
}
int lastHeight = height;
if (!perfectHeight)
{
lastHeight = source.Height - ((source.Height / height) * height);
}
int widthPartsCount = source.Width / width + (perfectWidth ? 0 : 1);
int heightPartsCount = source.Height / height + (perfectHeight ? 0 : 1);
for (int i = 0; i < widthPartsCount; i++)
for (int j = 0; j < heightPartsCount; j++)
{
int tileWidth = i == widthPartsCount - 1 ? lastWidth : width;
int tileHeight = j == heightPartsCount - 1 ? lastHeight : height;
using (Bitmap tile = new Bitmap(tileWidth, tileHeight))
{
using (Graphics g = Graphics.FromImage(tile))
{
g.DrawImage(source, new Rectangle(0, 0, tile.Width, tile.Height), new Rectangle(i * width, j * height, tile.Width, tile.Height), GraphicsUnit.Pixel);
}
tile.Save(string.Format("{0}-{1}.png", i + 1, j + 1), ImageFormat.Png);
}
}
}
}
I would advise to make some smaller images(Mipmapping http://en.wikipedia.org/wiki/Mipmap ) or/and cut them in smaller parts. (Slice up an image into tiles)
Think about, you can't see all the pixels of 500mb data. Only transfer what you actually see.
The image produced by the color and depth sensor on the Kinect are slightly out of alignment. How can I transform them to make them line up?
The key to this is the call to 'Runtime.NuiCamera.GetColorPixelCoordinatesFromDepthPixel'
Here is an extension method for the Runtime class. It returns a WriteableBitmap object. This WriteableBitmap is automatically updated as new frames come in. So the usage of it is really simple:
kinect = new Runtime();
kinect.Initialize(RuntimeOptions.UseColor | RuntimeOptions.UseSkeletalTracking | RuntimeOptions.UseDepthAndPlayerIndex);
kinect.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution320x240, ImageType.DepthAndPlayerIndex);
kinect.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480, ImageType.Color);
myImageControl.Source = kinect.CreateLivePlayerRenderer();
and here's the code itself:
public static class RuntimeExtensions
{
public static WriteableBitmap CreateLivePlayerRenderer(this Runtime runtime)
{
if (runtime.DepthStream.Width == 0)
throw new InvalidOperationException("Either open the depth stream before calling this method or use the overload which takes in the resolution that the depth stream will later be opened with.");
return runtime.CreateLivePlayerRenderer(runtime.DepthStream.Width, runtime.DepthStream.Height);
}
public static WriteableBitmap CreateLivePlayerRenderer(this Runtime runtime, int depthWidth, int depthHeight)
{
PlanarImage depthImage = new PlanarImage();
WriteableBitmap target = new WriteableBitmap(depthWidth, depthHeight, 96, 96, PixelFormats.Bgra32, null);
var depthRect = new System.Windows.Int32Rect(0, 0, depthWidth, depthHeight);
runtime.DepthFrameReady += (s, e) =>
{
depthImage = e.ImageFrame.Image;
Debug.Assert(depthImage.Height == depthHeight && depthImage.Width == depthWidth);
};
runtime.VideoFrameReady += (s, e) =>
{
// don't do anything if we don't yet have a depth image
if (depthImage.Bits == null) return;
byte[] color = e.ImageFrame.Image.Bits;
byte[] output = new byte[depthWidth * depthHeight * 4];
// loop over each pixel in the depth image
int outputIndex = 0;
for (int depthY = 0, depthIndex = 0; depthY < depthHeight; depthY++)
{
for (int depthX = 0; depthX < depthWidth; depthX++, depthIndex += 2)
{
// combine the 2 bytes of depth data representing this pixel
short depthValue = (short)(depthImage.Bits[depthIndex] | (depthImage.Bits[depthIndex + 1] << 8));
// extract the id of a tracked player from the first bit of depth data for this pixel
int player = depthImage.Bits[depthIndex] & 7;
// find a pixel in the color image which matches this coordinate from the depth image
int colorX, colorY;
runtime.NuiCamera.GetColorPixelCoordinatesFromDepthPixel(
e.ImageFrame.Resolution,
e.ImageFrame.ViewArea,
depthX, depthY, // depth coordinate
depthValue, // depth value
out colorX, out colorY); // color coordinate
// ensure that the calculated color location is within the bounds of the image
colorX = Math.Max(0, Math.Min(colorX, e.ImageFrame.Image.Width - 1));
colorY = Math.Max(0, Math.Min(colorY, e.ImageFrame.Image.Height - 1));
output[outputIndex++] = color[(4 * (colorX + (colorY * e.ImageFrame.Image.Width))) + 0];
output[outputIndex++] = color[(4 * (colorX + (colorY * e.ImageFrame.Image.Width))) + 1];
output[outputIndex++] = color[(4 * (colorX + (colorY * e.ImageFrame.Image.Width))) + 2];
output[outputIndex++] = player > 0 ? (byte)255 : (byte)0;
}
}
target.WritePixels(depthRect, output, depthWidth * PixelFormats.Bgra32.BitsPerPixel / 8, 0);
};
return target;
}
}
One way to do this is to assume that the color and depth images have similar variations in them, and to cross-correlate the two images (or smaller versions of them).
Pre-whiten the images to get at the underlying variations.
Cross-correlate the pre-whitened images or smaller versions of them.
The peak position of the cross-correlation will tell you the offset in x and y
i am trying to create thumbnails. my path to original folder is: suppose I:\my images**, and i want to generate it to **i:\new images. i got two problem, first problem is that if my images folder contains subfolder then in the new images it should also be in the sub folder not as a parent folder .
second i got an Error.**A generic error occurred in GDI+.
3rd i get this error: Out of memory.**
its a csharp console application
at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
at System.Drawing.Image.Save(String filename, ImageFormat format)
at ConsoleApplication1.Program.CreateThumbnail(String[] b, Double wid, Double hght, Boolean Isprint)
public void CreateThumbnail(string[] b, double wid, double hght, bool Isprint)
{
string[] path;
path = new string [64];
path = b;
string saveath = "i:\\check\\a test\\";
for (int i = 0; i < b.Length; i++)
{
DirectoryInfo dir = new DirectoryInfo(path[i]);
string dir1 = dir.ToString();
dir1 = dir1.Substring(dir1.LastIndexOf("\\"));
FileInfo[] files1 = dir.GetFiles();
foreach (FileInfo f in files1)
{
string gh = f.ToString();
try
{
System.Drawing.Image myThumbnail150;
System.Drawing.Image.GetThumbnailImageAbort myCallback = new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
System.Drawing.Image imagesize = System.Drawing.Image.FromFile(f.FullName);
Bitmap bitmapNew = new Bitmap(imagesize);
double maxWidth = wid;
double maxHeight = hght;
int w = imagesize.Width;
int h = imagesize.Height;
// Longest and shortest dimension
int longestDimension = (w > h) ? w : h;
int shortestDimension = (w < h) ? w : h;
// propotionality
float factor = ((float)longestDimension) / shortestDimension;
// default width is greater than height
double newWidth = maxWidth;
double newHeight = maxWidth / factor;
// if height greater than width recalculate
if (w < h)
{
newWidth = maxHeight / factor;
newHeight = maxHeight;
}
myThumbnail150 = bitmapNew.GetThumbnailImage((int)newWidth, (int)newHeight, myCallback, IntPtr.Zero);
string ext = Path.GetExtension(f.Name);
if (!Directory.Exists(saveath + dir1))
{
Directory.CreateDirectory(saveath + dir1);
myThumbnail150.Save(saveath + dir1 + "\\" + f.Name.Replace(ext, ".Jpeg"), System.Drawing.Imaging.ImageFormat.Jpeg);
}
else if(Directory.Exists(saveath+dir1))
{
myThumbnail150.Save(saveath + dir1+" \\"+ f.Name.Replace(ext, ".Jpeg"), System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
catch (Exception ex)
{
Console.WriteLine("something went wrong" + ex.ToString());
}
}
}
}
I have just refactored a bit the code and now it works (on my machine):
private static void CreateThumbnail(string[] b, double wid, double hght, bool Isprint)
{
string saveAt = "D:\\check";
foreach (string path in b)
{
var directory = new DirectoryInfo(path);
string outputPath = Path.Combine(saveAt, directory.Name);
foreach (FileInfo f in directory.GetFiles("*.*", SearchOption.AllDirectories))
{
if (f.DirectoryName != directory.FullName)
{
outputPath = Path.Combine(saveAt, directory.Name, f.Directory.Name);
}
if (!Directory.Exists(outputPath))
{
Directory.CreateDirectory(outputPath);
}
using (Image imagesize = Image.FromFile(f.FullName))
using (Bitmap bitmapNew = new Bitmap(imagesize))
{
double maxWidth = wid;
double maxHeight = hght;
int w = imagesize.Width;
int h = imagesize.Height;
// Longest and shortest dimension
int longestDimension = (w > h) ? w : h;
int shortestDimension = (w < h) ? w : h;
// propotionality
float factor = ((float)longestDimension) / shortestDimension;
// default width is greater than height
double newWidth = maxWidth;
double newHeight = maxWidth / factor;
// if height greater than width recalculate
if (w < h)
{
newWidth = maxHeight / factor;
newHeight = maxHeight;
}
string fileName = Path.Combine(outputPath, Path.GetFileNameWithoutExtension(f.Name) + ".jpeg");
bitmapNew.GetThumbnailImage((int)newWidth, (int)newHeight, () => false, IntPtr.Zero)
.Save(fileName, System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
}
}
I have to say few things about your old code:
use foreach when possible;
avoid the first three lines, they are useless;
avoid unused variables;
keep your code as clean as possible;
About the "GDI+ generic error" and the "Out Of Memory" exceptions, you should take a look at that link on SO: What is the "best" way to create a thumbnail using ASP.NET?
You must use the C# using statement to make sure unmanaged GDI+ resources underneath the .NET surface are freed as quickly as possible to avoid out of memory errors.
The GDI+ generic can happen if the image cannot be converted for example.