Skip to content

imwrite not fully completed when returned corrupting imagefiles #2342

@oliverunger

Description

@oliverunger

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:

Image

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?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions