← Inbox

C3D-0362 · Embed the vicinity PNG bytes into the DWG (base64 Xrecord) so it survives a lost link [C3D-VICEMBED] done

Reads 260714-vicinity.png from disk (54433 bytes), stores it as chunked base64 in an Xrecord under named-dictionary key C3D_VICINITY_EMBED (filename + length + chunk count header, then 2000-char chunks). The RasterImage link is unchanged - the file stays in the surveydisco folder as part of the process - but a full copy now lives in the drawing. Idempotent: replaces any prior embed. Verifies by decoding the round-trip and comparing the byte count.

Script file
C3D-0362.cs
Target
260714 - 285 Huckaby Rd R4.dwg · model space
Author
claude
Approved
yes · auto-auth
Timeout
180s

C# payload

// Embed the vicinity PNG bytes INSIDE the drawing so it survives the linked file going missing.
// The RasterImage stays linked (display path unchanged); a base64 copy of the file is stored,
// chunked, in an Xrecord under a named-object-dictionary key. Recovery elsewhere: read chunks,
// concat, Convert.FromBase64String, write back to the source path, Load().
const string DICTKEY = "C3D_VICINITY_EMBED";
Log("drawing: " + Db.Filename);

// find the vicinity image def + its source path
string src = null;
var nod = (DBDictionary)Tx.GetObject(Db.NamedObjectsDictionaryId, OpenMode.ForWrite);
if (nod.Contains("ACAD_IMAGE_DICT")) {
    var idict = (DBDictionary)Tx.GetObject(nod.GetAt("ACAD_IMAGE_DICT"), OpenMode.ForRead);
    foreach (DBDictionaryEntry de in idict) {
        var def = (RasterImageDef)Tx.GetObject(de.Value, OpenMode.ForRead);
        if (de.Key.IndexOf("VICINITY", StringComparison.OrdinalIgnoreCase) >= 0) { src = def.SourceFileName; break; }
        if (src == null) src = def.SourceFileName;
    }
}
if (src == null) { Log("no image definition found - nothing to embed"); return; }
Log("source: " + src);
if (!System.IO.File.Exists(src)) { Log("source file missing on disk - cannot embed"); return; }

byte[] bytes = System.IO.File.ReadAllBytes(src);
string b64 = System.Convert.ToBase64String(bytes);
Log(string.Format("read {0} bytes -> {1} base64 chars", bytes.Length, b64.Length));

// idempotent: replace any prior embed
if (nod.Contains(DICTKEY)) { nod.Remove(DICTKEY); Log("removed previous " + DICTKEY); }

var xrec = new Xrecord();
var rb = new ResultBuffer();
// header: original filename + byte length + chunk count
string fname = System.IO.Path.GetFileName(src);
const int CHUNK = 2000;   // Xrecord Text caps at 2047; stay under
int chunks = (b64.Length + CHUNK - 1) / CHUNK;
rb.Add(new TypedValue((int)DxfCode.Text, fname));
rb.Add(new TypedValue((int)DxfCode.Int32, bytes.Length));
rb.Add(new TypedValue((int)DxfCode.Int32, chunks));
for (int i = 0; i < chunks; i++) {
    int len = System.Math.Min(CHUNK, b64.Length - i * CHUNK);
    rb.Add(new TypedValue((int)DxfCode.Text, b64.Substring(i * CHUNK, len)));
}
xrec.Data = rb;
nod.SetAt(DICTKEY, xrec);
Tx.AddNewlyCreatedDBObject(xrec, true);
Log(string.Format("wrote {0}: {1} in {2} chunks", DICTKEY, fname, chunks));

// verify: read it straight back and rebuild the byte count
{
    var back = (Xrecord)Tx.GetObject(nod.GetAt(DICTKEY), OpenMode.ForRead);
    var sb = new System.Text.StringBuilder();
    string fn = ""; int declaredLen = 0, declaredChunks = 0; int idx = 0;
    foreach (TypedValue tv in back.Data) {
        if (idx == 0) fn = (string)tv.Value;
        else if (idx == 1) declaredLen = System.Convert.ToInt32(tv.Value);
        else if (idx == 2) declaredChunks = System.Convert.ToInt32(tv.Value);
        else sb.Append((string)tv.Value);
        idx++;
    }
    byte[] round = System.Convert.FromBase64String(sb.ToString());
    bool ok = round.Length == bytes.Length && fn == fname;
    Log(string.Format("VERIFY: fname=\"{0}\" declaredLen={1} chunks={2} decoded={3} bytes  {4}",
        fn, declaredLen, declaredChunks, round.Length, ok ? "MATCH" : "*** MISMATCH ***"));
}

Result

Status
success
Drawing file
C:\Users\sanja\OneDrive\_SurveyDisco\260714 - 285 Huckaby Rd, Brooks, GA 30205, USA\260714 - 285 Huckaby Rd R4.dwg
Message
Executed C3D-0362 (0 entities touched).
Entities
Duration
917 ms
Civil 3D
25.0.0.0

Log

drawing: C:\Users\sanja\OneDrive\_SurveyDisco\260714 - 285 Huckaby Rd, Brooks, GA 30205, USA\260714 - 285 Huckaby Rd R4.dwg
source: C:\Users\sanja\OneDrive\_SurveyDisco\260714 - 285 Huckaby Rd, Brooks, GA 30205, USA\260714-vicinity.png
read 54433 bytes -> 72580 base64 chars
removed previous C3D_VICINITY_EMBED
wrote C3D_VICINITY_EMBED: 260714-vicinity.png in 37 chunks
VERIFY: fname="260714-vicinity.png" declaredLen=54433 chunks=37 decoded=54433 bytes  MATCH

Notes

What worked, what didn't, job-specific gotchas — flagged notes feed the recipes.

No notes yet.