private enum ScanState {
GROUND,
QUOTE,
- COLOR_ENTRY,
- COLOR_PARAM,
- COLOR_PIXELS,
- SIXEL_REPEAT,
+ COLOR,
+ REPEAT,
}
// ------------------------------------------------------------------------
/**
* If true, enable debug messages.
*/
- private static boolean DEBUG = true;
+ private static boolean DEBUG = false;
/**
* Number of pixels to increment when we need more horizontal room.
private ScanState scanState = ScanState.GROUND;
/**
- * Parameter characters being collected.
+ * Parameters being collected.
*/
- private ArrayList<Integer> colorParams;
+ private int [] params = new int[5];
+
+ /**
+ * Current parameter being collected.
+ */
+ private int paramsI = 0;
/**
* The sixel palette colors specified.
*/
private int x = 0;
+ /**
+ * The maximum y drawn to. This will set the final image height.
+ */
+ private int y = 0;
+
/**
* The current drawing color.
*/
*/
public Sixel(final String buffer) {
this.buffer = buffer;
- colorParams = new ArrayList<Integer>();
palette = new HashMap<Integer, Color>();
image = new BufferedImage(200, 100, BufferedImage.TYPE_INT_ARGB);
for (int i = 0; i < buffer.length(); i++) {
*/
public BufferedImage getImage() {
if ((width > 0) && (height > 0)) {
- return image.getSubimage(0, 0, width, height);
+ return image.getSubimage(0, 0, width, y + 1);
}
return null;
}
BufferedImage newImage = new BufferedImage(newWidth, newHeight,
BufferedImage.TYPE_INT_ARGB);
+ if (DEBUG) {
+ System.err.println("resizeImage(); old " + image.getWidth() + "x" +
+ image.getHeight() + " new " + newWidth + "x" + newHeight);
+ }
+
Graphics2D gr = newImage.createGraphics();
gr.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
gr.dispose();
* Clear the parameters and flags.
*/
private void toGround() {
- colorParams.clear();
+ paramsI = 0;
+ for (int i = 0; i < params.length; i++) {
+ params[i] = 0;
+ }
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.
*
* @return parameter value
*/
private int getColorParam(final int position, final int defaultValue) {
- if (colorParams.size() < position + 1) {
+ if (position > paramsI) {
return defaultValue;
}
- return colorParams.get(position).intValue();
+ return params[position];
}
/**
*/
private void addSixel(final char ch) {
int n = ((int) ch - 63);
+
+ if (DEBUG && (color == null)) {
+ System.err.println("color is null?!");
+ System.err.println(buffer);
+ }
+
int rgb = color.getRGB();
int rep = (repeatCount == -1 ? 1 : repeatCount);
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.
return;
}
+ int dy = 0;
for (int i = 0; i < rep; i++) {
- if ((n & 0x01) == 0x01) {
- image.setRGB(x, height, rgb);
+ if ((n & 0x01) != 0) {
+ dy = 0;
+ image.setRGB(x, height + dy, rgb);
}
- if ((n & 0x02) == 0x02) {
- image.setRGB(x, height + 1, rgb);
+ if ((n & 0x02) != 0) {
+ dy = 1;
+ image.setRGB(x, height + dy, rgb);
}
- if ((n & 0x04) == 0x04) {
- image.setRGB(x, height + 2, rgb);
+ if ((n & 0x04) != 0) {
+ dy = 2;
+ image.setRGB(x, height + dy, rgb);
}
- if ((n & 0x08) == 0x08) {
- image.setRGB(x, height + 3, rgb);
+ if ((n & 0x08) != 0) {
+ dy = 3;
+ image.setRGB(x, height + dy, rgb);
}
- if ((n & 0x10) == 0x10) {
- image.setRGB(x, height + 4, rgb);
+ if ((n & 0x10) != 0) {
+ dy = 4;
+ image.setRGB(x, height + dy, rgb);
}
- if ((n & 0x20) == 0x20) {
- image.setRGB(x, height + 5, rgb);
+ if ((n & 0x20) != 0) {
+ dy = 5;
+ image.setRGB(x, height + dy, rgb);
}
- x++;
- if (x > width) {
- width++;
- assert (x == width);
+ if (height + dy > y) {
+ y = height + dy;
}
+ x++;
+ }
+ if (x > width) {
+ width = x;
}
}
private void setPalette() {
int idx = getColorParam(0, 0);
- if (colorParams.size() == 1) {
+ if (paramsI == 0) {
Color newColor = palette.get(idx);
if (newColor != null) {
color = newColor;
+ } else {
+ if (DEBUG) {
+ System.err.println("COLOR " + idx + " NOT FOUND");
+ }
+ color = Color.BLACK;
}
if (DEBUG) {
- System.err.println("set color: " + color);
+ System.err.println("set color " + idx + " " + color);
}
return;
}
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);
+ }
}
}
// DEBUG
// System.err.printf("Sixel.consume() %c STATE = %s\n", ch, scanState);
- switch (scanState) {
-
- case GROUND:
- switch (ch) {
- case '#':
- scanState = ScanState.COLOR_ENTRY;
- return;
- case '\"':
- scanState = ScanState.QUOTE;
- return;
- default:
- break;
- }
-
- if (ch == '!') {
- // Repeat count
- scanState = ScanState.SIXEL_REPEAT;
- }
- if (ch == '-') {
- 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;
- }
-
- if (ch == '$') {
- x = 0;
- }
- return;
-
- case QUOTE:
- switch (ch) {
- case '#':
- scanState = ScanState.COLOR_ENTRY;
- return;
- default:
- break;
+ // Between decimal 63 (inclusive) and 127 (exclusive) --> pixels
+ if ((ch >= 63) && (ch < 127)) {
+ if (scanState == ScanState.COLOR) {
+ setPalette();
}
-
- // Ignore everything else in the quote header.
+ addSixel(ch);
+ toGround();
return;
+ }
- case COLOR_ENTRY:
- // Between decimal 63 (inclusive) and 189 (exclusive) --> pixels
- if ((ch >= 63) && (ch < 189)) {
- addSixel(ch);
- return;
- }
-
- // 30-39, 3B --> param, then switch to COLOR_PARAM
- if ((ch >= '0') && (ch <= '9')) {
- param((byte) ch);
- scanState = ScanState.COLOR_PARAM;
- }
- if (ch == ';') {
- param((byte) ch);
- scanState = ScanState.COLOR_PARAM;
- }
-
- if (ch == '#') {
- // Next color is here, parse what we had before.
+ if (ch == '#') {
+ // Next color is here, parse what we had before.
+ if (scanState == ScanState.COLOR) {
setPalette();
toGround();
}
+ scanState = ScanState.COLOR;
+ return;
+ }
- if (ch == '!') {
- setPalette();
- toGround();
-
- // Repeat count
- scanState = ScanState.SIXEL_REPEAT;
- }
- if (ch == '-') {
+ if (ch == '!') {
+ // Repeat count
+ 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;
}
+ scanState = ScanState.REPEAT;
+ repeatCount = 0;
+ return;
+ }
- if (ch == '$') {
+ if (ch == '-') {
+ if (scanState == ScanState.COLOR) {
setPalette();
toGround();
-
- x = 0;
}
- return;
- case COLOR_PARAM:
-
- // Between decimal 63 (inclusive) and 189 (exclusive) --> pixels
- if ((ch >= 63) && (ch < 189)) {
- addSixel(ch);
- return;
- }
+ height += 6;
+ x = 0;
- // 30-39, 3B --> param, then switch to COLOR_PARAM
- if ((ch >= '0') && (ch <= '9')) {
- param((byte) ch);
- }
- if (ch == ';') {
- param((byte) ch);
+ if (height + 6 > image.getHeight()) {
+ // Resize the image, give us another HEIGHT_INCREASE
+ // pixels of vertical length.
+ resizeImage(image.getWidth(),
+ image.getHeight() + HEIGHT_INCREASE);
}
+ return;
+ }
- if (ch == '#') {
- // Next color is here, parse what we had before.
+ if (ch == '$') {
+ if (scanState == ScanState.COLOR) {
setPalette();
toGround();
- scanState = ScanState.COLOR_ENTRY;
}
+ x = 0;
+ return;
+ }
- if (ch == '!') {
- setPalette();
- toGround();
-
- // Repeat count
- scanState = ScanState.SIXEL_REPEAT;
- }
- if (ch == '-') {
+ 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;
}
+ scanState = ScanState.QUOTE;
+ return;
+ }
- if (ch == '$') {
- setPalette();
- toGround();
+ switch (scanState) {
- x = 0;
+ case GROUND:
+ // Unknown character.
+ if (DEBUG) {
+ System.err.println("UNKNOWN CHAR: " + ch);
}
return;
- case SIXEL_REPEAT:
+ case QUOTE:
+ // Ignore everything else in the quote header.
+ return;
- // Between decimal 63 (inclusive) and 189 (exclusive) --> pixels
- if ((ch >= 63) && (ch < 189)) {
- addSixel(ch);
- toGround();
+ case COLOR:
+ // 30-39, 3B --> param
+ if ((ch >= '0') && (ch <= '9')) {
+ params[paramsI] *= 10;
+ params[paramsI] += (ch - '0');
+ }
+ if (ch == ';') {
+ if (paramsI < params.length - 1) {
+ paramsI++;
+ }
}
+ return;
+ case REPEAT:
if ((ch >= '0') && (ch <= '9')) {
if (repeatCount == -1) {
repeatCount = (int) (ch - '0');
repeatCount += (int) (ch - '0');
}
}
-
- if (ch == '#') {
- // Next color.
- toGround();
- scanState = ScanState.COLOR_ENTRY;
- }
-
return;
+
}
}