/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (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
 *
 * 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.
 */

/* $Id: RunLengthEncodeOutputStream.java 1804124 2017-08-04 14:13:54Z ssteiner $ */

package org.apache.xmlgraphics.util.io;

import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;


This class applies a RunLengthEncode filter to the stream.
Version: $Id: RunLengthEncodeOutputStream.java 1804124 2017-08-04 14:13:54Z ssteiner $ Originally authored by Stephen Wolke.
/** * This class applies a RunLengthEncode filter to the stream. * * @version $Id: RunLengthEncodeOutputStream.java 1804124 2017-08-04 14:13:54Z ssteiner $ * * Originally authored by Stephen Wolke. */
public class RunLengthEncodeOutputStream extends FilterOutputStream implements Finalizable { private static final int MAX_SEQUENCE_COUNT = 127; private static final int END_OF_DATA = 128; private static final int BYTE_MAX = 256; private static final int NOT_IDENTIFY_SEQUENCE = 0; private static final int START_SEQUENCE = 1; private static final int IN_SEQUENCE = 2; private static final int NOT_IN_SEQUENCE = 3; private int runCount; private int isSequence = NOT_IDENTIFY_SEQUENCE; private byte[] runBuffer = new byte[MAX_SEQUENCE_COUNT + 1];
See Also:
/** @see java.io.FilterOutputStream **/
public RunLengthEncodeOutputStream(OutputStream out) { super(out); }
See Also:
/** @see java.io.FilterOutputStream **/
public void write(byte b) throws java.io.IOException { runBuffer[runCount] = b; switch (runCount) { case 0: runCount = 0; isSequence = NOT_IDENTIFY_SEQUENCE; runCount++; break; case 1: if (runBuffer[runCount] != runBuffer[runCount - 1]) { isSequence = NOT_IN_SEQUENCE; } runCount++; break; case 2: if (runBuffer[runCount] != runBuffer[runCount - 1]) { isSequence = NOT_IN_SEQUENCE; } else { if (isSequence == NOT_IN_SEQUENCE) { isSequence = START_SEQUENCE; } else { isSequence = IN_SEQUENCE; } } runCount++; break; case MAX_SEQUENCE_COUNT: if (isSequence == IN_SEQUENCE) { out.write(BYTE_MAX - (MAX_SEQUENCE_COUNT - 1)); out.write(runBuffer[runCount - 1]); runBuffer[0] = runBuffer[runCount]; runCount = 1; } else { out.write(MAX_SEQUENCE_COUNT); out.write(runBuffer, 0, runCount + 1); runCount = 0; } isSequence = NOT_IDENTIFY_SEQUENCE; break; default: switch (isSequence) { case NOT_IN_SEQUENCE: if (runBuffer[runCount] == runBuffer[runCount - 1]) { isSequence = START_SEQUENCE; } runCount++; break; case START_SEQUENCE: if (runBuffer[runCount] == runBuffer[runCount - 1]) { out.write(runCount - 3); out.write(runBuffer, 0, runCount - 2); runBuffer[0] = runBuffer[runCount]; runBuffer[1] = runBuffer[runCount]; runBuffer[2] = runBuffer[runCount]; runCount = 3; isSequence = IN_SEQUENCE; break; } else { isSequence = NOT_IN_SEQUENCE; runCount++; break; } case IN_SEQUENCE: default: if (runBuffer[runCount] != runBuffer[runCount - 1]) { out.write(BYTE_MAX - (runCount - 1)); out.write(runBuffer[runCount - 1]); runBuffer[0] = runBuffer[runCount]; runCount = 1; isSequence = NOT_IDENTIFY_SEQUENCE; break; } runCount++; break; } } }
See Also:
/** @see java.io.FilterOutputStream **/
public void write(byte[] b) throws IOException { for (byte aB : b) { this.write(aB); } }
See Also:
/** @see java.io.FilterOutputStream **/
public void write(byte[] b, int off, int len) throws IOException { for (int i = 0; i < len; i++) { this.write(b[off + i]); } }
See Also:
/** @see Finalizable **/
public void finalizeStream() throws IOException { switch (isSequence) { case IN_SEQUENCE: out.write(BYTE_MAX - (runCount - 1)); out.write(runBuffer[runCount - 1]); break; default: out.write(runCount - 1); out.write(runBuffer, 0, runCount); } out.write(END_OF_DATA); flush(); if (out instanceof Finalizable) { ((Finalizable) out).finalizeStream(); } }
See Also:
/** @see java.io.FilterOutputStream **/
public void close() throws IOException { finalizeStream(); super.close(); } }