All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bytedeco.javacv.Java2DFrameConverter Maven / Gradle / Ivy

There is a newer version: 1.5.11
Show newest version
/*
 * Copyright (C) 2015 Samuel Audet
 *
 * Licensed either under the Apache License, Version 2.0, or (at your option)
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation (subject to the "Classpath" exception),
 * either version 2, or any later version (collectively, the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *     http://www.gnu.org/licenses/
 *     http://www.gnu.org/software/classpath/license.html
 *
 * or as provided in the LICENSE.txt file that accompanied this code.
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.bytedeco.javacv;

import java.awt.Rectangle;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.ComponentSampleModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferDouble;
import java.awt.image.DataBufferFloat;
import java.awt.image.DataBufferInt;
import java.awt.image.DataBufferShort;
import java.awt.image.DataBufferUShort;
import java.awt.image.MultiPixelPackedSampleModel;
import java.awt.image.Raster;
import java.awt.image.SampleModel;
import java.awt.image.SinglePixelPackedSampleModel;
import java.awt.image.WritableRaster;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;

/**
 * A utility class to copy data between {@link Frame} and {@link BufferedImage}.
 * Since {@link BufferedImage} does not support NIO buffers, we cannot share
 * allocated memory with {@link Frame}.
 *
 * @author Samuel Audet
 */
public class Java2DFrameConverter extends FrameConverter {

    @Override public Frame convert(BufferedImage img) {
        return getFrame(img);
    }

    @Override public BufferedImage convert(Frame frame) {
        return getBufferedImage(frame);
    }

    public static BufferedImage cloneBufferedImage(BufferedImage bufferedImage) {
        if (bufferedImage == null) {
            return null;
        }
        BufferedImage bi = bufferedImage;
        int type = bi.getType();
        if (type == BufferedImage.TYPE_CUSTOM) {
            return new BufferedImage(bi.getColorModel(),
                    bi.copyData(null), bi.isAlphaPremultiplied(), null);
        } else {
            return new BufferedImage(bi.getWidth(), bi.getHeight(), type);
        }
    }

