Skip to content

Commit 91bc22e

Browse files
committed
add image generation
1 parent f26f56a commit 91bc22e

2 files changed

Lines changed: 80 additions & 2 deletions

File tree

src/processors/gridsetProcessor.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,32 @@ class GridsetProcessor extends BaseProcessor {
572572
);
573573
}
574574

575+
// Pre-load all image data for conversion to other formats (e.g., Snap)
576+
const imageDataCache = new Map<string, Buffer>();
577+
const imageEntries = entries.filter((e) => {
578+
const name = e.entryName.toLowerCase();
579+
return (
580+
name.endsWith('.png') ||
581+
name.endsWith('.jpg') ||
582+
name.endsWith('.jpeg') ||
583+
name.endsWith('.gif') ||
584+
name.endsWith('.svg')
585+
);
586+
});
587+
588+
for (const imageEntry of imageEntries) {
589+
try {
590+
const raw = await imageEntry.getData();
591+
const data = isEncryptedArchive
592+
? decryptGridsetEntry(Buffer.from(raw), encryptedContentPassword)
593+
: Buffer.from(raw);
594+
const normalizedEntry = imageEntry.entryName.replace(/\\/g, '/');
595+
imageDataCache.set(normalizedEntry, data);
596+
} catch (err) {
597+
// Silently fail - individual image loading failures shouldn't break the entire load
598+
}
599+
}
600+
575601
// First pass: collect all grid names and IDs for navigation resolution
576602
const gridNameToIdMap = new Map<string, string>();
577603
const gridIdToNameMap = new Map<string, string>();
@@ -1095,6 +1121,11 @@ class GridsetProcessor extends BaseProcessor {
10951121
);
10961122
}
10971123

1124+
// Load binary image data from cache for conversion to other formats (e.g., Snap)
1125+
const imageData = resolvedImageEntry
1126+
? imageDataCache.get(resolvedImageEntry)
1127+
: undefined;
1128+
10981129
// Check if image is a symbol library reference
10991130
let symbolLibraryRef: SymbolReference | null = null;
11001131
if (declaredImageName && isSymbolLibraryReference(declaredImageName)) {
@@ -1673,6 +1704,8 @@ class GridsetProcessor extends BaseProcessor {
16731704
!isMoreButton
16741705
? wordListCellIndex - 1
16751706
: undefined,
1707+
// Store binary image data for conversion to other formats
1708+
...(imageData ? { imageData, image_id: resolvedImageEntry } : {}),
16761709
},
16771710
});
16781711

src/processors/snapProcessor.ts

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,51 @@ class SnapProcessor extends BaseProcessor {
11061106
useMessageRecording = 1;
11071107
}
11081108

1109+
// Handle image data from button.parameters.imageData or button.image (data URL)
1110+
let pageSetImageId: number | null = null;
1111+
if (button.parameters?.imageData && Buffer.isBuffer(button.parameters.imageData)) {
1112+
// Use existing image data buffer
1113+
const imageIdentifier: string =
1114+
(button.parameters.image_id as string) || `IMG_${buttonIdCounter}`;
1115+
let imageId = pageSetDataIdentifierMap.get(imageIdentifier);
1116+
if (!imageId) {
1117+
imageId = pageSetDataIdCounter++;
1118+
insertPageSetData.run(imageId, imageIdentifier, button.parameters.imageData, 1);
1119+
pageSetDataIdentifierMap.set(imageIdentifier, imageId);
1120+
} else {
1121+
incrementRefCount.run(imageId);
1122+
}
1123+
pageSetImageId = imageId;
1124+
} else if (
1125+
button.image &&
1126+
typeof button.image === 'string' &&
1127+
button.image.startsWith('data:image')
1128+
) {
1129+
// Convert data URL to buffer
1130+
try {
1131+
const matches = button.image.match(/^data:image\/(\w+);base64,(.+)$/);
1132+
if (matches && matches[2]) {
1133+
const imageData = Buffer.from(matches[2], 'base64');
1134+
const imageIdentifier: string =
1135+
(button.parameters?.image_id as string) || `IMG_${buttonIdCounter}`;
1136+
let imageId = pageSetDataIdentifierMap.get(imageIdentifier);
1137+
if (!imageId) {
1138+
imageId = pageSetDataIdCounter++;
1139+
insertPageSetData.run(imageId, imageIdentifier, imageData, 1);
1140+
pageSetDataIdentifierMap.set(imageIdentifier, imageId);
1141+
} else {
1142+
incrementRefCount.run(imageId);
1143+
}
1144+
pageSetImageId = imageId;
1145+
}
1146+
} catch (err) {
1147+
console.warn(
1148+
`[SnapProcessor] Failed to convert data URL to Buffer for button ${button.id}:`,
1149+
err
1150+
);
1151+
}
1152+
}
1153+
11091154
// Retry logic for SQLite operations
11101155
let retries = 3;
11111156
while (retries > 0) {
@@ -1116,8 +1161,8 @@ class SnapProcessor extends BaseProcessor {
11161161
button.message || button.label || '',
11171162
navigatePageId,
11181163
elementRefId,
1119-
null,
1120-
null,
1164+
null, // LibrarySymbolId - not used for embedded images
1165+
pageSetImageId, // PageSetImageId - references embedded image in PageSetData
11211166
messageRecordingId,
11221167
serializedMetadata,
11231168
useMessageRecording,

0 commit comments

Comments
 (0)