Search code examples
javafxopencv3.0fingerprintmat

How convert a raw image stored in a byte array to a rgb image with opencv and Java


i am working in the preview of a fingerprint scaner using id3Fingerprint sdk and OpenCV. If i just show the preview from the id3fingerprint sdk all is fine, but if i load it to a Mat object of OpenCV in order to draw some rectangles in the image then: 1.- The fingerprints are displayed in right form but the rectangles are displayed as lines or pixels in random x,y location. 2.- The rectangles are displayed in right form but the fingerprints are displayed "blured" (look the image attached).fingerprints are blured

I think, my problem is when i convert the raw grayscale image (a byte array from the id3fingerprint sdk) to a RGB or RGBA image.

private void showPreview2(FingerImage image){
    int height = 750;
    int width = 750;
    int currentWidth = 0;
    int currentHeight = 0;
    try {
        currentWidth = image.getWidth();
        currentHeight = image.getHeight();
    } catch (FingerException ex) {
        Logger.getLogger(CallingID3Example.class.getName()).log(Level.SEVERE, null, ex);
    }
    byte[] pixels = image.getPixels();
    Mat dest = new Mat(); 
    Mat source = new Mat(); 
    Mat source2 = null;
        source2 = new Mat(currentWidth, currentHeight, CvType.CV_8UC1);
        source2.put(0, 0, pixels);
        MatOfByte pix = new MatOfByte();
        Imgcodecs.imencode(".bmp", source2, pix);
        source2.put(0, 0, pix.toArray());

        Imgproc.cvtColor(source2, source, Imgproc.COLOR_GRAY2RGBA);
        try {
            int i=0;
            for(FingerImage finger : image.getSegments()){
                Scalar color;
                        color = new Scalar(0, 250,0);
                FingerBounds bound = image.getSegmentBounds()[i];
                Imgproc.rectangle(source, new Point(bound.topLeft.x, bound.topLeft.y),      new Point(bound.bottomRight.x, bound.bottomRight.y), color, 3);
                double[] pixelTest;
                pixelTest = source.get(bound.topLeft.x, bound.topLeft.y);
                i++;
            }
        } catch (FingerException ex) {
            Logger.getLogger(CallingID3Example.class.getName()).log(Level.SEVERE, null, ex);
        }
        gc = canvas.getGraphicsContext2D();

        WritableImage writableImage = loadImage(source);

        imageView.setImage(writableImage);

}

private WritableImage loadImage(Mat matrix) {
  // Encoding the image
  MatOfByte matOfByte = new MatOfByte();
    Imgcodecs.imencode(".bmp", matrix, matOfByte);
  // Storing the encoded Mat in a byte array
  byte[] byteArray = matOfByte.toArray();

  // Displaying the image
  InputStream in = new ByteArrayInputStream(byteArray);
  BufferedImage bufImage = null;
    try {
        bufImage = ImageIO.read(in);
    } catch (IOException ex) {
    }
  // Creating the Writable Image
  WritableImage writableImage = SwingFXUtils.toFXImage(bufImage, null);
  return writableImage;
}

Thanks for your answer.


Solution

  • You could try something like this:

        // You need to know width/height of the image
        int width = 0;
        int height = 0;
        byte[] imageSrc = null;//
    
    
        // Convert 8bit greyscale byte array to RGBA byte array.
        byte[] imageRGBA = new byte[imageSrc.length * 4];
        int i;
        for (i = 0; i < imageSrc.length; i++) {
            imageRGBA[i * 4] = imageRGBA[i * 4 + 1] = imageRGBA[i * 4 + 2] = ((byte) ~imageSrc[i]);
    
            // Invert the source bits
            imageRGBA[i * 4 + 3] = -1;// 0xff, that's the alpha.
        }
    
    
        // Convert RGBA byte array to PNG 
        int samplesPerPixel = 4;
        int[] bandOffsets = {0,1,2,3}; // RGBA order
    
        byte[] bgraPixelData = new byte[width * height * samplesPerPixel];
    
        DataBuffer buffer = new DataBufferByte(bgraPixelData, bgraPixelData.length);
        WritableRaster raster = Raster.createInterleavedRaster(buffer, width, height, samplesPerPixel * width, samplesPerPixel, bandOffsets, null);
    
        ColorModel colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
    
        BufferedImage image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
    
        System.out.println("image: " + image); // Should print: image: BufferedImage@<hash>: type = 0 ...
    
        ImageIO.write(image, "PNG", new File(path));
    

    Update

    To draw rectangle on image: BufferedImage image = ...

        Graphics2D graph = img.createGraphics();
        graph.setColor(Color.BLACK);
        graph.fill(new Rectangle(x, y, width, height));
        graph.dispose();
    
        ImageIO.write(image, "PNG", new File(path));