    public static final byte[]
            gamma22    = new byte[256],
            gamma22inv = new byte[256];
    static {
        for (int i = 0; i < 256; i++) {
            gamma22[i]    = (byte)Math.round(Math.pow(i/255.0,   2.2)*255.0);
            gamma22inv[i] = (byte)Math.round(Math.pow(i/255.0, 1/2.2)*255.0);
        }
    }
    public static int decodeGamma22(int value) {
        return gamma22[value & 0xFF] & 0xFF;
    }
    public static int encodeGamma22(int value) {
        return gamma22inv[value & 0xFF] & 0xFF;
    }
    public static void flipCopyWithGamma(ByteBuffer srcBuf, int srcStep,
            ByteBuffer dstBuf, int dstStep, boolean signed, double gamma, boolean flip, int channels) {
        assert srcBuf != dstBuf;
        int w = Math.min(srcStep, dstStep);
        int srcLine = srcBuf.position(), dstLine = dstBuf.position();
        byte[] buffer = new byte[channels];
        while (srcLine < srcBuf.capacity() && dstLine < dstBuf.capacity()) {
            if (flip) {
                srcBuf.position(srcBuf.capacity() - srcLine - srcStep);
            } else {
                srcBuf.position(srcLine);
            }
            dstBuf.position(dstLine);
            w = Math.min(Math.min(w, srcBuf.remaining()), dstBuf.remaining());
            if (signed) {
                if (channels > 1) {
                    for (int x = 0; x < w; x+=channels) {
                        for (int z = 0; z < channels; z++) {
                            int in = srcBuf.get();
                            byte out;
                            if (gamma == 1.0) {
                                out = (byte)in;
                            } else {
                                out = (byte)Math.round(Math.pow((double)in/Byte.MAX_VALUE, gamma)*Byte.MAX_VALUE);
                            }
                            buffer[z] = out;
                        }
                        for (int z = channels-1; z >= 0; z--) {
                            dstBuf.put(buffer[z]);
                        }
                    }
                } else {
                    for (int x = 0; x < w; x++) {
                        int in = srcBuf.get();
                        byte out;
                        if (gamma == 1.0) {
                            out = (byte)in;
                        } else {
                            out = (byte)Math.round(Math.pow((double)in/Byte.MAX_VALUE, gamma)*Byte.MAX_VALUE);
                        }
                        dstBuf.put(out);
                    }
                }
            } else {
                if (channels > 1) {
                    for (int x = 0; x < w; x+=channels) {
                        for (int z = 0; z < channels; z++) {
                            byte out;
                            int in = srcBuf.get() & 0xFF;
                            if (gamma == 1.0) {
                                out = (byte)in;
                            } else if (gamma == 2.2) {
                                out = gamma22[in];
                            } else if (gamma == 1/2.2) {
                                out = gamma22inv[in];
                            } else {
                                out = (byte)Math.round(Math.pow((double)in/0xFF, gamma)*0xFF);
                            }
                            buffer[z] = out;
                        }
                        for (int z = channels-1; z >= 0; z--) {
                            dstBuf.put(buffer[z]);
                        }
                    }
                } else {
                    for (int x = 0; x < w; x++) {
                        byte out;
                        int in = srcBuf.get() & 0xFF;
                        if (gamma == 1.0) {
                            out = (byte)in;
                        } else if (gamma == 2.2) {
                            out = gamma22[in];
                        } else if (gamma == 1/2.2) {
                            out = gamma22inv[in];
                        } else {
                            out = (byte)Math.round(Math.pow((double)in/0xFF, gamma)*0xFF);
                        }
                        dstBuf.put(out);
                    }
                }
            }
            srcLine += srcStep;
            dstLine += dstStep;
        }
    }
    public static void flipCopyWithGamma(ShortBuffer srcBuf, int srcStep,
            ShortBuffer dstBuf, int dstStep, boolean signed, double gamma, boolean flip, int channels) {
        assert srcBuf != dstBuf;
        int w = Math.min(srcStep, dstStep);
        int srcLine = srcBuf.position(), dstLine = dstBuf.position();
        short[] buffer = new short[channels];
        while (srcLine < srcBuf.capacity() && dstLine < dstBuf.capacity()) {
            if (flip) {
                srcBuf.position(srcBuf.capacity() - srcLine - srcStep);
            } else {
                srcBuf.position(srcLine);
            }
            dstBuf.position(dstLine);
            w = Math.min(Math.min(w, srcBuf.remaining()), dstBuf.remaining());
            if (signed) {
                if (channels > 1) {
                    for (int x = 0; x < w; x+=channels) {
                        for (int z = 0; z < channels; z++) {
                            int in = srcBuf.get();
                            short out;
                            if (gamma == 1.0) {
                                out = (short)in;
                            } else {
                                out = (short)Math.round(Math.pow((double)in/Short.MAX_VALUE, gamma)*Short.MAX_VALUE);
                            }
                            buffer[z] = out;
                        }
                        for (int z = channels-1; z >= 0; z--) {
                            dstBuf.put(buffer[z]);
                        }
                    }
                } else {
                    for (int x = 0; x < w; x++) {
                        int in = srcBuf.get();
                        short out;
                        if (gamma == 1.0) {
                            out = (short)in;
                        } else {
                            out = (short)Math.round(Math.pow((double)in/Short.MAX_VALUE, gamma)*Short.MAX_VALUE);
                        }
                        dstBuf.put(out);
                    }
                }
            } else {
                if (channels > 1) {
                    for (int x = 0; x < w; x+=channels) {
                        for (int z = 0; z < channels; z++) {
                            int in = srcBuf.get();
                            short out;
                            if (gamma == 1.0) {
                                out = (short)in;
                            } else {
                                out = (short)Math.round(Math.pow((double)in/0xFFFF, gamma)*0xFFFF);
                            }
                            buffer[z] = out;
                        }
                        for (int z = channels-1; z >= 0; z--) {
                            dstBuf.put(buffer[z]);
                        }
                    }
                } else {
                    for (int x = 0; x < w; x++) {
                        int in = srcBuf.get() & 0xFFFF;
                        short out;
                        if (gamma == 1.0) {
                            out = (short)in;
                        } else {
                            out = (short)Math.round(Math.pow((double)in/0xFFFF, gamma)*0xFFFF);
                        }
                        dstBuf.put(out);
                    }
                }
            }
            srcLine += srcStep;
            dstLine += dstStep;
        }
    }
    public static void flipCopyWithGamma(IntBuffer srcBuf, int srcStep,
            IntBuffer dstBuf, int dstStep, double gamma, boolean flip, int channels) {
        assert srcBuf != dstBuf;
        int w = Math.min(srcStep, dstStep);
        int srcLine = srcBuf.position(), dstLine = dstBuf.position();
        int[] buffer = new int[channels];
        while (srcLine < srcBuf.capacity() && dstLine < dstBuf.capacity()) {
            if (flip) {
                srcBuf.position(srcBuf.capacity() - srcLine - srcStep);
            } else {
                srcBuf.position(srcLine);
            }
            dstBuf.position(dstLine);
            w = Math.min(Math.min(w, srcBuf.remaining()), dstBuf.remaining());
            if (channels > 1) {
                for (int x = 0; x < w; x+=channels) {
                    for (int z = 0; z < channels; z++) {
                        int in = srcBuf.get();
                        int out;
                        if (gamma == 1.0) {
                            out = (int)in;
                        } else {
                            out = (int)Math.round(Math.pow((double)in/Integer.MAX_VALUE, gamma)*Integer.MAX_VALUE);
                        }
                        buffer[z] = out;
                    }
                    for (int z = channels-1; z >= 0; z--) {
                        dstBuf.put(buffer[z]);
                    }
                }
            } else {
                for (int x = 0; x < w; x++) {
                    int in = srcBuf.get();
                    int out;
                    if (gamma == 1.0) {
                        out = in;
                    } else {
                        out = (int)Math.round(Math.pow((double)in/Integer.MAX_VALUE, gamma)*Integer.MAX_VALUE);
                    }
                    dstBuf.put(out);
                }
            }
            srcLine += srcStep;
            dstLine += dstStep;
        }
    }
    public static void flipCopyWithGamma(FloatBuffer srcBuf, int srcStep,
            FloatBuffer dstBuf, int dstStep, double gamma, boolean flip, int channels) {
        assert srcBuf != dstBuf;
        int w = Math.min(srcStep, dstStep);
        int srcLine = srcBuf.position(), dstLine = dstBuf.position();
        float[] buffer = new float[channels];
        while (srcLine < srcBuf.capacity() && dstLine < dstBuf.capacity()) {
            if (flip) {
                srcBuf.position(srcBuf.capacity() - srcLine - srcStep);
            } else {
                srcBuf.position(srcLine);
            }
            dstBuf.position(dstLine);
            w = Math.min(Math.min(w, srcBuf.remaining()), dstBuf.remaining());
            if (channels > 1) {
                for (int x = 0; x < w; x+=channels) {
                    for (int z = 0; z < channels; z++) {
                        float in = srcBuf.get();
                        float out;
                        if (gamma == 1.0) {
                            out = in;
                        } else {
                            out = (float)Math.pow(in, gamma);
                        }
                        buffer[z] = out;
                    }
                    for (int z = channels-1; z >= 0; z--) {
                        dstBuf.put(buffer[z]);
                    }
                }
            } else {
                for (int x = 0; x < w; x++) {
                    float in = srcBuf.get();
                    float out;
                    if (gamma == 1.0) {
                        out = in;
                    } else {
                        out = (float)Math.pow(in, gamma);
                    }
                    dstBuf.put(out);
                }
            }
            srcLine += srcStep;
            dstLine += dstStep;
        }
    }
    public static void flipCopyWithGamma(DoubleBuffer srcBuf, int srcStep,
            DoubleBuffer dstBuf, int dstStep, double gamma, boolean flip, int channels) {
        assert srcBuf != dstBuf;
        int w = Math.min(srcStep, dstStep);
        int srcLine = srcBuf.position(), dstLine = dstBuf.position();
        double[] buffer = new double[channels];
        while (srcLine < srcBuf.capacity() && dstLine < dstBuf.capacity()) {
            if (flip) {
                srcBuf.position(srcBuf.capacity() - srcLine - srcStep);
            } else {
                srcBuf.position(srcLine);
            }
            dstBuf.position(dstLine);
            w = Math.min(Math.min(w, srcBuf.remaining()), dstBuf.remaining());
            if (channels > 1) {
                for (int x = 0; x < w; x+=channels) {
                    for (int z = 0; z < channels; z++) {
                        double in = srcBuf.get();
                        double out;
                        if (gamma == 1.0) {
                            out = in;
                        } else {
                            out = Math.pow(in, gamma);
                        }
                        buffer[z] = out;
                    }
                    for (int z = channels-1; z >= 0; z--) {
                        dstBuf.put(buffer[z]);
                    }
                }
            } else {
                for (int x = 0; x < w; x++) {
                    double in = srcBuf.get();
                    double out;
                    if (gamma == 1.0) {
                        out = in;
                    } else {
                        out = Math.pow(in, gamma);
                    }
                    dstBuf.put(out);
                }
            }
            srcLine += srcStep;
            dstLine += dstStep;
        }
    }

