I have some task - resize image if height or width >500px.
I try this code.
But when I choosed image I have error like
NewImage.Save(path);
В GDI+ error of the general form.
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog fdlg = new OpenFileDialog();
fdlg.Multiselect = true;
if (fdlg.ShowDialog() == DialogResult.OK)
{
for (int i = 0; i < fdlg.FileNames.Length; i++)
{
string file = fdlg.FileNames[i];
string path = System.IO.Path.GetFullPath(file);
System.Drawing.Image img = System.Drawing.Image.FromFile(path);
if (img.Width > 500 || img.Height > 500)
{
int currW = img.Width;
int currH = img.Height;
int realWPer = 500 * 100 / currW;
int realHPer = 500 * 100 / currH;
int realW = currW / 100 * realWPer; // new width
int realH = currH / 100 * realHPer; // new height
Image NewImage = resizeImage(img, new Size(realW, realH));
NewImage.Save(path);
}
}
}
}
public static Image resizeImage(Image imgToResize, Size size)
{
return (Image)(new Bitmap(imgToResize, size));
}
You haven't posted the error message so one can only guess what may be wrong, I'd guess you get an error that you are trying to access a locked file.
You are trying to save the new image over the old image which is still open. You never close/dispose the img so it's still open when you try to save the new image using the same path as the old
Related
I am trying to generate a gif using Bumpkit gif encoder and while the gif works (Except for the first frames acting out), when I try to load the gif in photoshop, it says "Could not complete request because the file-format module cannot parse the file".
I don't know how to check the validity of the gif because it works when I view it. This is how Im using the Bumpkit library:
public void SaveImagesAsGif(Stream stream, ICollection<Bitmap> images, float fps, bool loop)
{
if (images == null || images.ToArray().Length == 0)
{
throw new ArgumentException("There are no images to add to animation");
}
int loopCount = 0;
if (!loop)
{
loopCount = 1;
}
using (var encoder = new BumpKit.GifEncoder(stream, null, null, loopCount))
{
foreach (Bitmap bitmap in images)
{
encoder.AddFrame(bitmap, 0, 0, TimeSpan.FromSeconds(1 / fps));
}
}
stream.Position = 0;
}
Am I doing something wrong when generating the gif?
When you are using the Bumpkit gif encoder library, I think you have to call the InitHeader function first.
Take from the GifEncoder.cs source:
private void InitHeader(Stream sourceGif, int w, int h)
You can see the source code for the InitHeader function, the AddFrame function and the rest of the GifEncoder.cs file at https://github.com/DataDink/Bumpkit/blob/master/BumpKit/BumpKit/GifEncoder.cs
So it's a small edit to your code:
public void SaveImagesAsGif(Stream stream, ICollection<Bitmap> images, float fps, bool loop)
{
if (images == null || images.ToArray().Length == 0)
{
throw new ArgumentException("There are no images to add to animation");
}
int loopCount = 0;
if (!loop)
{
loopCount = 1;
}
using (var encoder = new BumpKit.GifEncoder(stream, null, null, loopCount))
{
//calling initheader function
//TODO: Change YOURGIFWIDTHHERE and YOURGIFHEIGHTHERE to desired width and height for gif
encoder.InitHeader(stream, YOURGIFWIDTHHERE, YOURGIFHEIGHTHERE);
foreach (Bitmap bitmap in images)
{
encoder.AddFrame(bitmap, 0, 0, TimeSpan.FromSeconds(1 / fps));
}
}
stream.Position = 0;
}
I am attempting to capture a full-page screenshot of any website a user is viewing using the WebBrowser component.
At present, I am able to only able to capture what a user is viewing from within the WebBrowser. However, the screenshot image created is the size of the webpage. For example, below is a (half-sized) screenshot of the BBC website, the black area is actually saved transparent but I've filled it black for visibility.
I have seen solutions where a new WebBrowser instance is used to fetch a fullpage snapshot. However, I need the screenshot to be exactly of the page as the user is viewing it at the time, much like how the full-page screenshot works in Firefox.
My code below that generated the above image:
private void button1_Click(object sender, EventArgs e)
{
while (webBrowser1.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
}
int scrollWidth = 0;
int scrollHeight = 0;
scrollHeight = webBrowser1.Document.Body.ScrollRectangle.Height;
scrollWidth = webBrowser1.Document.Body.ScrollRectangle.Width;
webBrowser1.Size = new Size(scrollWidth, scrollHeight);
Bitmap bm = new Bitmap(scrollWidth, scrollHeight);
webBrowser1.DrawToBitmap(bm, new Rectangle(0, 0, bm.Width, bm.Height));
bm.Save(#"D:\Screenshots\test.png", ImageFormat.Png);
}
I've got a good working one..
private void button1_Click(object sender, EventArgs e)
{
using (FileDialog fd = new SaveFileDialog())
{
fd.Filter = "Image (*.png)|*.png";
if (fd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
new WebPageSnap(webBrowser1.Url.ToString(), fd.FileName);
//might take 3 or 4 seconds to save cauz it has to load again.
}
}
}
class WebPageSnap
{
WebBrowser wb;
string outFile;
public WebPageSnap(string url, string outputFile)
{
wb = new WebBrowser();
wb.ProgressChanged += wb_ProgressChanged;
outFile = outputFile;
wb.ScriptErrorsSuppressed = true;
wb.ScrollBarsEnabled = false;
wb.Navigate(url);
}
void wb_ProgressChanged(object sender, WebBrowserProgressChangedEventArgs e)
{
if (e.CurrentProgress == e.MaximumProgress)
{
wb.ProgressChanged -= wb_ProgressChanged;
try
{
int scrollWidth = 0;
int scrollHeight = 0;
scrollHeight = wb.Document.Body.ScrollRectangle.Height;
scrollWidth = wb.Document.Body.ScrollRectangle.Width;
wb.Size = new Size(scrollWidth, scrollHeight);
Bitmap bitmap = new Bitmap(wb.Width, wb.Height);
for (int Xcount = 0; Xcount < bitmap.Width; Xcount++)
for (int Ycount = 0; Ycount < bitmap.Height; Ycount++)
bitmap.SetPixel(Xcount, Ycount, Color.Black);
wb.DrawToBitmap(bitmap, new Rectangle(0, 0, wb.Width, wb.Height));
bitmap.Save(outFile, ImageFormat.Png);
}
catch { }
}
}
}
.
;Here's the result
.
Below is the offending code. The Stream is coming from a HttpPostedFile. Tested in local is fine.
Tested online also fine for the first time when overwriting. The exception is only thrown when you try to overwrite the file multiple times. Eg. Upload then Re-upload Any insights?
public void ResizeFromStream(string ImageSavePath, int MaxSideSize, Stream Buffer)
{
int intNewWidth;
int intNewHeight;
System.Drawing.Image imgInput = System.Drawing.Image.FromStream(Buffer);
//Determine image format
ImageFormat fmtImageFormat = imgInput.RawFormat;
//get image original width and height
int intOldWidth = imgInput.Width;
int intOldHeight = imgInput.Height;
//determine if landscape or portrait
int intMaxSide;
if (intOldWidth >= intOldHeight)
{
intMaxSide = intOldWidth;
}
else
{
intMaxSide = intOldHeight;
}
Bitmap bmpResized = null;
if (intMaxSide > MaxSideSize)
{
//set new width and height
double dblCoef = MaxSideSize / (double)intMaxSide;
intNewWidth = Convert.ToInt32(dblCoef * intOldWidth);
intNewHeight = Convert.ToInt32(dblCoef * intOldHeight);
bmpResized = new Bitmap(imgInput, intNewWidth, intNewHeight);
}
else
{
intNewWidth = intOldWidth;
intNewHeight = intOldHeight;
bmpResized = new Bitmap(Buffer);
}
//save bitmap to disk
bmpResized.Save(ImageSavePath, fmtImageFormat);
//release used resources
imgInput.Dispose();
bmpResized.Dispose();
Buffer.Dispose();
}
I am trying to port my app in windows phone . i have to upload an image on server So it is in small Size For uploading i have done this thing in Widows Successfully but problem is when i failed in it .. here is my code for windows App
public void CompressImage(int i, int j)
{
bmp1.SetPixel(j, i, Color.FromArgb(bmp.GetPixel(j, i).R, bmp.GetPixel(j, i).G, bmp.GetPixel(j, i).B));
}
private void bLoadImage_Click(object sender, EventArgs e)
{
OpenFileDialog file = new OpenFileDialog();
if (file.ShowDialog() == DialogResult.OK)
{
pictureBox1.Image = new Bitmap(file.FileName);
}
}
private void bCompression_Click(object sender, EventArgs e)
{
bmp = new Bitmap(pictureBox1.Image);
bmp1 = new Bitmap(bmp.Width, bmp.Height);
for (int i = 1; i < bmp.Height; i++)
for (int j = 1; j < bmp.Width; j++)
{
CompressImage(i, j);
}
pictureBox2.Image = bmp1;
bmp1.Save("Picture.jpeg", System.Drawing.Imaging.ImageFormat.Jpeg);
}
After Searching on google i found out that windows Phone does not support Bitmap .. any idea how i can do the same thing in windows phone or any other alternative for doing this
You should use WriteablBitmap to reduce size of image. WriteablBitmap has number of methods for images in windows phone Here is more about writeablebitmapex.
Try to load your original image to WriteableBitmap object, then you can use SaveJpeg() extension method from System.Windows.Media.Imaging namespace, to save new image with reduced size. For example :
.......
WriteableBitmap wb = new WriteableBitmap(bitmapImageObject);
wb.SaveJpeg(stream, 120, 160, 0, 100);
.......
When you are taking picture you can choose the resolution with which the picture will be taken. This can be done by
PhotoCamera cam;
After camera initizalition.
Following code when image is capturing (in the method that captures the image)
IEnumerable<Size> resList = cam.AvailableResolutions;
Size res;
if (resList.Count() > 0)
{
res = resList.ElementAt<Size>(0);
cam.Resolution = res;
}
This sample chooses the first resolution
You can try this. It worked for me. It reduced my 9.70MB file into 270KB.
WriteableBitmap cameraCapturedImage = PictureDecoder.DecodeJpeg(e.ChosenPhoto, 1024, 1024);
using (IsolatedStorageFileStream myFileStream = myStore.CreateFile(fileName))
{
System.Windows.Media.Imaging.Extensions.SaveJpeg(cameraCapturedImage, myFileStream, cameraCapturedImage.PixelWidth, cameraCapturedImage.PixelHeight, 0, 85);
myFileStream.Close();
}
N.B: fileName is the name of file to save size reduced image.
I've got an image upload page that works just fine when I only upload the files.
I added a 'Create Thumbnail' function. It looks like the file system has a handle on the images when the thumbnail process starts.
I get the 'unspecified GDI+ error' only when the image is over about 250K. When the files are below 250K, thumbnails are created as expected.
What are my options? Is there an elegant solution here? I want something not hacky.
Also, I am using HttpFileCollection so we can upload multiple images at one time. I've tried to use .Dispose on the Thumbnail creation, but it fails before we get to this point.
public void Upload_Click(object Sender, EventArgs e)
{
string directory = Server.MapPath(#"~\images\");
HttpFileCollection hfc = Request.Files;
for (int i = 0; i < hfc.Count; i++)
{
HttpPostedFile hpf = hfc[i];
if (hpf.ContentLength > 0)
{
string fileName = hpf.FileName;
fileName = fileName.Replace(" ", "");
hpf.SaveAs(fileName);
createThumbnail(fileName);
}
}
}
private void createThumbnail(string filename)
{
Image image = Image.FromFile(filename);
Image thumb = image.GetThumbnailImage(100,100, () => false, IntPtr.Zero);
thumb.Save(filename);
image.Dispose();
thumb.Dispose();
}
Please let me know if this works any better:
public string ImageDirectory { get { return Server.MapPath(#"~\images\"); } }
public void OnUploadClick(object sender, EventArgs e)
{
var files = HttpContext.Request.Files.AllKeys.AsEnumerable()
.Select(k =>HttpContext.Request.Files[k]);
foreach(var file in files)
{
if(file.ContentLength <= 0)
continue;
string savePath = GetFullSavePath(file);
var dimensions = new Size(100, 100);
CreateThumbnail(file,savePath,dimensions);
}
}
private void CreateThumbnail(HttpPostedFile file,string savePath, Size dimensions)
{
using (var image = Image.FromStream(file.InputStream))
{
using (var thumb = image.GetThumbnailImage(dimensions.Width, dimensions.Height, () => false, IntPtr.Zero))
{
thumb.Save(savePath);
}
}
}
private string GetFullSavePath(HttpPostedFile file)
{
string fileName = System.IO.Path.GetFileName(file.FileName).Replace(" ", "");
string savePath = System.IO.Path.Combine(this.ImageDirectory, fileName);
return savePath;
}
Edit -
The foreach should have followed more to this pattern:
var files = HttpContext.Request.Files.AllKeys.AsEnumerable()
.Select(k =>HttpContext.Request.Files[k]);
foreach(var file in files)
{
}
You can try this code to create your thumbnails.
MemoryStream ms = new MemoryStream(File.ReadAllBytes(path));
Bitmap originalBMP = new Bitmap(ms);
int maxWidth = 200;
int maxHeight = 200;
// Calculate the new image dimensions
int origWidth = originalBMP.Width;
int origHeight = originalBMP.Height;
double sngRatio = Convert.ToDouble(origWidth) / Convert.ToDouble(origHeight);
// New dimensions
int newWidth = 0;
int newHeight = 0;
try
{
// max 200 by 200
if ((origWidth <= maxWidth && origHeight <= maxHeight) || origWidth <= maxWidth)
{
newWidth = origWidth;
newHeight = origHeight;
}
else
{
// Width longer (shrink width)
newWidth = 200;
newHeight = Convert.ToInt32(Convert.ToDouble(newWidth) / sngRatio);
}
// Create a new bitmap which will hold the previous resized bitmap
Bitmap newBMP = new Bitmap(originalBMP, newWidth, newHeight);
// Create a graphic based on the new bitmap
Graphics oGraphics = Graphics.FromImage(newBMP);
// Set the properties for the new graphic file
oGraphics.SmoothingMode = SmoothingMode.AntiAlias;
oGraphics.InterpolationMode = InterpolationMode.High;
// Draw the new graphic based on the resized bitmap
oGraphics.CompositingQuality = CompositingQuality.HighSpeed;
oGraphics.DrawImage(originalBMP, 0, 0, newWidth, newHeight);
// Save the new graphic file to the server
EncoderParameters p = new EncoderParameters(1);
p.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, 70); // Percent Compression
MemoryStream savedBmp = new MemoryStream();
newBMP.Save(savedBmp, ImageCodecInfo.GetImageEncoders()[1], p);
// Once finished with the bitmap objects, we deallocate them.
originalBMP.Dispose();
newBMP.Dispose();
oGraphics.Dispose();
savedBmp.Dispose();
Certainly a bit more work but it does give you greater control.