+package be.nikiroo.jvcard.tui;
+
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.image.BufferedImage;
+import java.awt.image.ImageObserver;
+
+import com.googlecode.lanterna.TerminalSize;
+
+public class ImageText {
+ private Image image;
+ private TerminalSize size;
+ private String text;
+ private boolean ready;
+
+ public ImageText(Image image, TerminalSize size) {
+ setImage(image, size);
+ }
+
+ public void setImage(Image image) {
+ setImage(image, size);
+ }
+
+ public void setImage(TerminalSize size) {
+ setImage(image, size);
+ }
+
+ public void setImage(Image image, TerminalSize size) {
+ this.text = null;
+ this.ready = false;
+ this.size = size;
+ if (image != null) {
+ this.image = image;
+ }
+ }
+
+ public String getText() {
+ if (text == null) {
+ if (image == null)
+ return "";
+
+ int w = size.getColumns() * 2;
+ int h = size.getRows() * 2;
+ BufferedImage buff = new BufferedImage(w, h,
+ BufferedImage.TYPE_INT_ARGB);
+ Graphics gfx = buff.getGraphics();
+
+ TerminalSize srcSize = getSize(image);
+ int x = 0;
+ int y = 0;
+ if (srcSize.getColumns() > srcSize.getRows()) {
+ double ratio = (double) srcSize.getRows()
+ / (double) srcSize.getColumns();
+ h = (int) Math.round(ratio * h);
+ y = (buff.getHeight() - h) / 2;
+ } else {
+ double ratio = (double) srcSize.getColumns()
+ / (double) srcSize.getRows();
+ w = (int) Math.round(ratio * w);
+ x = (buff.getWidth() - w) / 2;
+
+ }
+
+ if (gfx.drawImage(image, x, y, w, h, new ImageObserver() {
+ @Override
+ public boolean imageUpdate(Image img, int infoflags, int x,
+ int y, int width, int height) {
+ ImageText.this.ready = true;
+ return true;
+ }
+ })) {
+ ready = true;
+ }
+
+ while (!ready) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ }
+ }
+
+ gfx.dispose();
+
+ int[][] square = new int[2][2];
+ StringBuilder builder = new StringBuilder();
+ for (int row = 0; row < buff.getHeight(); row += 2) {
+ if (row > 0)
+ builder.append('\n');
+
+ for (int col = 0; col < buff.getWidth(); col += 2) {
+ square[0][0] = buff.getRGB(col, row);
+ square[0][1] = buff.getRGB(col, row + 1);
+ square[1][0] = buff.getRGB(col + 1, row);
+ square[1][1] = buff.getRGB(col + 1, row + 1);
+ builder.append(getChar(square));
+ }
+ }
+
+ text = builder.toString();
+ }
+
+ return text;
+ }
+
+ @Override
+ public String toString() {
+ return getText();
+ }
+
+ static private TerminalSize getSize(Image img) {
+ TerminalSize size = null;
+ while (size == null) {
+ int w = img.getWidth(null);
+ int h = img.getHeight(null);
+ if (w > -1 && h > -1) {
+ size = new TerminalSize(w, h);
+ } else {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ return size;
+ }
+
+ static private char getChar(int[][] square) {
+ int choice = 0;
+ if (rgb2hsl(square[0][0])[3] > 50)
+ choice += 1;
+ if (rgb2hsl(square[0][1])[3] > 50)
+ choice += 2;
+ if (rgb2hsl(square[1][0])[3] > 50)
+ choice += 4;
+ if (rgb2hsl(square[1][1])[3] > 50)
+ choice += 8;
+
+ switch (choice) {
+ case 0:
+ return ' ';
+ case 1:
+ return '▘';
+ case 2:
+ return '▝';
+ case 3:
+ return '▀';
+ case 4:
+ return '▖';
+ case 5:
+ return '▌';
+ case 6:
+ return '▞';
+ case 7:
+ return '▛';
+ case 8:
+ return '▗';
+ case 9:
+ return '▚';
+ case 10:
+ return '▐';
+ case 11:
+ return '▜';
+ case 12:
+ return '▄';
+ case 13:
+ return '▙';
+ case 14:
+ return '▟';
+ case 15:
+ return '█';
+ }
+
+ return ' ';
+ }
+
+ // return [a, h, s, l]; a/s/l: 0 to 100%, h = 0 to 359°
+ static int[] rgb2hsl(int argb) {
+ double a, r, g, b;
+ a = ((argb & 0xff000000) >> 24) / 255.0;
+ r = ((argb & 0x00ff0000) >> 16) / 255.0;
+ g = ((argb & 0x0000ff00) >> 8) / 255.0;
+ b = ((argb & 0x000000ff)) / 255.0;
+
+ double rgbMin, rgbMax;
+ rgbMin = Math.min(r, Math.min(g, b));
+ rgbMax = Math.max(r, Math.max(g, b));
+
+ double l;
+ l = (rgbMin + rgbMax) / 2;
+
+ double s;
+ if (rgbMin == rgbMax) {
+ s = 0;
+ } else {
+ if (l <= 0.5) {
+ s = (rgbMax - rgbMin) / (rgbMax + rgbMin);
+ } else {
+ s = (rgbMax - rgbMin) / (2.0 - rgbMax - rgbMin);
+ }
+ }
+
+ double h;
+ if (r > g && r > b) {
+ h = (g - b) / (rgbMax - rgbMin);
+ } else if (g > b) {
+ h = 2.0 + (b - r) / (rgbMax - rgbMin);
+ } else {
+ h = 4.0 + (r - g) / (rgbMax - rgbMin);
+ }
+
+ int aa = (int) Math.round(100 * a);
+ int hh = (int) (60 * h);
+ if (hh < 0)
+ hh += 360;
+ int ss = (int) Math.round(100 * s);
+ int ll = (int) Math.round(100 * l);
+
+ return new int[] { aa, hh, ss, ll };
+ }
+}