    public static void applyGamma(Frame frame, double gamma) {
        applyGamma(frame.image[0].position(0), frame.imageDepth, frame.imageStride, gamma);
    }
    public static void applyGamma(Buffer buffer, int depth, int stride, double gamma) {
        if (gamma == 1.0) {
            return;
        }
        switch (depth) {
            case Frame.DEPTH_UBYTE:
                flipCopyWithGamma(((ByteBuffer)buffer).asReadOnlyBuffer(), stride, (ByteBuffer)buffer, stride, false, gamma, false, 0);
                break;
            case Frame.DEPTH_BYTE:
                flipCopyWithGamma(((ByteBuffer)buffer).asReadOnlyBuffer(), stride, (ByteBuffer)buffer, stride, true, gamma, false, 0);
                break;
            case Frame.DEPTH_USHORT:
                flipCopyWithGamma(((ShortBuffer)buffer).asReadOnlyBuffer(), stride, (ShortBuffer)buffer, stride, false, gamma, false, 0);
                break;
            case Frame.DEPTH_SHORT:
                flipCopyWithGamma(((ShortBuffer)buffer).asReadOnlyBuffer(), stride, (ShortBuffer)buffer, stride, true, gamma, false, 0);
                break;
            case Frame.DEPTH_INT:
                flipCopyWithGamma(((IntBuffer)buffer).asReadOnlyBuffer(), stride, (IntBuffer)buffer, stride, gamma, false, 0);
                break;
            case Frame.DEPTH_FLOAT:
                flipCopyWithGamma(((FloatBuffer)buffer).asReadOnlyBuffer(), stride, (FloatBuffer)buffer, stride, gamma, false, 0);
                break;
            case Frame.DEPTH_DOUBLE:
                flipCopyWithGamma(((DoubleBuffer)buffer).asReadOnlyBuffer(), stride, (DoubleBuffer)buffer, stride, gamma, false, 0);
                break;
            default:
                assert false;
        }
    }

