Change PdfImage type (Syncfusion PDF) - c#

So I'm using Syncfusion Controls for UWP XAML, and I'm trying to insert JPEGs into a PDF I'm creating, but PdfImage seems to always return bitmaps. Or at least images with bitmap-like file sizes.
Is there any way to ensure the images being inserted are of JPEG size? The images I'm inputting are JPEGs to begin with.
I'd be fine with bitmaps if I wasn't making PDFs of manga (Japanese comic books), i.e. the size per manga right now ranges from 50-150MB.
It's not a working sample, but here's what I'm using right now.
public async void SaveAsPdf(Stream fs, Manga manga)
{
var m = manga;
var c = m.Content;
if (fs.Length != 0) return;
var pdf = new PdfDocument();
var pages = await GetPages(m);
pdf.PageSettings.SetMargins(0);
pdf.FileStructure.IncrementalUpdate = true;
pdf.EnableMemoryOptimization = true;
pdf.Compression = PdfCompressionLevel.Best;
for (var pi = 0; pi < c.ContentPages; pi++)
{
var section = pdf.Sections.Add();
var mr = section.PageSettings.Margins = new PdfMargins();
mr.All = 0;
var page = section.Pages.Add();
var g = page.Graphics;
page.DefaultLayerIndex = 0;
var pu = pages[pi];
var client = new HttpClient();
var im = await client.GetAsync(pu);
var pdi = PdfImage.FromStream(im.Content.ReadAsStreamAsync().Result);
g.DrawImage(pdi, new PointF(0, 0), g.ClientSize);
await pdf.SaveAsync(fs);
}
await pdf.SaveAsync(fs);
pdf.DocumentInformation.Title = c.ContentName;
pdf.DocumentInformation.Author += string.Join(", ", c.ContentArtists.Select(x => x.Attribute));
pdf.DocumentInformation.Keywords += string.Join(", ", c.ContentTags.Select(x => x.Attribute)).Replace("\"", string.Empty);
pdf.Save(fs);
pdf.Close(true);
var toast = Notifications.NotifyMangaDownloaded(m);
ToastNotificationManager.CreateToastNotifier().Show(toast);
fs.Dispose();
}
I'd ask about the memory leak but it'd probably be best if I made another post for that.
Thanks in advance.
(I posted this on the Syncfusion forums but I felt like I might get a better response here)

Well, I refactored some of the methods and the memory leak ended up being the cause. Lesson learned: using statements are your friends.
To be a little more specific, I just created a file as a destination for the PDF, then called
using (Stream s = new FileStream(/*string*/>f.Path, FileMode.OpenOrCreate))
{
await Task.Run(() => SaveAsPdf(/*StorageFile*/f, /*Manga*/m));
}
Various other things needed to be moved around, but leaving the FileStream open ended up being the problem.

Related

ObservableCollection doesnt virtualise data?

I want to add approx 600 images to my collection to show them in a Listview that virtualizes with Itemsstackpanel. If i didnt misread with virtualization its possible to load large datasets. My problem is that the collection can only hold around 150 images and then i get a OutOfMemory Exception. Is there something more to enable virtualization or is the problem that my Collection calls its propertyChanged Event for every image added?
The error is thrown on:
await pdfPage.RenderToStreamAsync(Imagestream);
and how i add to my collection:
for (uint i = convertedPageString; i < 200 + convertedPageString; i++)
{
Image img = await LoadPage(l_document, i);
collection.Add(img);
g_rootPage.ListViewControl.ItemsSource = collection;
}
convertedPageString is just the Page im starting on when the program is opened.
EDIT:
This is my function to get the Pages.
public async Task<Image> LoadPage(PdfDocument a_document, uint page)
{
Image l_image;
BitmapImage l_bitmap;
PdfPage pdfPage;
using (IRandomAccessStream Imagestream = new MemoryStream().AsRandomAccessStream())
{
using (pdfPage = a_document.GetPage(page))
{
await pdfPage.RenderToStreamAsync(Imagestream);
l_bitmap = new BitmapImage();
await l_bitmap.SetSourceAsync(Imagestream);
l_image = new Image();
l_bitmap.DecodePixelHeight = 1200;
l_bitmap.DecodePixelWidth = 1000;
l_image.Source = l_bitmap;
l_image.Margin = new Thickness(0, 5, 0, 10);
}
}
return l_image;
}
I forgot to mention that i open the application via the commandLine with a specified page and path.

