X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fjexer%2Ftterminal%2FSixel.java;h=a4c00fc67f1da1ca38847b9bb5dad63daac5e006;hb=929409950e82914aa3cee323cfa7c5007585d2ea;hp=de3232c6588da3b1e6445a8d031b3804f8ab69eb;hpb=69a8c36844309a07dfe7c8c7576d9c0e47be3303;p=fanfix.git diff --git a/src/jexer/tterminal/Sixel.java b/src/jexer/tterminal/Sixel.java deleted file mode 100644 index de3232c..0000000 --- a/src/jexer/tterminal/Sixel.java +++ /dev/null @@ -1,457 +0,0 @@ -/* - * Jexer - Java Text User Interface - * - * The MIT License (MIT) - * - * Copyright (C) 2019 Kevin Lamonte - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * @author Kevin Lamonte [kevin.lamonte@gmail.com] - * @version 1 - */ -package jexer.tterminal; - -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import java.util.ArrayList; -import java.util.HashMap; - -/** - * Sixel parses a buffer of sixel image data into a BufferedImage. - */ -public class Sixel { - - // ------------------------------------------------------------------------ - // Constants -------------------------------------------------------------- - // ------------------------------------------------------------------------ - - /** - * Parser character scan states. - */ - private enum ScanState { - GROUND, - QUOTE, - COLOR, - REPEAT, - } - - // ------------------------------------------------------------------------ - // Variables -------------------------------------------------------------- - // ------------------------------------------------------------------------ - - /** - * If true, enable debug messages. - */ - private static boolean DEBUG = false; - - /** - * Number of pixels to increment when we need more horizontal room. - */ - private static int WIDTH_INCREASE = 400; - - /** - * Number of pixels to increment when we need more vertical room. - */ - private static int HEIGHT_INCREASE = 400; - - /** - * Current scanning state. - */ - private ScanState scanState = ScanState.GROUND; - - /** - * Parameter characters being collected. - */ - private ArrayList colorParams; - - /** - * The sixel palette colors specified. - */ - private HashMap palette; - - /** - * The buffer to parse. - */ - private String buffer; - - /** - * The image being drawn to. - */ - private BufferedImage image; - - /** - * The real width of image. - */ - private int width = 0; - - /** - * The real height of image. - */ - private int height = 0; - - /** - * The repeat count. - */ - private int repeatCount = -1; - - /** - * The current drawing x position. - */ - private int x = 0; - - /** - * The current drawing color. - */ - private Color color = Color.BLACK; - - // ------------------------------------------------------------------------ - // Constructors ----------------------------------------------------------- - // ------------------------------------------------------------------------ - - /** - * Public constructor. - * - * @param buffer the sixel data to parse - */ - public Sixel(final String buffer) { - this.buffer = buffer; - colorParams = new ArrayList(); - palette = new HashMap(); - image = new BufferedImage(200, 100, BufferedImage.TYPE_INT_ARGB); - for (int i = 0; i < buffer.length(); i++) { - consume(buffer.charAt(i)); - } - } - - // ------------------------------------------------------------------------ - // Sixel ------------------------------------------------------------------ - // ------------------------------------------------------------------------ - - /** - * Get the image. - * - * @return the sixel data as an image. - */ - public BufferedImage getImage() { - if ((width > 0) && (height > 0)) { - return image.getSubimage(0, 0, width, height + 6); - } - return null; - } - - /** - * Resize image to a new size. - * - * @param newWidth new width of image - * @param newHeight new height of image - */ - private void resizeImage(final int newWidth, final int newHeight) { - BufferedImage newImage = new BufferedImage(newWidth, newHeight, - BufferedImage.TYPE_INT_ARGB); - - Graphics2D gr = newImage.createGraphics(); - gr.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null); - gr.dispose(); - image = newImage; - } - - /** - * Clear the parameters and flags. - */ - private void toGround() { - colorParams.clear(); - scanState = ScanState.GROUND; - repeatCount = -1; - } - - /** - * Save a byte into the color parameters buffer. - * - * @param ch byte to save - */ - private void param(final byte ch) { - if (colorParams.size() == 0) { - colorParams.add(Integer.valueOf(0)); - } - Integer n = colorParams.get(colorParams.size() - 1); - if ((ch >= '0') && (ch <= '9')) { - n *= 10; - n += (ch - '0'); - colorParams.set(colorParams.size() - 1, n); - } - - if ((ch == ';') && (colorParams.size() < 16)) { - colorParams.add(Integer.valueOf(0)); - } - } - - /** - * Get a color parameter value, with a default. - * - * @param position parameter index. 0 is the first parameter. - * @param defaultValue value to use if colorParams[position] doesn't exist - * @return parameter value - */ - private int getColorParam(final int position, final int defaultValue) { - if (colorParams.size() < position + 1) { - return defaultValue; - } - return colorParams.get(position).intValue(); - } - - /** - * Get a color parameter value, clamped to within min/max. - * - * @param position parameter index. 0 is the first parameter. - * @param defaultValue value to use if colorParams[position] doesn't exist - * @param minValue minimum value inclusive - * @param maxValue maximum value inclusive - * @return parameter value - */ - private int getColorParam(final int position, final int defaultValue, - final int minValue, final int maxValue) { - - assert (minValue <= maxValue); - int value = getColorParam(position, defaultValue); - if (value < minValue) { - value = minValue; - } - if (value > maxValue) { - value = maxValue; - } - return value; - } - - /** - * Add sixel data to the image. - * - * @param ch the character of sixel data - */ - private void addSixel(final char ch) { - int n = ((int) ch - 63); - int rgb = color.getRGB(); - int rep = (repeatCount == -1 ? 1 : repeatCount); - - if (DEBUG) { - System.err.println("addSixel() rep " + rep + " char " + - Integer.toHexString(n) + " color " + color); - } - - assert (n >= 0); - - if (x + rep > image.getWidth()) { - // Resize the image, give us another max(rep, WIDTH_INCREASE) - // pixels of horizontal length. - resizeImage(image.getWidth() + Math.max(rep, WIDTH_INCREASE), - image.getHeight()); - } - - // If nothing will be drawn, just advance x. - if (n == 0) { - x += rep; - if (x > width) { - width = x; - } - return; - } - - for (int i = 0; i < rep; i++) { - if ((n & 0x01) != 0) { - image.setRGB(x, height + 0, rgb); - } - if ((n & 0x02) != 0) { - image.setRGB(x, height + 1, rgb); - } - if ((n & 0x04) != 0) { - image.setRGB(x, height + 2, rgb); - } - if ((n & 0x08) != 0) { - image.setRGB(x, height + 3, rgb); - } - if ((n & 0x10) != 0) { - image.setRGB(x, height + 4, rgb); - } - if ((n & 0x20) != 0) { - image.setRGB(x, height + 5, rgb); - } - x++; - if (x > width) { - width++; - assert (x == width); - } - } - } - - /** - * Process a color palette change. - */ - private void setPalette() { - int idx = getColorParam(0, 0); - - if (colorParams.size() == 1) { - Color newColor = palette.get(idx); - if (newColor != null) { - color = newColor; - } else { - System.err.println("COLOR " + idx + " NOT FOUND"); - } - - if (DEBUG) { - System.err.println("set color " + idx + " " + color); - } - return; - } - - int type = getColorParam(1, 0); - float red = (float) (getColorParam(2, 0, 0, 100) / 100.0); - float green = (float) (getColorParam(3, 0, 0, 100) / 100.0); - float blue = (float) (getColorParam(4, 0, 0, 100) / 100.0); - - if (type == 2) { - Color newColor = new Color(red, green, blue); - palette.put(idx, newColor); - if (DEBUG) { - System.err.println("Palette color " + idx + " --> " + newColor); - } - } else { - if (DEBUG) { - System.err.println("UNKNOWN COLOR TYPE " + type + ": " + type + - " " + idx + " R " + red + " G " + green + " B " + blue); - } - } - } - - /** - * Run this input character through the sixel state machine. - * - * @param ch character from the remote side - */ - private void consume(char ch) { - - // DEBUG - // System.err.printf("Sixel.consume() %c STATE = %s\n", ch, scanState); - - // Between decimal 63 (inclusive) and 127 (exclusive) --> pixels - if ((ch >= 63) && (ch < 127)) { - if (scanState == ScanState.COLOR) { - setPalette(); - toGround(); - } - addSixel(ch); - toGround(); - return; - } - - if (ch == '#') { - // Next color is here, parse what we had before. - if (scanState == ScanState.COLOR) { - setPalette(); - toGround(); - } - scanState = ScanState.COLOR; - return; - } - - if (ch == '!') { - // Repeat count - if (scanState == ScanState.COLOR) { - setPalette(); - toGround(); - } - scanState = ScanState.REPEAT; - repeatCount = 0; - return; - } - - if (ch == '-') { - if (scanState == ScanState.COLOR) { - setPalette(); - toGround(); - } - - if (height + 6 < image.getHeight()) { - // Resize the image, give us another HEIGHT_INCREASE - // pixels of vertical length. - resizeImage(image.getWidth(), - image.getHeight() + HEIGHT_INCREASE); - } - height += 6; - x = 0; - return; - } - - if (ch == '$') { - if (scanState == ScanState.COLOR) { - setPalette(); - toGround(); - } - x = 0; - return; - } - - if (ch == '"') { - if (scanState == ScanState.COLOR) { - setPalette(); - toGround(); - } - scanState = ScanState.QUOTE; - return; - } - - switch (scanState) { - - case GROUND: - // Unknown character. - if (DEBUG) { - System.err.println("UNKNOWN CHAR: " + ch); - } - return; - - case QUOTE: - // Ignore everything else in the quote header. - return; - - case COLOR: - // 30-39, 3B --> param - if ((ch >= '0') && (ch <= '9')) { - param((byte) ch); - } - if (ch == ';') { - param((byte) ch); - } - return; - - case REPEAT: - if ((ch >= '0') && (ch <= '9')) { - if (repeatCount == -1) { - repeatCount = (int) (ch - '0'); - } else { - repeatCount *= 10; - repeatCount += (int) (ch - '0'); - } - } - return; - - } - - } - -}