[Glitch] Remove animation detection in favour of never cropping GIFs
Port 57c5d1c8dd50a02bc3a11af30b29fa8163fcdb73 to glitch-soc Signed-off-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
parent
0e56e899a0
commit
f135486200
@ -65,16 +65,23 @@ export const ImageUploadModal: FC<
|
|||||||
|
|
||||||
const handleFile = useCallback((file: File) => {
|
const handleFile = useCallback((file: File) => {
|
||||||
try {
|
try {
|
||||||
parseImageFile(file, (result, isAnimated) => {
|
// If the image is animated, skip cropping and go straight to alt text.
|
||||||
if (isAnimated) {
|
if (file.type === 'image/gif') {
|
||||||
// If the image is animated, skip cropping and go straight to alt text.
|
setImageBlob(file);
|
||||||
setImageBlob(file);
|
setStep('alt');
|
||||||
setStep('alt');
|
return;
|
||||||
} else {
|
}
|
||||||
setImageSrc(result);
|
|
||||||
setStep('crop');
|
const reader = new FileReader();
|
||||||
|
reader.onload = () => {
|
||||||
|
const dataUri = reader.result;
|
||||||
|
if (typeof dataUri !== 'string') {
|
||||||
|
throw new Error('Expected a string');
|
||||||
}
|
}
|
||||||
});
|
setImageSrc(dataUri);
|
||||||
|
setStep('crop');
|
||||||
|
};
|
||||||
|
reader.readAsDataURL(file);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn('Error with image parsing:', error);
|
console.warn('Error with image parsing:', error);
|
||||||
setStep('select');
|
setStep('select');
|
||||||
@ -408,54 +415,6 @@ const StepAlt: FC<{
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses an image file and determines if it's an animated GIF and returns a data URI for cropping.
|
|
||||||
* Based on https://gist.github.com/zakirt/faa4a58cec5a7505b10e3686a226f285.
|
|
||||||
*/
|
|
||||||
function parseImageFile(
|
|
||||||
file: File,
|
|
||||||
cb: (buffer: string, isAnimated: boolean) => void,
|
|
||||||
): void {
|
|
||||||
const reader = new FileReader();
|
|
||||||
reader.onload = () => {
|
|
||||||
const buffer = reader.result;
|
|
||||||
if (!(buffer instanceof ArrayBuffer)) {
|
|
||||||
throw new Error('Expected an ArrayBuffer');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert the ArrayBuffer to a base64 data URI.
|
|
||||||
const bytes = new Uint8Array(buffer);
|
|
||||||
const base64 = btoa(String.fromCharCode(...bytes));
|
|
||||||
const dataUri = `data:${file.type};base64,${base64}`;
|
|
||||||
|
|
||||||
// If the file type is not a GIF, then it's not animated as we don't support animated WebP or PNG.
|
|
||||||
if (file.type !== 'image/gif') {
|
|
||||||
cb(dataUri, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
const view = new DataView(buffer, 10); // Start from the last 4 bytes of the Logical Screen Descriptor.
|
|
||||||
let offset = 3;
|
|
||||||
|
|
||||||
// Check the first bit for the global color table flag.
|
|
||||||
const globalColorTable = view.getInt8(0);
|
|
||||||
if (globalColorTable & 0x08) {
|
|
||||||
// Grab last three bits to calculate the global color table size, and skip it.
|
|
||||||
offset += 3 * Math.pow(2, (globalColorTable & 0x7) + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check Graphics Control Extension and Graphics Control Label to access animated data.
|
|
||||||
let delayTime = 0;
|
|
||||||
if (view.getUint8(offset) & 0x21 && view.getUint8(offset + 1) & 0xf9) {
|
|
||||||
// Skip to the delay time, which is stored in the next two bytes.
|
|
||||||
delayTime = view.getUint16(offset + 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there is a delay time, the GIF is animated.
|
|
||||||
cb(dataUri, delayTime > 0);
|
|
||||||
};
|
|
||||||
reader.readAsArrayBuffer(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function calculateCroppedImage(
|
async function calculateCroppedImage(
|
||||||
imageSrc: string,
|
imageSrc: string,
|
||||||
crop: Area,
|
crop: Area,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user