Microsoft.CognitiveServices.Speech.DetailedSpeechRecognitionResultCollection error

We're experimenting with speech-to-text using Microsoft Cognitive Services. One of our requirements is to have word level timestamps. This works fine with short wav files, say, 2-3 minutes of audio, but with larger files we're getting an error:
"There was an error deserializing the object of type Microsoft.CognitiveServices.Speech.DetailedSpeechRecognitionResultCollection. The value '2152200000' cannot be parsed as the type 'Int32'."
Any and all hints as to how I can get around this would be greatly appreciated. Thanks in advance!
Code snippet:
config.OutputFormat = OutputFormat.Detailed;
config.RequestWordLevelTimestamps();
using (var audioInput = AudioConfig.FromWavFileInput(wavfile))
{
using var recognizer = new SpeechRecognizer(config, audioInput);
recognizer.Recognized += (s, e) =>
{
if (e.Result.Reason == ResultReason.RecognizedSpeech)
{
var framesStart = TimeSpan.FromTicks(e.Result.OffsetInTicks).TotalMilliseconds / 40;
var te = new TranscriptElement((long)framesStart, e.Result.Text, languageCode);
// Eventually fails on the following line:
var words = e.Result.Best().OrderByDescending(x => x.Confidence).First().Words;
foreach (var w in words.OrderBy(w => w.Offset))
{
var start = TimeSpan.FromTicks(w.Offset).TotalMilliseconds / 40;
var duration = TimeSpan.FromTicks(w.Duration).TotalMilliseconds / 40;
te.SingleWords.Add(new TranscriptSingleWord((long)start, (long)(start + duration), w.Word));
}
transcriptElements.Add(te);
}
else if (e.Result.Reason == ResultReason.NoMatch)
{
_logger.LogError($"NOMATCH: Speech could not be recognized.");
}
};
await recognizer.StartContinuousRecognitionAsync().ConfigureAwait(false);
Task.WaitAny(new[] { stopRecognition.Task });
await recognizer.StopContinuousRecognitionAsync().ConfigureAwait(false);
}
It's a bug in the data type the extension is using for the offset. An int can only track ~214s of audio.
You can access the raw JSON that the Best() method is using from the result's property collection through the SpeechServiceResponse_JsonResult property until a fix is available.

Saving Canvas to device memory in Xamarin.Forms

I have canvas made from bitMap (photo) and my finger drawings in Xamarin Forms. I need to save it to memory device (perfectly it would be photo roll but could be just memory of device). For now (after googling few hours) i have something like this:
saveButt.Clicked += async(sender, args) =>
{
var newSurface = SKSurface.Create(
(int)canvasView.CanvasSize.Width,
(int)canvasView.CanvasSize.Height,
SKImageInfo.PlatformColorType,
SKAlphaType.Premul);
var canvas = newSurface.Canvas;
if (photoBitmap != null)
{
canvas.DrawBitmap(photoBitmap, new SKRect(0, 0, (float) canvasView.Width, (float) canvasView.Height));
}
foreach (SKPath path in completedPaths)
{
canvas.DrawPath(path, paint);
}
foreach (SKPath path in inProgressPaths.Values)
{
canvas.DrawPath(path, paint);
}
canvas.Flush();
var snap = newSurface.Snapshot();
var pngImage = snap.Encode();
};
I don't know how i can get access to memory or photo roll to save it.
#Edit
I tried use PCLStorage plugin to save it and for now it don't throw any exceptions or errors but still when i look through all folders i can't find any new folder or file with those names.
var snap = newSurface.Snapshot();
var pngImage = snap.Encode();
IFolder rootFolder = FileSystem.Current.LocalStorage;
IFolder folder = await rootFolder.CreateFolderAsync("MySubFolder",
CreationCollisionOption.OpenIfExists);
IFile file = await folder.CreateFileAsync("image.png",
CreationCollisionOption.ReplaceExisting);
using (Stream s = await file.OpenAsync(PCLStorage.FileAccess.ReadAndWrite))
{
pngImage.SaveTo(s);
}

