Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * @(#)DIBCodec.java 
   *
   * Copyright © 2011-2012 Werner Randelshofer, Goldau, Switzerland.
   * All rights reserved.
   *
   * You may not use, copy or modify this file, except in compliance with the
   * license agreement you entered into with Werner Randelshofer.
   * For details see accompanying license terms.
  */
 package org.monte.media.avi;
 
 import static org.monte.media.VideoFormatKeys.*;
 import static org.monte.media.BufferFlag.*;

DIBCodec encodes a BufferedImage as a Microsoft Device Independent Bitmap (DIB) into a byte array.

The DIB codec only works with the AVI file format. Other file formats, such as QuickTime, use a different encoding for uncompressed video.

This codec currently only supports encoding from a BufferedImage into the file format. Decoding support may be added in the future.

This codec does not encode the color palette of an image. This must be done separately.

The pixels of a frame are written row by row from bottom to top and from the left to the right. 24-bit pixels are encoded as BGR.

Supported input formats:

    Format with BufferedImage.class, any width, any height, depth=4.
Supported output formats:
    Format with byte[].class, same width and height as input format, depth=4.

Author(s):
Werner Randelshofer
Version:
$Id: DIBCodec.java 299 2013-01-03 07:40:18Z werner $
 
 public class DIBCodec extends AbstractVideoCodec {
 
     public DIBCodec() {
         super(new Format[]{
                     new Format(.,
                     true), //
                     new Format(.,
                     byte[].class,
                     true, 4), //
                     new Format(.,
                     byte[].class,
                     true, 8), //
                     new Format(.,
                     byte[].class,
                     true, 24), //
                 },
                 new Format[]{
                     new Format(.,
                     true), //
                     new Format(.,
                     byte[].class,
                     true, 4), //
                     new Format(.,
                     byte[].class,
                     true, 8), //
                     new Format(.,
                     byte[].class,
                     true, 24), //
                 });
     }
 
     @Override
     public int process(Buffer inBuffer out) {
         if (.get() == ) {
             return decode(inout);
         } else {
             return encode(inout);
         }
     }
 
     public int decode(Buffer inBuffer out) {
         out.setMetaTo(in);
         out.format = ;
        if (in.isFlag()) {
            return ;
        }
        out.sampleCount = 1;
        BufferedImage img = null;
        int imgType;
        switch (.get()) {
            case 4:
                imgType = .;
                break;
            case 8:
                imgType = .;
                break;
            case 24:
                imgType = .;
                break;
            default:
                imgType = .;
                break;
        }
        if (out.data instanceof BufferedImage) {
            img = (BufferedImageout.data;
            // Fixme: Handle sub-image
            if (img.getWidth() != .get()
                    || img.getHeight() != .get()
                    || img.getType() != imgType) {
                img = null;
            }
        }
        if (img == null) {
            img = new BufferedImage(.get(), .get(), imgType);
        }
        out.data = img;
        switch (.get()) {
            case 4:
                readKey4((byte[]) in.datain.offsetin.lengthimg);
                break;
            case 8:
                readKey8((byte[]) in.datain.offsetin.lengthimg);
                break;
            case 24:
            default:
                readKey24((int[]) in.datain.offsetin.lengthimg);
                break;
        }
        return ;
    }
    public int encode(Buffer inBuffer out) {
        out.setMetaTo(in);
        out.format = ;
        if (in.isFlag()) {
            return ;
        }
        SeekableByteArrayOutputStream tmp;
        if (out.data instanceof byte[]) {
            tmp = new SeekableByteArrayOutputStream((byte[]) out.data);
        } else {
            tmp = new SeekableByteArrayOutputStream();
        }
        // Handle sub-image
        // FIXME - Scanline stride must be a multiple of four.
        Rectangle r;
        int scanlineStride;
        if (in.data instanceof BufferedImage) {
            BufferedImage image = (BufferedImagein.data;
            WritableRaster raster = image.getRaster();
            scanlineStride = raster.getSampleModel().getWidth();
            r = raster.getBounds();
            r.x -= raster.getSampleModelTranslateX();
            r.y -= raster.getSampleModelTranslateY();
            out.header = image.getColorModel();
        } else {
            r = new Rectangle(0, 0, .get(), .get());
            scanlineStride = .get();
            out.header = null;
        }
        try {
            switch (.get()) {
                case 4: {
                    byte[] pixels = getIndexed8(in);
                    if (pixels == null) {
                        out.setFlag();
                        return ;
                    }
                    writeKey4(tmppixelsr.widthr.heightr.x + r.y * scanlineStridescanlineStride);
                    break;
                }
                case 8: {
                    byte[] pixels = getIndexed8(in);
                    if (pixels == null) {
                        out.setFlag();
                        return ;
                    }
                    writeKey8(tmppixelsr.widthr.heightr.x + r.y * scanlineStridescanlineStride);
                    break;
                }
                case 24: {
                    int[] pixels = getRGB24(in);
                    if (pixels == null) {
                        out.setFlag();
                        return ;
                    }
                    writeKey24(tmppixelsr.widthr.heightr.x + r.y * scanlineStridescanlineStride);
                    break;
                }
                default:
                    out.setFlag();
                    return ;
            }
            out.setFlag();
            out.data = tmp.getBuffer();
            out.sampleCount = 1;
            out.offset = 0;
            out.length = (inttmp.getStreamPosition();
            return ;
        } catch (IOException ex) {
            ex.printStackTrace();
            out.setFlag();
            return ;
        }
    }
    public void readKey4(byte[] inint offsetint lengthBufferedImage img) {
        DataBufferByte buf = (DataBufferByteimg.getRaster().getDataBuffer();
        WritableRaster raster = img.getRaster();
        int scanlineStride = raster.getSampleModel().getWidth();
        Rectangle r = raster.getBounds();
        r.x -= raster.getSampleModelTranslateX();
        r.y -= raster.getSampleModelTranslateY();
        
        throw new UnsupportedOperationException("readKey4 not yet implemented");
    }
    public void readKey8(byte[] inint offsetint lengthBufferedImage img) {
        DataBufferByte buf = (DataBufferByteimg.getRaster().getDataBuffer();
        WritableRaster raster = img.getRaster();
        int scanlineStride = raster.getSampleModel().getWidth();
        Rectangle r = raster.getBounds();
        r.x -= raster.getSampleModelTranslateX();
        r.y -= raster.getSampleModelTranslateY();
        
        int h=img.getHeight();
        int w=img.getWidth();
        int i=offset;
        int j=r.x+r.y*scanlineStride+(h-1)*scanlineStride;
        byte[] out=buf.getData();
        for (int y=0;y<h;y++) {
            System.arraycopy(in,i,out,j,w);
            i+=w;
            j-=scanlineStride;
        }
    }
    public void readKey24(int[] inint offsetint lengthBufferedImage img) {
        DataBufferInt buf = (DataBufferIntimg.getRaster().getDataBuffer();
        WritableRaster raster = img.getRaster();
        int scanlineStride = raster.getSampleModel().getWidth();
        Rectangle r = raster.getBounds();
        r.x -= raster.getSampleModelTranslateX();
        r.y -= raster.getSampleModelTranslateY();
        
        int h=img.getHeight();
        int w=img.getWidth();
        int i=offset;
        int j=r.x+r.y*scanlineStride+(h-1)*scanlineStride;
        int[] out=buf.getData();
        for (int y=0;y<h;y++) {
            System.arraycopy(in,i,out,j,w);
            i+=w;
            j-=scanlineStride;
        }
    }

    
Encodes a 4-bit key frame.

Parameters:
out The output stream.
pixels The image data.
offset The offset to the first pixel in the data array.
width The width of the image in data elements.
scanlineStride The number to append to offset to get to the next scanline.
    public void writeKey4(OutputStream outbyte[] pixelsint widthint heightint offsetint scanlineStride)
            throws IOException {
        byte[] bytes = new byte[width];
        for (int y = (height - 1) * scanlineStridey >= 0; y -= scanlineStride) { // Upside down
            for (int x = offsetxx = 0, n = offset + widthx < nx += 2, ++xx) {
                bytes[xx] = (byte) (((pixels[y + x] & 0xf) << 4) | (pixels[y + x + 1] & 0xf));
            }
            out.write(bytes);
        }
    }

    
Encodes an 8-bit key frame.

Parameters:
out The output stream.
pixels The image data.
offset The offset to the first pixel in the data array.
width The width of the image in data elements.
scanlineStride The number to append to offset to get to the next scanline.
    public void writeKey8(OutputStream outbyte[] pixelsint widthint heightint offsetint scanlineStride)
            throws IOException {
        for (int y = (height - 1) * scanlineStridey >= 0; y -= scanlineStride) { // Upside down
            out.write(pixelsy + offsetwidth);
        }
    }

    
Encodes a 24-bit key frame.

Parameters:
out The output stream.
pixels The image data.
offset The offset to the first pixel in the data array.
width The width of the image in data elements.
scanlineStride The number to append to offset to get to the next scanline.
    public void writeKey24(OutputStream outint[] pixelsint widthint heightint offsetint scanlineStride)
            throws IOException {
        int w3 = width * 3;
        byte[] bytes = new byte[w3]; // holds a scanline of raw image data with 3 channels of 8 bit data
        for (int xy = (height - 1) * scanlineStride + offsetxy >= offsetxy -= scanlineStride) { // Upside down
            for (int x = 0, xp = 0; x < w3x += 3, ++xp) {
                int p = pixels[xy + xp];
                bytes[x] = (byte) (p); // Blue
                bytes[x + 1] = (byte) (p >> 8); // Green
                bytes[x + 2] = (byte) (p >> 16); // Red
            }
            out.write(bytes);
        }
    }
New to GrepCode? Check out our FAQ X