Pattern-Projector / pattern-projector

https://www.patternprojector.com/
MIT License
75 stars 16 forks source link

Thicken lines #8

Closed courtneypattison closed 5 months ago

hluedeke commented 6 months ago

Pulled this example from ChatGPT, so not sure it's reliable, but it's a starting point. This uses a direct render from pdfjs, not using the react wrapper lib:


    // URL of the PDF file
    const pdfUrl = 'example.pdf';

    // Asynchronous function to render PDF
    async function renderPDF() {
      // Fetch PDF document
      const loadingTask = pdfjsLib.getDocument(pdfUrl);
      const pdf = await loadingTask.promise;

      // Get the first page
      const pageNumber = 1;
      const page = await pdf.getPage(pageNumber);

      // Get canvas element
      const canvas = document.getElementById('pdfCanvas');

      // Set canvas dimensions
      const viewport = page.getViewport({ scale: 1.5 });
      canvas.width = viewport.width;
      canvas.height = viewport.height;

      // Render the page content on canvas
      const renderContext = {
        canvasContext: canvas.getContext('2d'),
        viewport: viewport
      };

      // Increase line width
      renderContext.canvasContext.lineWidth = 5;

      await page.render(renderContext);
    }

    // Call renderPDF function
    renderPDF();
  </script>```
hluedeke commented 6 months ago

I tried this approach with a custom renderer, and unfortunately it did not work.

My next plan is to try and get the document tree structure to see if there's a way to manually modify/draw it. However, I was unable to use the onGetTreeStructSuccess or onGetTreeStructError on the <Page /> element, as they were never called when loading my test document. The hook onGetTextSuccess did return all the text nodes in the document, so that's something at least.

This one is not looking very simple, but I will keep trying things as I think of them. In the meantime, PDFStitcher has a setting in its tool under the Layers tab that allows you to set the line thickness. This method worked beautifully for me, so perhaps in the short term we simply need to update the documentation with instructions on how to thicken lines using PDFStitcher.

courtneypattison commented 6 months ago

I tried this approach with a custom renderer, and unfortunately it did not work.

Ah, that's frustrating.

My next plan is to try and get the document tree structure to see if there's a way to manually modify/draw it. However, I was unable to use the onGetTreeStructSuccess or onGetTreeStructError on the <Page /> element, as they were never called when loading my test document. The hook onGetTextSuccess did return all the text nodes in the document, so that's something at least.

Since the page is rendered on the canvas, could we do something like getImageData() and run an algorithm for thickening up lines on the pixels?

This one is not looking very simple, but I will keep trying things as I think of them. In the meantime, PDFStitcher has a setting in its tool under the Layers tab that allows you to set the line thickness. This method worked beautifully for me, so perhaps in the short term we simply need to update the documentation with instructions on how to thicken lines using PDFStitcher.

I think that's a good idea, since I only mention using it for layers right now and people might not think of it for line thickness. However, I didn't have any luck getting it to work on the last pattern I cut. Can you verify if this pattern works for you? I would not be surprised if it's a case of user error!

hluedeke commented 6 months ago

Since the page is rendered on the canvas, could we do something like getImageData() and run an algorithm for thickening up lines on the pixels?

I'm all for trying it! Have you been working on this? I will totally leave you be to work on it if you already have a good start.

Can you verify if this pattern works for you? I would not be surprised if it's a case of user error!

I was able to thicken the lines, but it definitely tiled incorrectly, haha. You do have to click "Apply to Checked" after setting the line thickness, which isn't obvious. Try clicking the button after setting the line thickness and see if that fixes it!

courtneypattison commented 6 months ago

Since the page is rendered on the canvas, could we do something like getImageData() and run an algorithm for thickening up lines on the pixels?

I'm all for trying it! Have you been working on this? I will totally leave you be to work on it if you already have a good start.

I haven't started on it! Just an idea. I'm working on internationalization right now. Responding to messages has taken up a lot of time and I can only work on this when the kiddos are sleeping so progress is slow going.

Can you verify if this pattern works for you? I would not be surprised if it's a case of user error!

I was able to thicken the lines, but it definitely tiled incorrectly, haha. You do have to click "Apply to Checked" after setting the line thickness, which isn't obvious. Try clicking the button after setting the line thickness and see if that fixes it!

Ahh! That's it. Thank you :)

hluedeke commented 6 months ago

I dug into the bowels of react-pdf/pdfjs to see what I could accomplish. I discovered a way to hide pdf layers, however, it doesn't feel very nice. I'm not sure I have the PDF render lifecycle grasped well enough to feel confident implementing yet. However, I wanted to share my notes.

I don't think there is a way to hide layers using the standard canvas renderer PageCanvas provided by react-pdf, as there is no access to the RenderParameters object from that implementation. There is a property on RenderParameters called optionalContentConfigPromise that accepts a promise and allows you to access/hide the layers.

A basic implementation is:

async function optionalContentConfigPromise () {
  if (documentProxy) {
    const optionalContentConfig = await proxy.getOptionalContentConfig();
    const groups = optionalContentConfig.getGroups();
    if (groups) {
      Object.keys(groups).forEach((key) => {
         optionalContentConfig.setVisibility(key, false); // Hide the layer
      }
    }
    return optionalContentConfig;
  }
  return ...; // Need to figure out how to create a default optionalContentConfig
}

The next subject is line thickness. You can access the strokeWidth of each line by putting the following code in onLoadSuccess of the <Page /> component:

  const operatorList = await pageProxy.getOperatorList();
  operatorList.fnArray.forEach((fn, i) => {
    if (fn === 2) { // The numeric identifier for setting stroke width
       console.log('The stroke width setting:', operatorList.argsArray[i];
    }
  }
}

I have so far been unable to find a way to update the stroke width value. As far as I can tell, almost all methods on the proxy objects are getters and not setters.

courtneypattison commented 6 months ago

Thank you so much for looking into this :)

hluedeke commented 5 months ago

So I finally got a chance to use this today - like ACTUALLY use it to cut out a pattern!

I used the keys almost exclusively (including tab because I know it's there 😉). I did prefer to drag the canvas to get to the piece I wanted, but for corner calibration, the keys were the way to go!

I wanted to comment here because I don't know if it's just the pattern I'm using or the fact that I have a bright UST, but I did not think that the lines needed to be thickened at all. In fact, I used "green invert" mode, and it was amazing. The lines were very obvious and clear.

I am leaning toward won't fixing this because I really don't think it's necessary (of course I only tried with one pattern - a Sinclair one). I also think it's going to be a huge pain to figure out (we're talking custom library logic, not just custom renderer).

hluedeke commented 5 months ago

IMG_2639

IMG_2640

courtneypattison commented 5 months ago

I just tested this out and totally agree. Even with my lights on I could see the lines and I have a crummy $50 projector. I don't think it's worth the effort/complexity. Plus it seems a bit out of scope. pdfjs and pattern projector are pdf viewers not pdf editors.

I'm so happy you had the time to make something!!! I had a hectic day with the fam jam today but plan on cutting and sewing something tomorrow!