    public static void copy(Frame frame, BufferedImage bufferedImage) {
        copy(frame, bufferedImage, 1.0);
    }
    public static void copy(Frame frame, BufferedImage bufferedImage, double gamma) {
        copy(frame, bufferedImage, gamma, false, null);
    }
    public static void copy(Frame frame, BufferedImage bufferedImage, double gamma, boolean flipChannels, Rectangle roi) {
        Buffer in = frame.image[0].position(roi == null ? 0 : roi.y*frame.imageStride + roi.x*frame.imageChannels);
        SampleModel sm = bufferedImage.getSampleModel();
        Raster r       = bufferedImage.getRaster();
        DataBuffer out = r.getDataBuffer();
        int x = -r.getSampleModelTranslateX();
        int y = -r.getSampleModelTranslateY();
        int step = sm.getWidth()*sm.getNumBands();
        int channels = sm.getNumBands();
        if (sm instanceof ComponentSampleModel) {
            step = ((ComponentSampleModel)sm).getScanlineStride();
            channels = ((ComponentSampleModel)sm).getPixelStride();
        } else if (sm instanceof SinglePixelPackedSampleModel) {
            step = ((SinglePixelPackedSampleModel)sm).getScanlineStride();
            channels = 1;
        } else if (sm instanceof MultiPixelPackedSampleModel) {
            step = ((MultiPixelPackedSampleModel)sm).getScanlineStride();
            channels = ((MultiPixelPackedSampleModel)sm).getPixelBitStride()/8; // ??
        }
        int start = y*step + x*channels;

        if (out instanceof DataBufferByte) {
            byte[] a = ((DataBufferByte)out).getData();
            flipCopyWithGamma((ByteBuffer)in, frame.imageStride, ByteBuffer.wrap(a, start, a.length - start), step, false, gamma, false, flipChannels ? channels : 0);
        } else if (out instanceof DataBufferDouble) {
            double[] a = ((DataBufferDouble)out).getData();
            flipCopyWithGamma((DoubleBuffer)in, frame.imageStride, DoubleBuffer.wrap(a, start, a.length - start), step, gamma, false, flipChannels ? channels : 0);
        } else if (out instanceof DataBufferFloat) {
            float[] a = ((DataBufferFloat)out).getData();
            flipCopyWithGamma((FloatBuffer)in, frame.imageStride, FloatBuffer.wrap(a, start, a.length - start), step, gamma, false, flipChannels ? channels : 0);
        } else if (out instanceof DataBufferInt) {
            int[] a = ((DataBufferInt)out).getData();
            int stride = frame.imageStride;
            if (in instanceof ByteBuffer) {
                in = ((ByteBuffer)in).order(flipChannels ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN).asIntBuffer();
                stride /= 4;
            }
            flipCopyWithGamma((IntBuffer)in, stride, IntBuffer.wrap(a, start, a.length - start), step, gamma, false, flipChannels ? channels : 0);
        } else if (out instanceof DataBufferShort) {
            short[] a = ((DataBufferShort)out).getData();
            flipCopyWithGamma((ShortBuffer)in, frame.imageStride, ShortBuffer.wrap(a, start, a.length - start), step, true, gamma, false, flipChannels ? channels : 0);
        } else if (out instanceof DataBufferUShort) {
            short[] a = ((DataBufferUShort)out).getData();
            flipCopyWithGamma((ShortBuffer)in, frame.imageStride, ShortBuffer.wrap(a, start, a.length - start), step, false, gamma, false, flipChannels ? channels : 0);
        } else {
            assert false;
        }
    }

