Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ interface ViewportDownloadFormNewProps {
onEnableViewport: (element: HTMLElement) => void;
onDisableViewport: () => void;
onDownload: (filename: string, fileType: string) => void;
onCopyToClipboard: () => void;
warningState: { enabled: boolean; value: string };
}

Expand All @@ -32,6 +33,7 @@ function ViewportDownloadFormNew({
onEnableViewport,
onDisableViewport,
onDownload,
onCopyToClipboard,
}: ViewportDownloadFormNewProps) {
const [viewportElement, setViewportElement] = useState<HTMLElement | null>(null);
const [showWarningMessage, setShowWarningMessage] = useState(true);
Expand Down Expand Up @@ -138,6 +140,18 @@ function ViewportDownloadFormNew({
<FooterAction.Secondary onClick={onClose}>
{t('Common:Cancel')}
</FooterAction.Secondary>
<FooterAction.Secondary
onClick={async () => {
try {
await onCopyToClipboard();
onClose();
} catch (error) {
console.error('Failed to copy to clipboard:', error);
}
}}
>
{t('Copy to Clipboard')}
</FooterAction.Secondary>
<FooterAction.Primary
onClick={() => {
onDownload(filename || DEFAULT_FILENAME, fileType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,18 +118,22 @@ const CornerstoneViewportDownloadForm = ({
const downloadViewport = renderingEngine.getViewport(VIEWPORT_ID);

try {
const properties = viewport.getProperties();
if (downloadViewport instanceof StackViewport) {
const imageId = viewport.getCurrentImageId();
const properties = viewport.getProperties();

await downloadViewport.setStack([imageId]);
downloadViewport.setProperties(properties);
} else if (downloadViewport instanceof BaseVolumeViewport) {
const volumeIds = viewport.getAllVolumeIds();
downloadViewport.setVolumes([{ volumeId: volumeIds[0] }]);
await downloadViewport.setVolumes([{ volumeId: volumeIds[0] }]);
}
downloadViewport.setProperties(properties);
const viewRef = viewport.getViewReference();
downloadViewport.setViewReference(viewRef);
downloadViewport.render();

if (segmentationRepresentations.length > 0) {
if (segmentationRepresentations?.length) {
segmentationRepresentations.forEach(segRepresentation => {
const { segmentationId, colorLUTIndex, type } = segRepresentation;
if (type === Enums.SegmentationRepresentations.Labelmap) {
Expand Down Expand Up @@ -230,6 +234,48 @@ const CornerstoneViewportDownloadForm = ({
downloadUrl(canvas.toDataURL(`image/${fileType}`, 1.0), { filename });
};

const handleCopyToClipboard = async () => {
const divForDownloadViewport = document.querySelector(
`div[data-viewport-uid="${VIEWPORT_ID}"]`
);

if (!divForDownloadViewport) {
console.debug('No viewport found for copy');
return;
}

try {
const canvas = await html2canvas(divForDownloadViewport as HTMLElement);

// Clipboard API only supports PNG format in most browsers
const blob = await new Promise<Blob>((resolve, reject) => {
canvas.toBlob(
blob => {
if (blob) {
resolve(blob);
} else {
reject(new Error('Failed to create blob from canvas'));
}
},
'image/png',
1.0
);
});

// Copy to clipboard using the Clipboard API
await navigator.clipboard.write([
new ClipboardItem({
'image/png': blob,
}),
]);

console.log('Image copied to clipboard successfully');
} catch (error) {
console.error('Failed to copy image to clipboard:', error);
throw error;
}
};

const ViewportDownloadFormNew = customizationService.getCustomization(
'ohif.captureViewportModal'
);
Expand All @@ -247,6 +293,7 @@ const CornerstoneViewportDownloadForm = ({
onEnableViewport={handleEnableViewport}
onDisableViewport={handleDisableViewport}
onDownload={handleDownload}
onCopyToClipboard={handleCopyToClipboard}
warningState={warningState}
/>
);
Expand Down