|
|
|
@ -3,6 +3,7 @@ import styles from '@/components/FlowEditor/node/style/baseOther.module.less';
|
|
|
|
import { Handle, Position } from '@xyflow/react';
|
|
|
|
import { Handle, Position } from '@xyflow/react';
|
|
|
|
import { Image } from '@arco-design/web-react';
|
|
|
|
import { Image } from '@arco-design/web-react';
|
|
|
|
import { formatDataType } from '@/utils/common';
|
|
|
|
import { formatDataType } from '@/utils/common';
|
|
|
|
|
|
|
|
import UTIF from 'utif';
|
|
|
|
|
|
|
|
|
|
|
|
interface NodeContentData {
|
|
|
|
interface NodeContentData {
|
|
|
|
parameters?: {
|
|
|
|
parameters?: {
|
|
|
|
@ -120,6 +121,44 @@ const getImageBlobType = (url: string, blobType: string) => {
|
|
|
|
return blobType || 'application/octet-stream';
|
|
|
|
return blobType || 'application/octet-stream';
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const isTiffImage = (url: string, blobType: string) => {
|
|
|
|
|
|
|
|
const imageType = getImageBlobType(url, blobType).toLowerCase();
|
|
|
|
|
|
|
|
const cleanUrl = url.split('?')[0].toLowerCase();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
|
|
imageType === 'image/tiff' ||
|
|
|
|
|
|
|
|
cleanUrl.endsWith('.tif') ||
|
|
|
|
|
|
|
|
cleanUrl.endsWith('.tiff')
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const createTiffPreviewUrl = async (url: string, blob: Blob) => {
|
|
|
|
|
|
|
|
const buffer = await blob.arrayBuffer();
|
|
|
|
|
|
|
|
const ifds = UTIF.decode(buffer);
|
|
|
|
|
|
|
|
const firstImage = ifds[0];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!firstImage) {
|
|
|
|
|
|
|
|
throw new Error('empty tiff image');
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
UTIF.decodeImage(buffer, firstImage);
|
|
|
|
|
|
|
|
const rgba = UTIF.toRGBA8(firstImage);
|
|
|
|
|
|
|
|
const canvas = document.createElement('canvas');
|
|
|
|
|
|
|
|
canvas.width = firstImage.width;
|
|
|
|
|
|
|
|
canvas.height = firstImage.height;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const context = canvas.getContext('2d');
|
|
|
|
|
|
|
|
if (!context) {
|
|
|
|
|
|
|
|
throw new Error('canvas context unavailable');
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const imageData = context.createImageData(firstImage.width, firstImage.height);
|
|
|
|
|
|
|
|
imageData.data.set(rgba);
|
|
|
|
|
|
|
|
context.putImageData(imageData, 0, 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return canvas.toDataURL('image/png');
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const NodeContent = ({ data, imageUrl = '' }: { data: NodeContentData; imageUrl?: string }) => {
|
|
|
|
const NodeContent = ({ data, imageUrl = '' }: { data: NodeContentData; imageUrl?: string }) => {
|
|
|
|
const [previewUrl, setPreviewUrl] = useState('');
|
|
|
|
const [previewUrl, setPreviewUrl] = useState('');
|
|
|
|
const [imageLoadError, setImageLoadError] = useState(false);
|
|
|
|
const [imageLoadError, setImageLoadError] = useState(false);
|
|
|
|
@ -152,6 +191,14 @@ const NodeContent = ({ data, imageUrl = '' }: { data: NodeContentData; imageUrl?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const blob = await response.blob();
|
|
|
|
const blob = await response.blob();
|
|
|
|
|
|
|
|
if (isTiffImage(imageUrl, blob.type)) {
|
|
|
|
|
|
|
|
const tiffPreviewUrl = await createTiffPreviewUrl(imageUrl, blob);
|
|
|
|
|
|
|
|
if (!canceled) {
|
|
|
|
|
|
|
|
setPreviewUrl(tiffPreviewUrl);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const typedBlob = new Blob([blob], {
|
|
|
|
const typedBlob = new Blob([blob], {
|
|
|
|
type: getImageBlobType(imageUrl, blob.type),
|
|
|
|
type: getImageBlobType(imageUrl, blob.type),
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|