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

org.monte.media.iff.MC68000OutputStream Maven / Gradle / Ivy

There is a newer version: 1.1
Show newest version
/*
 * @(#)MC68000OutputStream.java  1.1  2010-10-26
 *
 * Copyright (c) 2006-2010 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.iff;

import java.io.*;
import java.util.Arrays;

/**
 * MC68000OutputStream.
 *
 * @author Werner Randelshofer
 * @version 1.1 2010-12-26 Added method writeType().
 * 
1.0.1 2008-08-03 The ByteRun1 encoder incorrectly added 1 to its * index when flushing the literal run. *
1.0 December 25, 2006 Created. */ public class MC68000OutputStream extends FilterOutputStream { /** * The number of bytes written to the data output stream so far. * If this counter overflows, it will be wrapped to Integer.MAX_VALUE. */ protected long written; /** Creates a new instance. */ public MC68000OutputStream(OutputStream out) { super(out); } public void writeLONG(int v) throws IOException { out.write((v >>> 24) & 0xFF); out.write((v >>> 16) & 0xFF); out.write((v >>> 8) & 0xFF); out.write((v >>> 0) & 0xFF); incCount(4); } public void writeULONG(long v) throws IOException { out.write((int) ((v >>> 24) & 0xFF)); out.write((int) ((v >>> 16) & 0xFF)); out.write((int) ((v >>> 8) & 0xFF)); out.write((int) ((v >>> 0) & 0xFF)); incCount(4); } public void writeWORD(int v) throws IOException { out.write((v >>> 8) & 0xFF); out.write((v >>> 0) & 0xFF); incCount(2); } public void writeUWORD(int v) throws IOException { out.write((v >>> 8) & 0xFF); out.write((v >>> 0) & 0xFF); incCount(2); } public void writeUBYTE(int v) throws IOException { out.write((v >>> 0) & 0xFF); incCount(1); } /** * ByteRun1 Run Encoding. *

* The run encoding scheme in byteRun1 is best described by * pseudo code for the decoder Unpacker (called UnPackBits in the * Macintosh toolbox): *

     * UnPacker:
     *    LOOP until produced the desired number of bytes
     *       Read the next source byte into n
     *       SELECT n FROM
     *          [ 0..127 ] => copy the next n+1 bytes literally
     *          [-1..-127] => replicate the next byte -n+1 timees
     *          -128       => no operation
     *       ENDCASE
     *    ENDLOOP
     * 
*/ public void writeByteRun1(byte[] data) throws IOException { writeByteRun1(data, 0, data.length); } public void writeByteRun1(byte[] data, int offset, int length) throws IOException { int end = offset + length; // Start offset of the literal run int literalOffset = offset; int i; for (i = offset; i < end; i++) { // Read a byte byte b = data[i]; // Count repeats of that byte int repeatCount = i + 1; for (; repeatCount < end; repeatCount++) { if (data[repeatCount] != b) { break; } } repeatCount = repeatCount - i; if (repeatCount == 1) { // Flush the literal run, if it gets too large if (i - literalOffset > 127) { write(i - literalOffset - 1); write(data, literalOffset, i - literalOffset); literalOffset = i; } // If the byte repeats just twice, and we have a literal // run with enough space, add it the literal run } else if (repeatCount == 2 && literalOffset < i && i - literalOffset < 127) { i++; } else { // Flush the literal run, if we have one if (literalOffset < i) { write(i - literalOffset - 1); write(data, literalOffset, i - literalOffset); } // Write the repeat run i += repeatCount - 1; literalOffset = i + 1; // We have to write multiple runs, if the byte repeats more // than 128 times. for (; repeatCount > 128; repeatCount -= 128) { write(-127); write(b); } write(-repeatCount + 1); write(b); } } // Flush the literal run, if we have one if (literalOffset < end) { write(i - literalOffset - 1); write(data, literalOffset, i - literalOffset); } } @Override public void write(int b) throws IOException { out.write(b); incCount(1); } @Override public void write(byte b[], int off, int len) throws IOException { out.write(b, off, len); incCount(len); } /** * Writes an chunk type identifier (4 bytes). * @param s A string with a length of 4 characters. */ public void writeType(String s) throws IOException { if (s.length() != 4) { throw new IllegalArgumentException("type string must have 4 characters"); } try { out.write(s.getBytes("ASCII"), 0, 4); incCount(4); } catch (UnsupportedEncodingException e) { throw new InternalError(e.toString()); } } /** * Returns the current value of the counter written, * the number of bytes written to this data output stream so far. * If the counter overflows, it will be wrapped to Integer.MAX_VALUE. * * @return the value of the written field. * @see java.io.DataOutputStream#written */ public final long size() { return written; } /** * Sets the value of the counter written to 0. */ public void clearCount() { written = 0; } /** * Increases the written counter by the specified value * until it reaches Long.MAX_VALUE. */ protected void incCount(int value) { long temp = written + value; if (temp < 0) { temp = Long.MAX_VALUE; } written = temp; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy