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

ome.codecs.MSVideoCodec Maven / Gradle / Ivy

The newest version!
/*
 * #%L
 * Image encoding and decoding routines.
 * %%
 * Copyright (C) 2005 - 2017 Open Microscopy Environment:
 *   - Board of Regents of the University of Wisconsin-Madison
 *   - Glencoe Software, Inc.
 *   - University of Dundee
 * %%
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * #L%
 */

package ome.codecs;

import java.io.IOException;

import loci.common.RandomAccessInputStream;
import ome.codecs.CodecException;
import ome.codecs.UnsupportedCompressionException;

/**
 * Methods for compressing and decompressing data using Microsoft Video 1.
 *
 * See http://wiki.multimedia.cx/index.php?title=Microsoft_Video_1 for an
 * excellent description of MSV1.
 */
public class MSVideoCodec extends BaseCodec {

  /* @see Codec#compress(byte[], CodecOptions) */
  @Override
  public byte[] compress(byte[] data, CodecOptions options)
    throws CodecException
  {
    throw new UnsupportedCompressionException(
      "MS Video 1 compression not supported.");
  }

  /**
   * The CodecOptions parameter should have the following fields set:
   *  {@link CodecOptions#width width}
   *  {@link CodecOptions#height height}
   *  {@link CodecOptions#bitsPerSample bitsPerSample}
   *  {@link CodecOptions#previousImage previousImage}
   *
   * @see Codec#decompress(RandomAccessInputStream, CodecOptions)
   */
  @Override
  public byte[] decompress(RandomAccessInputStream in, CodecOptions options)
    throws CodecException, IOException
  {
    if (in == null) 
      throw new IllegalArgumentException("No data to decompress.");
    if (options == null) options = CodecOptions.getDefaultOptions();

    in.order(true);

    int row = 0;
    int column = 0;

    int plane = options.width * options.height;

    byte[] bytes = new byte[plane];
    short[] shorts = new short[plane];

    while (true) {
      if (in.getFilePointer() >= in.length() || row >= options.width ||
        column >= options.height)
      {
        break;
      }
      short a = (short) (in.read() & 0xff);
      short b = (short) (in.read() & 0xff);
      if (a == 0 && b == 0 && in.getFilePointer() >= in.length()) break;
      if (b >= 0x84 && b < 0x88) {
        // indicates that we are skipping some blocks

        int skip = (b - 0x84) * 256 + a;
        for (int i=0; i= options.width) break;
                if (column + y >= options.height) break;
                int ndx = options.width*(column + y) + row + x;
                int oldNdx =
                  options.width*(options.height - 1 - y - column) + row + x;
                if (options.bitsPerSample == 8) {
                  bytes[ndx] = options.previousImage[oldNdx];
                }
                else {
                  byte red = options.previousImage[oldNdx];
                  byte green = options.previousImage[oldNdx + plane];
                  byte blue = options.previousImage[oldNdx + 2*plane];
                  shorts[ndx] = (short) (((blue & 0x1f) << 10) |
                    ((green & 0x1f) << 5) | (red & 0x1f));
                }
              }
            }
          }

          row += 4;
          if (row >= options.width) {
            row = 0;
            column += 4;
          }
        }
      }
      else if (b >= 0 && b < 0x80) {
        if (options.bitsPerSample == 8) {
          byte colorA = in.readByte();
          byte colorB = in.readByte();

          for (int y=0; y<4; y++) {
            for (int x=3; x>=0; x--) {
              int ndx = options.width*(column + (3 - y)) + row + x;
              short flag = y < 2 ? b : a;
              int shift = 4 - 4*(y % 2) + x;
              int cmp = 1 << shift;
              if ((flag & cmp) == cmp) bytes[ndx] = colorA;
              else bytes[ndx] = colorB;
            }
          }
        }
        else {
          short check1 = in.readShort();
          short check2 = in.readShort();

          if ((check1 & 0x8000) == 0x8000) {
            // 8 color encoding
            short q1a = check1;
            short q1b = check2;
            short q2a = in.readShort();
            short q2b = in.readShort();
            short q3a = in.readShort();
            short q3b = in.readShort();
            short q4a = in.readShort();
            short q4b = in.readShort();

            for (int y=0; y<4; y++) {
              for (int x=3; x>=0; x--) {
                int ndx = options.width*(column + (3 - y)) + row + x;

                short colorA =
                  x < 2 ? (y < 2 ? q3a : q1a) : (y < 2 ? q4a : q2a);
                short colorB =
                  x < 2 ? (y < 2 ? q3b : q1b) : (y < 2 ? q4b : q2b);

                short flag = y < 2 ? b : a;
                int shift = 4 - 4*(y % 2) + x;
                int cmp = 1 << shift;
                if (ndx < shorts.length) {
                  if ((flag & cmp) == cmp) shorts[ndx] = colorA;
                  else shorts[ndx] = colorB;
                }
              }
            }
          }
          else {
            // 2 color encoding

            short colorA = check1;
            short colorB = check2;

            for (int y=0; y<4; y++) {
              for (int x=3; x>=0; x--) {
                int ndx = options.width*(column + (3 - y)) + row + x;
                if (ndx >= shorts.length) break;
                short flag = y < 2 ? b : a;
                int shift = 4 - 4*(y % 2) + x;
                int cmp = 1 << shift;
                if ((flag & cmp) == cmp) shorts[ndx] = colorA;
                else shorts[ndx] = colorB;
              }
            }
          }
        }

        row += 4;
        if (row >= options.width) {
          row = 0;
          column += 4;
        }
      }
      else if (options.bitsPerSample == 8 && 0x90 < b) {
        byte[] colors = new byte[8];
        in.read(colors);

        for (int y=0; y<4; y++) {
          for (int x=3; x>=0; x--) {
            int ndx = options.width*(column + (3 - y)) + row + x;
            byte colorA = y < 2 ? (x < 2 ? colors[4] : colors[6]) :
              (x < 2 ? colors[0] : colors[2]);
            byte colorB = y < 2 ? (x < 2 ? colors[5] : colors[7]) :
              (x < 2 ? colors[1] : colors[3]);

            short flag = y < 2 ? b : a;
            int shift = 4 - 4*(y % 2) + x;
            int cmp = 1 << shift;
            if ((flag & cmp) == cmp) bytes[ndx] = colorA;
            else bytes[ndx] = colorB;
          }
        }

        row += 4;
        if (row >= options.width) {
          row = 0;
          column += 4;
        }
      }
      else {
        for (int y=0; y<4; y++) {
          for (int x=0; x<4; x++) {
            int ndx = options.width*(column + (3 - y)) + row + x;
            if (options.bitsPerSample == 8) {
              if (ndx < bytes.length) {
                bytes[ndx] = (byte) (a & 0xff);
              }
            }
            else {
              if (ndx < shorts.length) {
                shorts[ndx] = (short) (((b << 8) | a) & 0xffff);
              }
            }
          }
        }
        row += 4;
        if (row >= options.width) {
          row = 0;
          column += 4;
        }
      }
    }

    if (options.bitsPerSample == 8) {
      byte[] tmp = bytes;
      bytes = new byte[tmp.length];
      for (int y=0; y> 10);
        b[dest + plane] = (byte) ((shorts[off] & 0x3e0) >> 5);
        b[dest] = (byte) (shorts[off] & 0x1f);
      }
    }

    return b;
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy