Files
zmVault/timestamped/2026-04-16_12-55-49.md

3.9 KiB

id, title, tags, date-created, daily
id title tags date-created daily
2026-04-16T12:55:49-0400 2026-04-16 12:55:49
status/draft
2026-04-16T12:55:49-04:00 2026-04-16

2026-04-16 12:55:49

Batch Creating Bluebeam Revu Length Measure Annotations

I've been trying for years now to figure out how to batch create PDF markups understood by the Bluebeam Revu as length measurements.

The most practical route I've found so far is to batch create polyline annotations through a PDF editing library, export these markups to Revu's XML based .bax format, edit the XML, then reimport the modified .bax file.

Converting a Polyline to a Bluebeam Polylength

Export Markups

Below is a .bax file for a single-page letter-sized PDF document with only two markups, one standard polyline, and one polylength measurement.

<?xml version="1.0" encoding="utf-8"?>
<Document Version="1">
  <Page Index="0">
    <Label>1</Label>
    <Width>612</Width>
    <Height>792</Height>
    <Annotation>
      <Page>1</Page>
      <Contents />
      <ModDate>2026-04-16T10:34:28.0000000Z</ModDate>
      <Color>#FF0000</Color>
      <Type>PolyLine</Type>
      <ID>QYMFSTEOUXIEHCPW</ID>
      <TypeInternal>Bluebeam.PDF.Annotations.AnnotationPolyline</TypeInternal>
      <Raw>789c<!--HEX TRUNCATED--></Raw>
      <Index>0</Index>
      <Subject>PolyLine</Subject>
      <CreationDate>2026-04-16T10:34:28.0000000Z</CreationDate>
      <Author>zmeyers</Author>
    </Annotation>
    <Annotation>
      <Page>1</Page>
      <Contents>15'-7"</Contents>
      <ModDate>2026-04-16T10:35:00.0000000Z</ModDate>
      <Color>#FF0000</Color>
      <Type>PolyLine</Type>
      <ID>BMHFFZSZURMLPTRN</ID>
      <TypeInternal>Bluebeam.PDF.Annotations.AnnotationMeasurePolylength</TypeInternal>
      <Raw>789cad92d<!--HEX TRUNCATED--></Raw>
      <Index>1</Index>
      <Subject>Polylength Measurement</Subject>
      <CreationDate>2026-04-16T10:34:50.0000000Z</CreationDate>
      <Author>zmeyers</Author>
    </Annotation>
    <Scale>
      <Page>1</Page>
      <ID>RKEGIABVKDXPBWJP</ID>
      <Raw>789c<!--HEX TRUNCATED--></Raw>
      <Ratio>0.25 in = 1 ft' in"</Ratio>
      <Index>-1</Index>
      <X1>0</X1>
      <Y1>0</Y1>
      <X2>612</X2>
      <Y2>792</Y2>
    </Scale>
  </Page>
  <GlobalResources>
    <Resource>
      <ID>789cf37<!--HEX TRUNCATED--></Raw>
    </Resource>
    <Resource>
      <ID>789c<!--HEX TRUNCATED--></ID>
      <Raw>789c<!--HEX TRUNCATED--></Raw>
    </Resource>
  </GlobalResources>
</Document>

Change <TypeInternal>

Change the <TypeInternal> property of the polyline from Bluebeam.PDF.Annotations.AnnotationPolyline to Bluebeam.PDF.Annotations.AnnotationMeasurePolylength

Change <Raw>

Decode and Decompress

Decode and decompress the value of the <Raw> property.

[!info] The standard header 789c indicates the data is zlib-compressed binary, encoded as hexadecimal.

# decompress_hex.py
import zlib
import binascii
import sys

raw_hex = sys.argv[1]

data = binascii.unhexlify(raw_hex)
decompressed = zlib.decompress(data)

print(decompressed)

The resultant text is a PDF object resembling the following:

<</Vertices[161.8211 574.2108 279.8409 669.1133 407.5944 594.2863]/IC[1 0 0]/T(zmey...>>
Modify the Object

Insert the following key-value pair:

/Measure/BBObjPtr_XXXXXXXXXXXXXXXX

where XXX... is the name of the Scale object. It may be most straightforward to copy this key-value pair from a manually created length measurement on the same page.

Recompress and Reencode
# compress_to_hex.py
import zlib
import binascii
import sys

text = sys.argv[1]
compressed = zlib.compress(text.encode('utf-8'))
hex_encoded = binascii.hexlify(compressed).decode('ascii')

print(hex_encoded)

Replace the old value of <Raw> with the modified hex.

Reimport Markups

In the target PDF, open the markup summary, delete all markups, then reimport.