    public static void copy(BufferedImage image, Frame frame) {
        copy(image, frame, 1.0);
    }
    public static void copy(BufferedImage image, Frame frame, double gamma) {
        copy(image, frame, gamma, false, null);
    }
    public static void copy(BufferedImage image, Frame frame, double gamma, boolean flipChannels, Rectangle roi) {
        Buffer out = frame.image[0].position(roi == null ? 0 : roi.y*frame.imageStride + roi.x*frame.imageChannels);
        SampleModel sm = image.getSampleModel();
        Raster r       = image.getRaster();
        DataBuffer in  = r.getDataBuffer();
        int x = -r.getSampleModelTranslateX();
        int y = -r.getSampleModelTranslateY();
        int step = sm.getWidth()*sm.getNumBands();
        int channels = sm.getNumBands();
        if (sm instanceof ComponentSampleModel) {
            step = ((ComponentSampleModel)sm).getScanlineStride();
            channels = ((ComponentSampleModel)sm).getPixelStride();
        } else if (sm instanceof SinglePixelPackedSampleModel) {
            step = ((SinglePixelPackedSampleModel)sm).getScanlineStride();
            channels = 1;
        } else if (sm instanceof MultiPixelPackedSampleModel) {
            step = ((MultiPixelPackedSampleModel)sm).getScanlineStride();
            channels = ((MultiPixelPackedSampleModel)sm).getPixelBitStride()/8; // ??
        }
        int start = y*step + x*channels;

        if (in instanceof DataBufferByte) {
            byte[] a = ((DataBufferByte)in).getData();
            flipCopyWithGamma(ByteBuffer.wrap(a, start, a.length - start), step, (ByteBuffer)out, frame.imageStride, false, gamma, false, flipChannels ? channels : 0);
        } else if (in instanceof DataBufferDouble) {
            double[] a = ((DataBufferDouble)in).getData();
            flipCopyWithGamma(DoubleBuffer.wrap(a, start, a.length - start), step, (DoubleBuffer)out, frame.imageStride, gamma, false, flipChannels ? channels : 0);
        } else if (in instanceof DataBufferFloat) {
            float[] a = ((DataBufferFloat)in).getData();
            flipCopyWithGamma(FloatBuffer.wrap(a, start, a.length - start), step, (FloatBuffer)out, frame.imageStride, gamma, false, flipChannels ? channels : 0);
        } else if (in instanceof DataBufferInt) {
            int[] a = ((DataBufferInt)in).getData();
            int stride = frame.imageStride;
            if (out instanceof ByteBuffer) {
                out = ((ByteBuffer)out).order(flipChannels ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN).asIntBuffer();
                stride /= 4;
            }
            flipCopyWithGamma(IntBuffer.wrap(a, start, a.length - start), step, (IntBuffer)out, stride, gamma, false, flipChannels ? channels : 0);
        } else if (in instanceof DataBufferShort) {
            short[] a = ((DataBufferShort)in).getData();
            flipCopyWithGamma(ShortBuffer.wrap(a, start, a.length - start), step, (ShortBuffer)out, frame.imageStride, true, gamma, false, flipChannels ? channels : 0);
        } else if (in instanceof DataBufferUShort) {
            short[] a = ((DataBufferUShort)in).getData();
            flipCopyWithGamma(ShortBuffer.wrap(a, start, a.length - start), step, (ShortBuffer)out, frame.imageStride, false, gamma, false, flipChannels ? channels : 0);
        } else {
            assert false;
        }
    }