WIA Duplex scanning using document feeder

Below is my c# code trying to transfer image from the duplex scanner. I'm able to acquire one image (Front Only) but i cant get the second image. I have tried changing the device property 3088 to 5 but i get a catastrophic failure. I'm working with WIA 2.0 on windows 10, 64 bit but project is using X86. I have also tried to transfer the image twice as i have read in previous questions but i get an error. I'm using duplexid600 scanner and from the windows scanner software i'm able to get a duplex image. Below is my code
CommonDialogClass commonDialogClass = new CommonDialogClass();
Device scannerDevice = commonDialogClass.ShowSelectDevice(WiaDeviceType.ScannerDeviceType, false, false);
if (scannerDevice != null)
{
Item scannnerItem = scannerDevice.Items[1];
//object value;
// AdjustScannerSettings(scannnerItem, 300, 0, 0, 1010, 620, 0, 0);
// object kuku;
// kuku = scannerDevice.Properties["Document Handling Select"].get_Value();
scannerDevice.Properties["Document Handling Select"].set_Value(1);//3088
// kuku = scannerDevice.Properties["Document Handling Select"].get_Value();
scannerDevice.Properties["Pages"].set_Value(1);//3096
// object scanResult = commonDialogClass.ShowTransfer(scannnerItem, WIA.FormatID.wiaFormatTIFF, false);
object scanResult = scannnerItem.Transfer(WIA.FormatID.wiaFormatBMP);
//object scanResult1 = scannnerItem.Transfer(WIA.FormatID.wiaFormatTIFF);
if (scanResult != null)
{
ImageFile image = (ImageFile) scanResult;
// string fileName = Path.GetTempPath() + DateTime.Now.ToString("dd-MM-yyyy-hh-mm-ss-fffffff") + ".tif";
var imageBytes = (byte[])image.FileData.get_BinaryData();
var ms = new MemoryStream(imageBytes);
var img = Image.FromStream(ms);
//int pageCount = 0;
//Image Tiff = img;
//pageCount = Tiff.GetFrameCount(FrameDimension.Page);
// Tiff.Dispose();
// SaveImageToPNGFile(image, fileName);
pictureBoxScannedImage.Image = img;
}
}
Call this one twice, it should give the 2nd image if you have 3088 set to 5 (duplex).
object scanResult = scannnerItem.Transfer(WIA.FormatID.wiaFormatBMP);
object scanResultbacksite = scannnerItem.Transfer(WIA.FormatID.wiaFormatBMP);
Beware though - on my scanner with the 2nd "start scan" command, you issue a new task, meaning your scanner could start to scan the 2nd physical page already - while assigning the backpage to your file. If you know a solution to this, tell me please!

Convert StorageFile to WriteableBitmap WP8.1 Silverlight

I am developing this application where I am able to get all the pictures from picture library as StorageFile data type. now I want to change it to writeablebitmap, apply a sketch filter and show in image control. can someone please help me in changing the data type from StorageFile to writeablebitmap?
here is my code:
StorageFolderpicturesFolder = KnownFolders.PicturesLibrary;
IReadOnlyList<IStorageFile> file = await picturesFolder.GetFilesAsync(CommonFileQuery.OrderByDate);
if(file.Count > 0)
{
foreach(StorageFile f in file)
{
// the code for changing the data type will go here
}
This code works for me.
if (file.Count > 0)
{
foreach (StorageFile f in file)
{
ImageProperties properties = await f.Properties.GetImagePropertiesAsync();
WriteableBitmap bmp = new WriteableBitmap((int)properties.Width, (int)properties.Height);
bmp.SetSource((await f.OpenReadAsync()).AsStream());
// Ready to go with bmp
}
}
Try this, it should work:
IReadOnlyList<IStorageFile> files = await picturesFolder.GetFilesAsync(CommonFileQuery.OrderByDate);
if(files.Count > 0)
{
var images = new List<WriteableBitmap>();
foreach(var f in files)
{
var bitmap = new WriteableBitmap(500, 500);
using (var stream = await f.OpenAsync(FileAccessMode.ReadWrite))
{
bitmap.SetSource(stream);
}
images.Add(bitmap);
}
}

Categories

Resources