I have a listview with Image control, bound with Uri value (image path on disk). I want to convert only those Uri in "Field of view" and dispose (or convert back to Uri) which goes out of "Field of View".
What I have tried:
I have used IValueConverter to convert Uri to Image but ConvertBack is not firing.
<Image Source="{Binding PageSource,Mode=TwoWay, UpdateSourceTrigger=Explicit, Converter={StaticResource ImageConverter}}" HorizontalAlignment="Center" VerticalAlignment="Top"/>
Source code:
private void LoadPdfFile(string fileName)
{
string folderPath = Environment.CurrentDirectory + "//ImageCache";
Directory.CreateDirectory(folderPath);
//concurrent queue- thread safe
ConcurrentQueue<PdfPage> cQueue = new ConcurrentQueue<PdfPage>();
//loading pdf file
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
//syncfusion pdf library to load pdf file
using (PdfLoadedDocument ldoc = new PdfLoadedDocument(fs))
{
//parallel for- to simultaneous loop
Parallel.For(0, ldoc.Pages.Count,
i =>
{
//convert pdf page into bitmap
Bitmap img = ldoc.ExportAsImage(i);
//saving image onto disk
//I don't want to load it into memory directly to save memory(but it is not working)
string imageName = folderPath + "//" + Guid.NewGuid().ToString();
img.Save(imageName);
//filling object value
PdfPage newFile = new PdfPage();
//Uri PageSource
newFile.PageSource = new Uri(imageName, UriKind.Absolute);
//int PageNumber
newFile.PageNumber = i + 1;
cQueue.Enqueue(newFile);
//disposing bitmap value
img.Dispose();
img = null;
GC.Collect();
GC.WaitForPendingFinalizers();
});
}
}
List<PdfPage> Pages = cQueue.OrderBy(x => x.PageNumber).ToList();
//assigning it to the collectionviewsource
itemCollectionViewSource.Source = Pages;
}
public class ImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
{
return null;
}
else
{
var uri = (Uri)value;
BitmapImage bmp = new BitmapImage();
bmp.BeginInit();
bmp.UriSource = uri;
bmp.UriCachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.NoCacheNoStore);
bmp.CacheOption = BitmapCacheOption.None;
bmp.EndInit();
return bmp;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
Update: I have changed the code to
Parallel.For(0, ldoc.Pages.Count,
i =>
{
using (Bitmap img = ldoc.ExportAsImage(i))
{
using (Stream stream = new MemoryStream())
{
PdfPage newFile = new PdfPage();
img.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp);
BitmapImage bmp = new BitmapImage();
bmp.BeginInit();
bmp.CacheOption = BitmapCacheOption.OnLoad;
bmp.StreamSource = stream;
bmp.EndInit();
bmp.Freeze();
//BitmapImage PageSource
newFile.PageSource = bmp;
newFile.PageNumber = i + 1;
cQueue.Enqueue(newFile);
}
}
GC.Collect();
GC.WaitForPendingFinalizers();
});
but this throws A generic error occurred in GDI+ error for large pages pdf file.