question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

IndexSizeError: Index or size is negative or greater than the allowed amount (Firefox)

See original GitHub issue

Works just fine on Chrome but in Firefox I got this error.

import React, { useState, useEffect, useCallback, useRef } from 'react';
import ReactCrop from 'react-image-crop';
import 'react-image-crop/dist/ReactCrop.css';
import { Typography } from '@material-ui/core';
import { Row, Col } from 'reactstrap';
import Modal from 'react-bootstrap/Modal';

function getResizedCanvas(canvas, newWidth, newHeight) {
    const tmpCanvas = document.createElement('canvas');
    tmpCanvas.width = newWidth;
    tmpCanvas.height = newHeight;

    const ctx = tmpCanvas.getContext('2d');

    ctx.drawImage(
        canvas,
        0,
        0,
        canvas.width,
        canvas.height,
        0,
        0,
        newWidth,
        newHeight
    );

    return tmpCanvas;
}

function generateDownload(previewCanvas, crop) {
    if (!crop || !previewCanvas) {
        return;
    }

    const dpr = window.devicePixelRatio || 1;
    const canvas =
        dpr !== 1
            ? getResizedCanvas(previewCanvas, crop.width, crop.height)
            : previewCanvas;

    canvas.toBlob(
        (blob) => {
            const previewUrl = window.URL.createObjectURL(blob);

            const anchor = document.createElement('a');
            anchor.download = 'cropPreview.png';
            anchor.href = URL.createObjectURL(blob);
            anchor.click();

            window.URL.revokeObjectURL(previewUrl);
        },
        'image/png',
        1
    );
}

export default function CropImageModal(props) {
    const { src, setImage, setImagePreview, isOpen, setIsOpen } = props;
    // const [upImg, setUpImg] = useState();
    const imgRef = useRef(null);
    const previewCanvasRef = useRef(null);
    const [previewUrl, setPreviewUrl] = useState(null);
    const [crop, setCrop] = useState({ aspect: 1 / 1 });
    const [completedCrop, setCompletedCrop] = useState(null);

    const handleCloseModal = () => {
        setIsOpen(false);
    };

    useEffect(() => {
        function createImageURL() {
            if (src) setPreviewUrl(URL?.createObjectURL(src));
            console.log(previewUrl);
        }
        createImageURL();
    }, [src]);

    const onLoad = useCallback((img) => {
        imgRef.current = img;
    }, []);

    useEffect(() => {
        if (!completedCrop || !previewCanvasRef.current || !imgRef.current) {
            return;
        }

        const image = imgRef.current;
        const canvas = previewCanvasRef.current;
        const crop = completedCrop;
        const dpr = window.devicePixelRatio || 1;

        const scaleX = image.naturalWidth / image.width;
        const scaleY = image.naturalHeight / image.height;
        const ctx = canvas.getContext('2d');

        ctx.drawImage(
            image,
            crop.x * scaleX,
            crop.y * scaleY,
            crop.width * scaleX,
            crop.height * scaleY,
            0,
            0,
            crop.width * dpr,
            crop.height * dpr
        );
    }, [completedCrop]);

    return (
        <Modal
            show={isOpen}
            onHide={handleCloseModal}
            size="md"
            aria-labelledby="contained-modal-title-vcenter"
        >
            <Modal.Body>
                <Row
                    style={{
                        textAlign: 'center',
                        justifyContent: 'center',
                    }}
                >
                    <ReactCrop
                        src={previewUrl}
                        onImageLoaded={onLoad}
                        crop={crop}
                        onChange={(c) => setCrop(c)}
                        onComplete={(c) => setCompletedCrop(c)}
                    />
                    <div>
                        <canvas
                            ref={previewCanvasRef}
                            style={{
                                width: completedCrop?.width ?? 0,
                                height: completedCrop?.height ?? 0,
                            }}
                        />
                    </div>
                    <button
                        type="button"
                        disabled={
                            !completedCrop?.width || !completedCrop?.height
                        }
                        onClick={() =>
                            generateDownload(
                                previewCanvasRef.current,
                                completedCrop
                            )
                        }
                    >
                        Download cropped image
                    </button>
                </Row>
            </Modal.Body>
        </Modal>
    );
}

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:9 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
JanderSilvcommented, Jun 15, 2020

Problem solved, you are awesome. Thanks for the attention again!!

1reaction
DominicTobiascommented, Jun 15, 2020

Hi, you’re right, this happens when trying to draw something on to a 0x0 canvas, well the crop values are also zero except for the X+Y but Firefox doesn’t like it.

Fixed in the demo, you can fix it by wrapping the drawing function in a conditional:

if (canvas.width && canvas.height) {
      ctx.drawImage(
        image,
        crop.x * scaleX,
        crop.y * scaleY,
        crop.width * scaleX,
        crop.height * scaleY,
        0,
        0,
        crop.width * dpr,
        crop.height * dpr
      );
    }
Read more comments on GitHub >

github_iconTop Results From Across the Web

Canvas - IndexSizeError: Index or size is negative or greater ...
If width and/or height is 0, it will result in: IndexSizeError: Index or size is negative or greater than the allowed amount. In...
Read more >
Error "IndexSizeError: Index or size is negative or greater than ...
Error "IndexSizeError: Index or size is negative or greater than the allowed amount" when using the animation inspector.
Read more >
IndexSizeError: DOM Exception 1: Index or size was negative ...
I have a music application, The music streaming work fine in Firefox and chrome ... 1: Index or size was negative, or greater...
Read more >
[Javascript] IndexSizeError: Index or size is negative or greater ...
"IndexSizeError: Index or size is negative or greater than the allowed amount" ... But for some reason, it doesn't work in FireFox.
Read more >
IndexSizeError: Index or size is negative or greater ... - GitHub
IndexSizeError : Index or size is negative or greater than the allowed amount #1245 ... Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0 ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found