    protected BufferedImage bufferedImage = null;
    public static int getBufferedImageType(Frame frame) {
        // precanned BufferedImage types are confusing... in practice though,
        // they all use the sRGB color model when blitting:
        //     http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5051418
        // and we should use them because they are *A LOT* faster with Java 2D.
        // workaround: do gamma correction ourselves ("gamma" parameter)
        //             since we'll never use getRGB() and setRGB(), right?
        int type = BufferedImage.TYPE_CUSTOM;
        if (frame.imageChannels == 1) {
            if (frame.imageDepth == Frame.DEPTH_UBYTE || frame.imageDepth == Frame.DEPTH_BYTE) {
                type = BufferedImage.TYPE_BYTE_GRAY;
            } else if (frame.imageDepth == Frame.DEPTH_USHORT) {
                type = BufferedImage.TYPE_USHORT_GRAY;
            }
        } else if (frame.imageChannels == 3) {
            if (frame.imageDepth == Frame.DEPTH_UBYTE || frame.imageDepth == Frame.DEPTH_BYTE) {
                type = BufferedImage.TYPE_3BYTE_BGR;
            }
        } else if (frame.imageChannels == 4) {
            // The channels end up reversed of what we need for OpenCL.
            // We work around this in copyTo() and copyFrom() by
            // inversing the channels to let us use RGBA in our IplImage.
            if (frame.imageDepth == Frame.DEPTH_UBYTE || frame.imageDepth == Frame.DEPTH_BYTE) {
                type = BufferedImage.TYPE_4BYTE_ABGR;
            }
        }
        return type;
    }
    public BufferedImage getBufferedImage(Frame frame) {
        return getBufferedImage(frame, 1.0);
    }
    public BufferedImage getBufferedImage(Frame frame, double gamma) {
        return getBufferedImage(frame, gamma, false, null);
    }
    public BufferedImage getBufferedImage(Frame frame, double gamma, boolean flipChannels, ColorSpace cs) {
        if (frame == null || frame.image == null) {
            return null;
        }
        int type = getBufferedImageType(frame);

        if (bufferedImage == null || bufferedImage.getWidth() != frame.imageWidth
                || bufferedImage.getHeight() != frame.imageHeight || bufferedImage.getType() != type) {
            bufferedImage = type == BufferedImage.TYPE_CUSTOM || cs != null ? null
                    : new BufferedImage(frame.imageWidth, frame.imageHeight, type);
        }

        if (bufferedImage == null) {
            boolean alpha = false;
            int[] offsets = null;
            if (frame.imageChannels == 1) {
                alpha = false;
                if (cs == null) {
                    cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
                }
                offsets = new int[] {0};
            } else if (frame.imageChannels == 3) {
                alpha = false;
                if (cs == null) {
                    cs = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB);
                }
                // raster in "BGR" order like OpenCV..
                offsets = new int[] {2, 1, 0};
            } else if (frame.imageChannels == 4) {
                alpha = true;
                if (cs == null) {
                    cs = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB);
                }
                // raster in "RGBA" order for OpenCL.. alpha needs to be last
                offsets = new int[] {0, 1, 2, 3};
            } else {
                assert false;
            }

