bytedeco/javacv

imwrite not fully completed when returned corrupting imagefiles

Open

#2342 opened on Jul 16, 2025

View on GitHub
 (15 comments) (0 reactions) (0 assignees)Java (6,985 stars) (1,583 forks)batch import
help wantedquestion

Description

The following code creates corrupt imagefiles (one in a few thousands). When trying to read the file 1 hour later we see an error. The location to write to is a remote file server.

static boolean writeFile(final byte[] imageAsBytes, final String label, final Path imageFilePath) {
        try (final BytePointer imageBytesInNativeMemoryPointer = new BytePointer(imageAsBytes); // Copies the bytes of the image from the heap (because 'bytes' is an array) to the native memory and creates a pointer.
             final Mat imageBytesInNativeMemoryMatrix = new Mat(imageBytesInNativeMemoryPointer, false); // Creates a matrix representation for the given pointer. Just a wrapper, that does not copy anything.
             final Mat imageDecodedInNativeMemoryMatrix = imdecode(imageBytesInNativeMemoryMatrix, CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR); // Decodes the image to a new matrix in native memory with real pixel values.
             final Point textBottomLeftCorner = new Point(10, 55);
             final Scalar textWhiteColor = new Scalar(255, 255, 255, 255)
        ) {
            // Add image description in the upper left corner
            putText(imageDecodedInNativeMemoryMatrix, label, textBottomLeftCorner, FONT_HERSHEY_SIMPLEX, 0.7, textWhiteColor, 2, LINE_AA, false);
            FilesAndFoldersUtil.createFolder(imageFilePath.getParent());
            // Stores the given image matrix from native memory to the given file
            final boolean writeSuccess = imwrite(imageFilePath.toString(), imageDecodedInNativeMemoryMatrix);
            final boolean fileCreated = Files.exists(imageFilePath);
            if (!writeSuccess || !fileCreated) {
                throw new IOException("Could not write image to file " + imageFilePath + ". Was a file created? " + fileCreated + ". File size " + (fileCreated ? Files.size(imageFilePath) : -1) + ". Matrix size: [width= " + imageDecodedInNativeMemoryMatrix.size().width() + "|height=" + imageBytesInNativeMemoryMatrix.size().height() + "]");
            }
        } catch (final Exception ex) {
            LOG.warn("Exception while writing image to file", ex);
            return false;
        }
        return true;
    }

if (!writeSuccess || !fileCreated) : This condition was false so imwrite says its finished by returning true and the file exists. An example of a corrupt imagefile:

Error when reading:

javax.imageio.IIOException: Error reading PNG image data
at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.readImage(PNGImageReader.java:1528)
at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.read(PNGImageReader.java:1845)
at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1466)
at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1315)
...
Caused by: javax.imageio.IIOException: Unknown row filter type (= 30)!
at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.decodePass(PNGImageReader.java:1267)
at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.decodeImage(PNGImageReader.java:1379)
at java.desktop/com.sun.imageio.plugins.png.PNGImageReader.readImage(PNGImageReader.java:1519)

How to prevent this? Write to memory first and than send it over the line? Add a thread sleep after imwrite()? Add a release() or something?

Contributor guide