1

Good afternoon!

I'm trying to open a pdf located into knownfolders in an UWP Hololens app without results... Does anyone know how to proceed? I managed to open it and retrieve its page number by using:

StorageFolder storageFolder = KnownFolders.CameraRoll;
StorageFile sampleFile = await storageFolder.GetFileAsync("prova.pdf");
PdfDocument pdfDocument = await PdfDocument.LoadFromFileAsync(sampleFile);
test.text = pdfDocument.PageCount.ToString();

I then added the selection of a page by using:

using (PdfPage firstPage = pdfDocument.GetPage(0))
{
    InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream();
    await firstPage.RenderToStreamAsync(stream);
    //Missing something here...
}

But as my comment state i have no idea how to convert the stream i create into an actual texture to apply to something... Any suggestion would be highly appreciated :)

Edit: I managed to make it work, to every poor soul trying to achieve the same results this is my code!

public async void LoadAsync()
{
    StorageFolder storageFolder = KnownFolders.CameraRoll;
    StorageFile sampleFile = await storageFolder.GetFileAsync("test.pdf");
    //pdfDocument is an instanced object of type PdfDocument
    pdfDocument = await PdfDocument.LoadFromFileAsync(sampleFile);
}

public async void ChangePageAsync()
{
    //pg is the page to load
    using (PdfPage firstPage = pdfDocument.GetPage((uint)pg)) 
    {
        InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream();
        await firstPage.RenderToStreamAsync(stream);
    
        MemoryStream tempStream = new MemoryStream();
        await stream.AsStream().CopyToAsync(tempStream);
           
        byte[] imgBytes = new byte[16 * 1024];
        imgBytes = tempStream.ToArray();

        Texture2D imgTex = new Texture2D(2048, 2048, TextureFormat.BC7, false);
        imgTex.LoadImage(imgBytes);
        imgTex.filterMode = FilterMode.Bilinear;
        imgTex.wrapMode = TextureWrapMode.Clamp;

        MeshRenderer meshRenderer = PDFPlane.GetComponent<MeshRenderer>();
        Material mat = meshRenderer.material;
        mat.SetTexture("_MainTex", imgTex);
        mat.mainTextureScale = new Vector2(1, 1);
    }
}

Big thanks to @AlexAR

1 Answers1

1

Basically you can turn your stream into a byte array and load these bytes into a texture. Then you can easily set this texture to a quad material to show the image of the pdf page. Here's a exemple of what I've done on a project :

using (PdfPage firstPage = pdfDocument.GetPage(0))
{
    InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream();
    await firstPage.RenderToStreamAsync(stream);
    
    MemoryStream tempStream = (MemoryStream)stream.AsStream();
    
    //initialize an empty byte array
    byte[] imgBytes = new byte[16 * 1024];
    imgBytes = tempStream.ToArray();

    //best parameters I found to get a good quality
    Texture2D imgTex = new Texture2D(2048, 2048, TextureFormat.BC7, false);
    imgTex.LoadImage(imgBytes);
    imgTex.filterMode = FilterMode.Bilinear;
    imgTex.wrapMode = TextureWrapMode.Clamp;

    MeshRenderer meshRenderer = YourGameObject.GetComponent<MeshRenderer>();
    Material mat = meshRenderer.material;
    mat.SetTexture("_MainTex", imgTex);
    mat.mainTextureScale = new Vector2(1, 1);
}             
AlexAR
  • 1,052
  • 1
  • 9
  • 15
  • Thanks for the answer! I'm trying to implement what you suggested, just a question, why did you initialize the byte array with that specific size? Was it by any chance dependant on the pdf page size? – Ivan Oe Valentini Mar 07 '22 at 16:12
  • I wasn't really sure and was wondering the same. I copy paste my solution as it was working for me. I found that value in this post : (Creating a byte array from a stream)[https://stackoverflow.com/questions/221925/creating-a-byte-array-from-a-stream] – AlexAR Mar 07 '22 at 16:43
  • Oh ok perfect. Tomorrow i will try something more, the actual idea was to set the sprite of an ui image as the page. I will probably try to create a sprite by using the texture created in the second to last paragraph of code. – Ivan Oe Valentini Mar 07 '22 at 21:41
  • Still here fighting with the thing, let me ask you one more thing, did you use the default material for the object that displays the page or did you create one ad hoc? And i imagine you used a plane as your display for the page, am i right? – Ivan Oe Valentini Mar 08 '22 at 15:29
  • As I remember I used the slate object of the MRTK and I used the material of the quad – AlexAR Mar 08 '22 at 20:45
  • Ok i managed to make it work! – Ivan Oe Valentini Mar 09 '22 at 15:15