PDF file size when printing with RhinoCommon

Hello dear Rhino colleagues. I have created layout to pdf a batch export command (C# command). However, if file is opened for the first time and printed pdfs file size are huge. If same command is immediately repeated, file size get to app. 6-8 smaller size (same size as if it is printed manually with RhinoPDF). Time for command run is also shorter. See video…

I overcome that problem with running printing twice during one command. In first print huge sizes are created. In second there are replaced by smaller one. Both runs uses same C# code.

Do anyone knows what why files sizes varies?

Thank you for your time and reply,

Ondřej

Hi @janotaondrej91 ,
I think it would difficult to suggest anything, without looking at the code.

Here is the code. It is same for both cases.

protected override Result RunCommand(RhinoDoc doc, RunMode mode)
        {
            string dummyFileName = "Do not override me!!";
            SaveFileDialog sf = new SaveFileDialog();
            sf.FileName = dummyFileName;
            sf.Title = "Select directory.";
            sf.RestoreDirectory = true;
            string dir = "";
            if (sf.ShowDialog() == DialogResult.OK)
            {
                dir = System.IO.Path.GetDirectoryName(sf.FileName);
            }
            else
            {
                return Result.Cancel;
            }

            Rhino.DocObjects.Tables.ViewTable viewTable = Rhino.RhinoDoc.ActiveDoc.Views;
            int dpi = 600;
            for (int i = 0; i < 2; i++)
            {
                foreach (Rhino.Display.RhinoView view in viewTable)
                {
                    var pdf = Rhino.FileIO.FilePdf.Create();
                    if (view as Rhino.Display.RhinoPageView != null)
                    {
                            Rhino.Display.RhinoPageView actuaView = view as Rhino.Display.RhinoPageView;
                            int w = Convert.ToInt32(actuaView.PageHeight);
                            int h = Convert.ToInt32(actuaView.PageWidth);
                            System.Drawing.Size size = new System.Drawing.Size(Convert.ToInt32(h * 600 / 25.4), Convert.ToInt32(w * 600 / 25.4));
                            Rhino.Display.ViewCaptureSettings settings = new Rhino.Display.ViewCaptureSettings(view, size, dpi);
                            settings.RasterMode = false;
                            double res = settings.Resolution;
                            pdf.AddPage(settings);
                            string filePath = System.IO.Path.Combine(dir, actuaView.PageName + ".pdf");
                            pdf.Write(filePath);
                    }
                }
            }
            return Result.Success;
        }
    }

A couple of things I see in the code that could be causing excessive resolution and possibly file size.

your code makes some assumptions about the layouts page units. I see you’re doing an inch conversion on them. This is ok assuming your layouts are always in the same units but otherwise it will spell trouble. I would suggest adding a more direct unit scale inspection and conversion. Something like below.

  var unit_scale = RhinoMath.UnitScale(LayoutUnits, UnitSystem.Inches);
  var scaled_width = Layout.Width * unit_scale;
  var scaled_height = Layout.Height * unit_scale;
  var scaled_size = new Size((int)(scaled_width * resolution), (int)(scaled_height * resolution));

This will help configure the view capture when you’re using the ViewCaptureSettings constructor with 3 parameters.

Which leads me to the other thing.

There’s also a 2 param version of ViewCaptureSettings that takes a RhinoPageView and Resolution. You might find this version to be a lot less work if you always want the pdf sheet dimensions to match the layout dimensions.

var settings = new ViewCaptureSettings(pageView ,resolution);

If that doesn’t tame the file size issue I’d need the file to know more.

2 Likes

Thank you for your reply and suggestions.

We use these settings in 99% of drawings. Anyway, I have updated code according to yours suggestions.
Unfortunately, use of constructor with 2 arguments did not help either.

I don’t thing code structure is causing the problem. If I run code for the first time on any .3dm file it creates a huge file size. If it is rerun then file size is correct. Routine is same on each run.

Please find file used in the video in the attachments.

D214_SO132001_009-015.3dm (9.8 MB)

I have experienced the exact same effect. The PDF file size is huge on the first run.
I did not realise it first, and re-saved optimised from PDF viewer. But then quickly realised that after re-print the file’s size is fine.

I have been using this:

Exactly same problem. I have overcame it by doing it twice. However, if it works correctly time needed for
second run is much shorter.

Bummer, well we’ll dig in and take a look to see if we’re able to clean things up a bit.

https://mcneel.myjetbrains.com/youtrack/issue/RH-77542/FilePDF-creates-large-file-sizes-on-first-run

I’ve found a similar issue with Rhino 7, 7.34.23267.11001.

I believe it’s related to the print settings because I found that if I print the layout manually then save the file, next time around the file size and vector creation come out correctly (most of the time…). It appears that “ViewCaptureSettings” may not be respecting RasterMode = False if it’s not saved in the file. The large file sizes do not have transparent backgrounds as well which seems to indicate they end up as rasters.

Work around in my script has been to do as suggested above - print twice. (Below script opens each .3dm in a folder, runs grasshopper script that’s open, then saves result to pdf.)

import Rhino
import scriptcontext as sc
from scriptcontext import doc
import rhinoscriptsyntax as rs
import os
gh = Rhino.RhinoApp.GetPlugInObject("Grasshopper")

# USER INPUT
file_dir = r"<your dir>"
output_dir = r"<your dir>"


# DON'T NEED TO TOUCH THE REST
should_run = True
if should_run:
    # Get all the .3dm files
    files = os.listdir(file_dir)
    rhino_files = [f for f in files if os.path.splitext(f)[1] == '.3dm']
    rhino_files = [os.path.join(file_dir, f) for f in rhino_files]
    # Print to PDF for all
    for rf in rhino_files:
        # Open each Rhino file in the file_dir
        rs.Command('_-Open "{}" _Enter'.format(rf), 0)
        # Run grasshopper
        gh.RunSolver(True)
        
        # Save PDF of the file to output_dir
        fn = os.path.splitext(os.path.basename(rf))[0] + '.pdf'
        pdf_path = os.path.join(output_dir, fn)
        pages = sc.doc.Views.GetPageViews()
        if len(pages) > 0:
            pdf = Rhino.FileIO.FilePdf.Create()
            dpi = 300
            for page in pages:
                capture = Rhino.Display.ViewCaptureSettings(page, dpi)
                # Use DisplayColors for printing
                capture.OutputColor = 0
                capture.RasterMode = False
                capture.DrawBackground = False
                capture.DrawBackgroundBitmap = False
                pdf.AddPage(capture)
            pdf.Write(pdf_path)
            # Try to run again to get vector output?
            pdf = Rhino.FileIO.FilePdf.Create()
            dpi = 300
            for page in pages:
                capture = Rhino.Display.ViewCaptureSettings(page, dpi)
                # Use DisplayColors for printing
                capture.OutputColor = 0
                capture.RasterMode = False
                capture.DrawBackground = False
                capture.DrawBackgroundBitmap = False
                pdf.AddPage(capture)
            pdf.Write(pdf_path)
            
            # Save the 3dm file with markups to go to next file
            rs.Command('_-Save "{}"'.format(rf), 0)