163 lines
3.9 KiB
Markdown
163 lines
3.9 KiB
Markdown
---
|
|
id: 2026-04-16T12:55:49-0400
|
|
title: 2026-04-16 12:55:49
|
|
tags:
|
|
- status/draft
|
|
date-created: 2026-04-16T12:55:49-04:00
|
|
daily: "[[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.
|
|
|
|
```python
|
|
# 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:
|
|
|
|
```pdf
|
|
<</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
|
|
|
|
```python
|
|
# 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.
|