Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I'm getting an out of memory exception while looping through images. It happens after about 500 images.
if I try to run the same code through a parallel loop it only makes it through about 5 images.
It usually seems to slow down before throwing the out of memory exception
Here is my code. I'm using MagickNet
public static void PreProductionProcessing(DirectoryInfo dirInfo)
{
var tw = new StreamWriter(#"C:\bar.csv", true);
tw.WriteLine("Filename, Alpha Channel Removed, Dpi Changed, Resized");
foreach (var currentFile in dirInfo.GetFiles("*.tif"))
{
var alphaChannelRemoved = false;
var resized = false;
var DpiChanged = false;
Image img = null;
MemoryStream ms = null;
try
{
img = new Image(currentFile.FullName);
if (img.Matte)
{
ms = RemoveAlphaChanell(currentFile.FullName);
img = new Image(ms);
alphaChannelRemoved = true;
}
if (img.Density.x_res < 300)
{
img.Density = new Image.Resolution(300, 300);
DpiChanged = true;
}
if (img.Size.Width != 1875)
{
var newSize = img.Size;
double resizeRatio = (double)newSize.Width / (double)1875;
newSize.Width = Convert.ToInt16(img.Size.Width / resizeRatio);
newSize.Height = Convert.ToInt16(img.Size.Height / resizeRatio);
img.Resize(newSize);
resized = true;
}
using (var filestream = new FileStream(Path.Combine(#"C:\OutFolder", currentFile.Name), FileMode.CreateNew))
{
img.Write(filestream, "tif");
}
tw.WriteLine("{0}, {1}, {2}, {3}", currentFile.Name, alphaChannelRemoved, DpiChanged, resized);
tw.Flush();
}
catch (Exception e)
{
tw.WriteLine("{0}, {1}", currentFile.Name, e.Message);
tw.Flush();
}
finally
{
if (img != null)
{
img.Dispose();
img = null;
}
if (ms != null)
ms.Dispose();
Magick.Term();
}
}
}
static MemoryStream RemoveAlphaChanell(string source)
{
Bitmap old = new Bitmap(source);
Bitmap temp = new Bitmap(old.Width, old.Height, PixelFormat.Format24bppRgb);
Graphics g = Graphics.FromImage(temp);
g.Clear(System.Drawing.Color.White);
var rect = new Rectangle(Point.Empty, new Size(old.Width, old.Height));
g.DrawImage(old, rect);
var stream = new MemoryStream();
temp.Save(stream, ImageFormat.Tiff);
stream.Seek(0, SeekOrigin.Begin);
old.Dispose();
temp.Dispose();
g.Dispose();
return stream;
}
I'm not sure if the memory leak is within MagickNet or if anyone can see anything in my code that is causing this issue.
Any suggestions will be greatly appreciated
When img.Matte is true, you replace the image in the img variable with a new image. The previous image is never disposed.
Dispose the previous image before you replace it:
if (img.Matte)
{
img.Dispose();
ms = RemoveAlphaChanell(currentFile.FullName);
img = new Image(ms);
alphaChannelRemoved = true;
}
Related
I am trying to use Aspose.Imaging version 21.7.0 to compress some .jpg and .png byte arrays.
My Winforms Click event:
private void btnConvert_Click(object sender, EventArgs e)
{
_context.Images.Load();
var images = _context.Images.Local.ToBindingList();
foreach (var image in images)
{
if (image.ImageData != null)
{
image.MimeType = MimeTypes.GetMimeType(image.Filename.Trim());
if (image.MimeType.StartsWith("image") && image.MimeType != "image/vnd.microsoft.icon")
{
byte[] newImage;
using (MemoryStream stream = new MemoryStream(image.ImageData))
{
using (RasterImage myImage = (RasterImage) Image.Load(stream))
{
switch (image.MimeType)
{
case "image/png":
PngOptions options = new PngOptions
{
CompressionLevel = 9,
ColorType = PngColorType.IndexedColor,
Progressive = true,
Palette = ColorPaletteHelper.GetCloseImagePalette(myImage, 256,
PaletteMiningMethod.Histogram)
};
using (MemoryStream memory = new MemoryStream())
{
myImage.Save(memory, options);
memory.Position = 0;
newImage = memory.ToArray();
}
break;
case "image/jpeg":
JpegOptions saveOptions = new JpegOptions
{
BitsPerChannel = 8,
CompressionType = JpegCompressionMode.Progressive,
Quality = 100,
ResolutionSettings = new ResolutionSetting(96.0, 96.0),
ResolutionUnit = ResolutionUnit.Inch,
ColorType = JpegCompressionColorMode.Cmyk,
Palette = ColorPaletteHelper.GetCloseImagePalette(myImage, 256, PaletteMiningMethod.Histogram)
};
using (MemoryStream memory = new MemoryStream())
{
Debug.WriteLine(image.Filename);
try
{
myImage.Save(memory, saveOptions); <<== Exceptions
}
catch (Exception exception)
{
Debug.WriteLine("Image Byte Array: " + image.ImageData);
}
memory.Position = 0;
newImage = memory.ToArray();
}
break;
default:
newImage = null;
break;
}
}
}
image.CompressedImageData = Compress(newImage);
}
else
{
image.CompressedImageData = null;
}
}
}
var count = _context.SaveChanges();
MessageBox.Show($#"{count} images compressed.");
}
I am getting alot of Exceptions with jpeg images. Example:
Exception thrown: ' ' in Aspose.Imaging.dll
Exception thrown: 'Aspose.Imaging.FileFormats.Dng.DngException' in Aspose.Imaging.dll
Exception thrown: ' ' in Aspose.Imaging.dll
Exception thrown: 'Aspose.Imaging.CoreExceptions.ImageSaveException' in Aspose.Imaging.dll
... all thrown from myImage.Save(memory, saveOptions) in the jpeg section.
Any help will be appreciated.
Since Aspose.Imaging is a paid product,
you should contact them at their site for support.
There is a free forum specially for Aspose products:
https://forum.aspose.com/
Everyone that have experienced with Aspose errors know that the errors are hard to understand due to their obfuscation of the code, so the best solution is to contact them directly.
I am loading an image and i get an increase of memory around 10x the size of the file.
this is the output for the code below
Loading file img_6.jpg with originally 513kb
Memory for image img_6.jpg is 63704kb (124.12x)
Thanks!
this is the code i use to load
string filename = "img_6.jpg";
Directory.SetCurrentDirectory(#"C:\Users\Admin\Desktop\isolated images");
Helpers.membefore(filename);
BitmapImage bitmap = new BitmapImage();
//using (Stream stream = new FileStream(filepath, FileMode.Open))
{
bitmap.BeginInit();
//bitmap.StreamSource = stream;
bitmap.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.UriSource = new Uri(filename, UriKind.Relative);
bitmap.EndInit();
}
ImageBrush ib = new ImageBrush() { ImageSource = bitmap };
Helpers.memafter(ib);
these are the memory log helpers
public static void memafter(object result)
{
//debugging
if (result.GetType() == typeof(ImageBrush) && (result as ImageBrush).ImageSource != null)
{
var after = Process.GetCurrentProcess().VirtualMemorySize64;
string factor = ((double)(after - before) / (double)len).ToString("N") ;
string source = (result as ImageBrush).ImageSource.ToString();
Console.WriteLine(String.Format("Memory for image {0} is {1}kb ({2}x)",
source,
(after - before) / 1024,
factor.ToString()));
string s = result.ToString();
}
}
public static void membefore(string xaml)
{
FileInfo fi = new FileInfo(xaml);
len = fi.Length;
Console.WriteLine(string.Format("Loading file {0} with originally {1}kb", xaml, fi.Length / 1024));
if (xaml.Contains("ico") || xaml.Contains("jpg") || xaml.Contains("bmp") || xaml.Contains("png"))
{
before = Process.GetCurrentProcess().VirtualMemorySize64;
}
}
private static long len = 0;
static long before = 0;
Ok right,
the reason there are different file formats was behind it.
Irfanview helped a lot with pressing I opening image information shows file and loaded memory size.
Hello! The problem is? that I've got a multipage Tiff file to show, and I use
BitmapFrame.Thumbnail property to show small size thumbnail of every frame(page) of my multipage Tiff file. But< for some reason? the property returns null. Please, give step by step description, of how this should be done?
I've already tried to create my own BitmapSource thumbnail with this method:
public static BitmapImage GetThumbnail(BitmapFrame bitmapFrame)
{
try
{
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
MemoryStream memorystream = new MemoryStream();
BitmapImage tmpImage = new BitmapImage();
encoder.Frames.Add(bitmapFrame);
encoder.Save(memorystream);
tmpImage.BeginInit();
tmpImage.CacheOption = BitmapCacheOption.OnLoad;
tmpImage.StreamSource = new MemoryStream(memorystream.ToArray());
File.WriteAllBytes( $"{Path.GetTempFileName()}.jpg", memorystream.ToArray());
tmpImage.UriSource = new Uri($"{Path.GetTempFileName()}.jpg");
tmpImage.DecodePixelWidth = 80;
tmpImage.DecodePixelHeight = 120;
tmpImage.EndInit();
memorystream.Close();
return tmpImage;
}
catch (Exception ex)
{
return null;
throw ex;
}
}
then I convert the result to BitmapSource and create a list of BitmapFrames using:
List<BitmapFrame> tiffImageList = new List<BitmapFrame>();
tiffImageList.Add(new TiffImage() { index = imageIndex, image = BitmapFrame.Create(frame, (BitmapSource)GetThumbnail(frame))});
In the end I try to get property, but it returns null:
foreach (var tiffImage in tiffImageList)
{
Image image = new Image();
image.Source = tiffImage.image.Thumbnail;
}
I ran into a similar issue, modifying with the SDK PhotoViewerDemo example. Some valid jpg's are shown as white square thumbnails.
I think I found why the question code does not work. Ivan's question provides a correct constructor of BitmapFrame, but the functions have to create a BitmapSource, not a BitmapImage.
C# BitmapFrame.Thumbnail property is null for some images
I got it working with the function provided in that topic, using Ivan's call to the constructor, using the two bitmapsource arguments.
Code in the SDK example I now use is..
private BitmapSource CreateBitmapSource(Uri path)
{
BitmapImage bmpImage = new BitmapImage();
bmpImage.BeginInit();
bmpImage.UriSource = path;
bmpImage.EndInit();
return bmpImage;
}
private BitmapSource CreateThumbnail(Uri path)
{
BitmapImage bmpImage = new BitmapImage();
bmpImage.BeginInit();
bmpImage.UriSource = path;
bmpImage.DecodePixelWidth = 120;
bmpImage.EndInit();
return bmpImage;
}
// it has to be plugged in here,
public Photo(string path)
{
Source = path;
_source = new Uri(path);
// replaced.. Image = BitmapFrame.Create(_source);
// with this:
Image = BitmapFrame.Create(CreateBitmapSource(_source),CreateThumbnail(_source));
Metadata = new ExifMetadata(_source);
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 9 years ago.
Improve this question
I have a task of posting two images to the server, combining them (one on top of the other) and then saving the resulting image to Azure Storage. I have code that works, but it just looks...wrong. Is there a less ugly way to do this? I hate seeing all those "Using" statements and the long indent.
This code combines a signature image and an initials image, then saves the result to Azure Storage.
code:
string initialscontainerPath = "signatures/initailsdata.png";
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(Microsoft.WindowsAzure.CloudConfigurationManager.GetSetting("StorageConnection"));
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(Request.Url.Host.ToLower().Replace(".", "-"));
CloudBlockBlob blockBlob = container.GetBlockBlobReference(initialscontainerPath);
blockBlob.Properties.ContentType = "image/png";
byte[] initialsbytes = Convert.FromBase64String(initialsData);
byte[] signaturebytes = Convert.FromBase64String(signatureData);
using (System.IO.MemoryStream msinitials = new System.IO.MemoryStream(initialsbytes))
{
using (System.IO.MemoryStream mssignature = new System.IO.MemoryStream(signaturebytes))
{
using (System.Drawing.Image bminitials = new System.Drawing.Bitmap(msinitials))
{
using (System.Drawing.Image bmsignature = new System.Drawing.Bitmap(mssignature))
{
using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmsignature))
{
g.DrawImage(bminitials, 0, 0);
using (System.IO.MemoryStream savestream = new System.IO.MemoryStream())
{
bmsignature.Save(savestream, System.Drawing.Imaging.ImageFormat.Png);
using (System.IO.MemoryStream uploadstream = new System.IO.MemoryStream(savestream.ToArray()))
{
blockBlob.UploadFromStream(uploadstream);
}
}
}
}
}
}
}
Have you looked into drawing one on top of the other? Just read the images into bitmap objects and draw the smaller one on top of the other, kinda like this:
public Bitmap Combine(Bitmap largeBmp, Bitmap smallBmp) {
Graphics g = Graphics.FromImage(largeBmp);
g.CompositingMode = CompositingMode.SourceOver;
int margin = 5;
int x = largeBmp.Width - smallBmp.Width - margin;
int y = largeBmp.Height - smallBmp.Height - margin;
g.DrawImage(smallBmp, new Point(x, y));
return largeBmp;
}
note that x and y are the coordinates on which the small image is gonna exit on the larger image.
Hope it helps
Using just gets converted into a try...catch...finaly block and in the finaly the variable gets disposed. And also you could eliminate the namespace and put more using statements in the begining of the code. I think this is more readable:
string initialscontainerPath = "signatures/initailsdata.png";
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(Microsoft.WindowsAzure.CloudConfigurationManager.GetSetting("StorageConnection"));
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(Request.Url.Host.ToLower().Replace(".", "-"));
CloudBlockBlob blockBlob = container.GetBlockBlobReference(initialscontainerPath);
blockBlob.Properties.ContentType = "image/png";
byte[] initialsbytes = Convert.FromBase64String(initialsData);
byte[] signaturebytes = Convert.FromBase64String(signatureData);
CombineBitmaps(initialsbytes, signaturebytes);
Where CombineBitmaps is
private void CombineBitmaps(byte[] initialsbytes, byte[] signaturebytes, CloudBlockBlob blockBlob)
{
MemoryStream msinitials = null;
MemoryStream mssignature = null;
MemoryStream savestream = null;
MemoryStream uploadstream = null;
Bitmap bminitials = null;
Bitmap bmsignature = null;
Graphics g = null;
try
{
msinitials = new MemoryStream(initialsbytes);
mssignature = new MemoryStream(signaturebytes);
bminitials = new Bitmap(msinitials);
bmsignature = new Bitmap(mssignature);
savestream = new MemoryStream();
g = Graphics.FromImage(bmsignature);
g.DrawImage(bminitials, 0, 0);
bmsignature.Save(savestream, ImageFormat.Png);
uploadstream = new MemoryStream(savestream.ToArray());
blockBlob.UploadFromStream(uploadstream);
}
finally
{
DisposeNotNull(msinitials, mssignature, bminitials, bmsignature, g, savestream, uploadstream);
}
}
private void DisposeNotNull(params IDisposable[] objects)
{
foreach(IDisposable obj in objects)
if (obj != null) obj.Dispose();
}
And the variable names could use some pascal caseing (or what ever the name is).
How can I build video from stream image (only image without sound) in C#?
Here is some code of my application:
static int ii = 1;
public void drawBitmap(byte[] data)
{
MemoryStream ms = new MemoryStream(data);
try
{
Bitmap b = new Bitmap(ms);
b.Save(#"c:\test\" + (ii++) + ".jpg");
Image i = (Image)b;
pictureBox1.Image = i;
ii++;
}
catch (Exception e)
{
}
}
I used the wrapper mentioned above, like this:
private static void hejHopp()
{
//http://www.codeproject.com/Articles/7388/A-Simple-C-Wrapper-for-the-AviFile-Library
//myReadyNAS device, got files via FTP from my webcam
var jpgFileList = Directory.EnumerateFiles(sourcePath,"*.jpg");
//load the first image
Bitmap bitmap = (Bitmap)Image.FromFile(jpgFileList.First());
//create a new AVI file
AviManager aviManager = new AviManager(sourcePath + "\\tada.avi", false);
//add a new video stream and one frame to the new file
//set IsCompressed = false
VideoStream aviStream = aviManager.AddVideoStream(false, 2, bitmap);
jpgFileList.Skip(1).ToList().ForEach(file =>
{
bitmap = (Bitmap)Bitmap.FromFile(file);
aviStream.AddFrame(bitmap);
bitmap.Dispose();
});
aviManager.Close();
}
You might want to take a look at this thread:
http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/f23caf50-85a9-4074-8328-176c8bcc393e/
Same question. Some answers.
More is also available here:
http://www.codeproject.com/Articles/7388/A-Simple-C-Wrapper-for-the-AviFile-Library