            ColorModel cm = null;
            WritableRaster wr = null;
            if (frame.imageDepth == Frame.DEPTH_UBYTE || frame.imageDepth == Frame.DEPTH_BYTE) {
                cm = new ComponentColorModel(cs, alpha,
                        false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
                wr = Raster.createWritableRaster(new ComponentSampleModel(
                        DataBuffer.TYPE_BYTE, frame.imageWidth, frame.imageHeight, frame.imageChannels, frame.imageStride,
                        offsets), null);
            } else if (frame.imageDepth == Frame.DEPTH_USHORT) {
                cm = new ComponentColorModel(cs, alpha,
                        false, Transparency.OPAQUE, DataBuffer.TYPE_USHORT);
                wr = Raster.createWritableRaster(new ComponentSampleModel(
                        DataBuffer.TYPE_USHORT, frame.imageWidth, frame.imageHeight, frame.imageChannels, frame.imageStride,
                        offsets), null);
            } else if (frame.imageDepth == Frame.DEPTH_SHORT) {
                cm = new ComponentColorModel(cs, alpha,
                        false, Transparency.OPAQUE, DataBuffer.TYPE_SHORT);
                wr = Raster.createWritableRaster(new ComponentSampleModel(
                        DataBuffer.TYPE_SHORT, frame.imageWidth, frame.imageHeight, frame.imageChannels, frame.imageStride,
                        offsets), null);
            } else if (frame.imageDepth == Frame.DEPTH_INT) {
                cm = new ComponentColorModel(cs, alpha,
                        false, Transparency.OPAQUE, DataBuffer.TYPE_INT);
                wr = Raster.createWritableRaster(new ComponentSampleModel(
                        DataBuffer.TYPE_INT, frame.imageWidth, frame.imageHeight, frame.imageChannels, frame.imageStride,
                        offsets), null);
            } else if (frame.imageDepth == Frame.DEPTH_FLOAT) {
                cm = new ComponentColorModel(cs, alpha,
                        false, Transparency.OPAQUE, DataBuffer.TYPE_FLOAT);
                wr = Raster.createWritableRaster(new ComponentSampleModel(
                        DataBuffer.TYPE_FLOAT, frame.imageWidth, frame.imageHeight, frame.imageChannels, frame.imageStride,
                        offsets), null);
            } else if (frame.imageDepth == Frame.DEPTH_DOUBLE) {
                cm = new ComponentColorModel(cs, alpha,
                        false, Transparency.OPAQUE, DataBuffer.TYPE_DOUBLE);
                wr = Raster.createWritableRaster(new ComponentSampleModel(
                        DataBuffer.TYPE_DOUBLE, frame.imageWidth, frame.imageHeight, frame.imageChannels, frame.imageStride,
                        offsets), null);
            } else {
                assert false;
            }

            bufferedImage = new BufferedImage(cm, wr, false, null);
        }

        if (bufferedImage != null) {
            copy(frame, bufferedImage, gamma, flipChannels, null);
        }

        return bufferedImage;
    }

    /**
     * Returns a Frame based on a BufferedImage.
     */
    public Frame getFrame(BufferedImage image) {
        return getFrame(image, 1.0);
    }
    /**
     * Returns a Frame based on a BufferedImage, and given gamma.
     */
    public Frame getFrame(BufferedImage image, double gamma) {
        return getFrame(image, gamma, false);
    }
    /**
     * Returns a Frame based on a BufferedImage, given gamma, and inverted channels flag.
     */
    public Frame getFrame(BufferedImage image, double gamma, boolean flipChannels) {
        if (image == null) {
            return null;
        }
        SampleModel sm = image.getSampleModel();
        int depth = 0, numChannels = sm.getNumBands();
        switch (image.getType()) {
            case BufferedImage.TYPE_INT_RGB:
            case BufferedImage.TYPE_INT_ARGB:
            case BufferedImage.TYPE_INT_ARGB_PRE:
            case BufferedImage.TYPE_INT_BGR:
                depth = Frame.DEPTH_UBYTE;
                numChannels = 4;
                break;
        }
        if (depth == 0 || numChannels == 0) {
            switch (sm.getDataType()) {
                case DataBuffer.TYPE_BYTE:   depth = Frame.DEPTH_UBYTE;  break;
                case DataBuffer.TYPE_USHORT: depth = Frame.DEPTH_USHORT; break;
                case DataBuffer.TYPE_SHORT:  depth = Frame.DEPTH_SHORT;  break;
                case DataBuffer.TYPE_INT:    depth = Frame.DEPTH_INT;    break;
                case DataBuffer.TYPE_FLOAT:  depth = Frame.DEPTH_FLOAT;  break;
                case DataBuffer.TYPE_DOUBLE: depth = Frame.DEPTH_DOUBLE; break;
                default: assert false;
            }
        }
        if (frame == null || frame.imageWidth != image.getWidth() || frame.imageHeight != image.getHeight()
                || frame.imageDepth != depth || frame.imageChannels != numChannels) {
            frame = new Frame(image.getWidth(), image.getHeight(), depth, numChannels);
        }
        copy(image, frame, gamma, flipChannels, null);
        return frame;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy