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

jfxtras.labs.scene.control.gauge.UtilHex Maven / Gradle / Ivy

There is a newer version: 9.0-r1
Show newest version
/*
 * Copyright (c) 2012, JFXtras
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *      * Redistributions of source code must retain the above copyright
 *        notice, this list of conditions and the following disclaimer.
 *      * Redistributions in binary form must reproduce the above copyright
 *        notice, this list of conditions and the following disclaimer in the
 *        documentation and/or other materials provided with the distribution.
 *      * Neither the name of the  nor the
 *        names of its contributors may be used to endorse or promote products
 *        derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED. IN NO EVENT SHALL  BE LIABLE FOR ANY
 *  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package jfxtras.labs.scene.control.gauge;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.MissingResourceException;


/**
 * @author Jose Pereda Llamas 
 *         Created on : 23-jun-2012, 14:49:58
 */
public class UtilHex {

    private byte[] rawData = null;

    public UtilHex() {
    }

    public static byte[] toBytes(String hexString) {
        String[] bytes = hexString.split("\\s");
        return toBytes(bytes);
    }

    public static byte[] toBytes(String[] bytes) {
        List list = new ArrayList();
        for (String bStr : bytes) {
            int n = 0;
            if (!(bStr.equals("0") || bStr.equals("00"))) {
                n = Byte.parseByte(bStr.substring(0, 1), 16);
                n = 16 * n + Byte.parseByte(bStr.substring(1), 16);
            }
            list.add(new Byte((byte) n));
        }
        byte[] result = new byte[list.size()];
        for (int i = 0; i < list.size(); i++) {
            result[i] = list.get(i);
        }
        return result;
    }
    public static String long2Dword(long l,boolean bLastSB){
        String s1=Long.toHexString(l);
        String ss1=("00000000".substring(0,8-s1.length())).concat(s1);
        //orden lsb:
        if(bLastSB){
            return ss1.substring(6,8).concat(" ").concat(ss1.substring(4,6)).
                    concat(" ").concat(ss1.substring(2,4)).concat(" ").concat(ss1.substring(0,2));
        }
        return ss1.substring(0,2).concat(" ").concat(ss1.substring(2,4)).
                    concat(" ").concat(ss1.substring(4,6)).concat(" ").concat(ss1.substring(6,8));
        
    }public static String long2Word(long l, boolean bLastSB) {
        String s1 = Long.toHexString(l);
        String ss1 = ("0000".substring(0, 4 - s1.length())).concat(s1);
        //orden lsb:
        if (bLastSB) {
            return ss1.substring(2, 4).concat(" ").concat(ss1.substring(0, 2));
        }
        return ss1.substring(0, 2).concat(" ").concat(ss1.substring(2, 4));
    }

    public static String dec2hexStr(byte b) {
        return Integer.toString((b & 0xff) + 0x100, 16).substring(1).toUpperCase();
    }

    public static String dec2hexStr(int b) {
        return Integer.toString((b & 0xff) + 0x100, 16).substring(1).toUpperCase();
    }

    public static String bin2Hex(String s) {
        return Integer.toHexString(Integer.parseInt(s, 2));
    }

    public static String bytes2String(byte[] theBytes) {
        String out = "";
        for (int i = 0; i < theBytes.length; i++) {
            out = out.concat(dec2hexStr(theBytes[i]));
            if (i < theBytes.length - 1) {
                out = out.concat(" ");
            }
        }
        return out;
    }

    public static int word2Int(String s1, String s2) {
        String ss1 = ("00".substring(0, 2 - s1.length())).concat(s1);
        String ss2 = ss1.concat(("00".substring(0, 2 - s2.length())).concat(s2));
        return Integer.parseInt(ss2, 16);
    }
    public static long dword2Long(String s1, String s2, String s3, String s4) {
        String ss1=("00".substring(0,2-s1.length())).concat(s1);
        String ss2=ss1.concat(("00".substring(0,2-s2.length())).concat(s2));
        String ss3=ss2.concat(("00".substring(0,2-s3.length())).concat(s3));
        String ss4=ss3.concat(("00".substring(0,2-s4.length())).concat(s4));
        return Long.parseLong(ss4, 16);
    }
    
    public static int hex2Decimal(String s) {
        int decimal = Integer.parseInt(s, 16);
        return decimal;
    }

    public static String String2Binary(String s) {
        return Integer.toBinaryString(hex2Decimal(s));
    }

    public static String hex2bin(String s) {
        String s1 = String2Binary(s);
        String ss1 = ("00000000".substring(0, 8 - s1.length())).concat(s1);
        return ss1;
    }

    /*
    * Converts BMP format into a BMT file
    * Levels: [0-255]
    */
    public boolean convertsBmp(String pathBmp, int minLevel, int maxLevel,
                               boolean colorR, boolean colorG, boolean colorB) {
        if (maxLevel > 255) {
            maxLevel = 255;
        }
        if (minLevel > maxLevel) {
            minLevel = maxLevel;
        }
        if (minLevel < 0) {
            minLevel = 0;
        }

        int[] tonos = {
            minLevel,
            (int) ((maxLevel + minLevel) / 2),
            maxLevel
        };

        int[] colores = {
            (colorR) ? 1 : 0,
            (colorG) ? 1 : 0,
            (colorB) ? 1 : 0
        }; // R-G-B

        final String fullpathBmp=(pathBmp.endsWith(".bmp")?pathBmp:pathBmp.concat(".bmp"));
        
        InputStream bmpStream=null;
        
        // Try load bmp from jar
        try {	
            bmpStream = getClass().getResourceAsStream( fullpathBmp );            
        }
        catch(MissingResourceException mre){	            
        }
        
        jBMP2Panel bmp = new jBMP2Panel(fullpathBmp, colores, tonos);

        try {
            
            // 1. Open bmp and read rawData
            boolean bFound=false;
            
            if(bmpStream!=null){ 
                bFound=bmp.getBMPImageFromStream(bmpStream);
            }
            else{
                bFound=bmp.getBMPImage();
            }

            if (bFound) {

                // 2. Get hex string with rawdata
                String mem = bmp.BMP2MemoriaGrafica();
                
                this.rawData = toBytes(mem);

                return true;
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return false;
    }

    public String getRawData() {
        if (rawData == null) {
            return null;
        }
        return bytes2String(rawData);
    }

    private class jBMP2Panel {

        /*
        * BMPLoader.
        *
        * JavaZOOM : [email protected]
        *            http://www.javazoom.net
        *
        *-----------------------------------------------------------------------
        *   This program is free software; you can redistribute it and/or modify
        *   it under the terms of the GNU Library General Public License as published
        *   by the Free Software Foundation; either version 2 of the License, or
        *   (at your option) any later version.
        *
        *   This program is distributed in the hope that it will be useful,
        *   but WITHOUT ANY WARRANTY; without even the implied warranty of
        *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        *   GNU Library General Public License for more details.
        *
        *   You should have received a copy of the GNU Library General Public
        *   License along with this program; if not, write to the Free Software
        *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
        *----------------------------------------------------------------------
        */


        private InputStream is;
        private int curPos = 0;
        private int bitmapOffset; // starting position of image data
        private int width; // image width in pixels
        private int height; // image height in pixels
        private int levels = 3; // entre 1 y 4 tonos
        private int[] tonos; // segun levels, entre 0-255 decimal
        private int colorMask = 1; // 7(=Blue 4, Green 2, Red 1 para los tres colores) o 1 (para el Red=1)
        private int numColors = 1;
        private short bitsPerPixel; // 1, 4, 8, or 24 (no color map)
        private int compression; // 0 (none), 1 (8-bit RLE), or 2 (4-bit RLE)
        private int actualSizeOfBitmap;
        private int scanLineSize;
        private int actualColorsUsed;
        private byte r[], g[], b[]; // color palette
        private int noOfEntries;
        private byte[] byteData; // Unpacked data
        private int[] intData; // Unpacked data

        private byte[] m_RawData = null; // the raw bmp data
        private String m_sFullPath = null;

        public jBMP2Panel(String fullPath, int[] colores, int[] tonos) {
            m_sFullPath = fullPath;
            this.tonos = tonos;
            levels = tonos.length;
            colorMask = colores[0] + 2 * colores[1] + 4 * colores[2];
            numColors = 3; //colores[0] + colores[1] + colores[2];
        }

        public boolean getBMPImage() throws Exception {
            File file = new File(m_sFullPath);
            FileInputStream fis = null;
            try {
                fis = new FileInputStream(file);
            } catch (FileNotFoundException ex) {
                System.out.println("File " + m_sFullPath + " not found");
                return false;
            }
            try {
                read(fis);
            } catch (IOException ex) {
                System.out.append("Error reading bmp file");
                return false;
            }

            return true;
        }

        public boolean getBMPImageFromStream(InputStream stream) throws Exception 
        {

            try {
                read(stream);
            } catch (IOException ex) {
                System.out.append("Error reading bmp file");
                return false;
            }

            return true;
        }
        
        protected void getFileHeader() throws IOException, Exception {
            // Actual contents (14 bytes):
            short fileType = 0x4d42;// always "BM"
            int fileSize; // size of file in bytes
            short reserved1 = 0; // always 0
            short reserved2 = 0; // always 0
            fileType = readShort();
            if (fileType != 0x4d42) {
                throw new Exception("Not a BMP file"); // wrong file type
            }
            fileSize = readInt();
            reserved1 = readShort();
            reserved2 = readShort();
            bitmapOffset = readInt();
        }

        protected void getBitmapHeader() throws IOException {
            // Actual contents (40 bytes):
            int size; // size of this header in bytes
            short planes; // no. of color planes: always 1
            int sizeOfBitmap; // size of bitmap in bytes (may be 0: if so, calculate)
            int horzResolution; // horizontal resolution, pixels/meter (may be 0)
            int vertResolution; // vertical resolution, pixels/meter (may be 0)
            int colorsUsed; // no. of colors in palette (if 0, calculate)
            int colorsImportant; // no. of important colors (appear first in palette) (0 means all are important)
            boolean topDown;
            int noOfPixels;
            size = readInt();
            width = readInt();
            height = readInt();
            planes = readShort();
            bitsPerPixel = readShort();
            compression = readInt();
            sizeOfBitmap = readInt();
            horzResolution = readInt();
            vertResolution = readInt();
            colorsUsed = readInt();
            colorsImportant = readInt();
            topDown = (height < 0);
            noOfPixels = width * height;
            // Scan line is padded with zeroes to be a multiple of four bytes
            scanLineSize = ((width * bitsPerPixel + 31) / 32) * 4;
            if (sizeOfBitmap != 0) {
                actualSizeOfBitmap = sizeOfBitmap;
            } else
            // a value of 0 doesn't mean zero - it means we have to calculate it
            {
                actualSizeOfBitmap = scanLineSize * height;
            }
            if (colorsUsed != 0) {
                actualColorsUsed = colorsUsed;
            } else
                // a value of 0 means we determine this based on the bits per pixel
                if (bitsPerPixel < 16) {
                    actualColorsUsed = 1 << bitsPerPixel;
                } else {
                    actualColorsUsed = 0; // no palette
                }
        }

        protected void getPalette() throws IOException {
            noOfEntries = actualColorsUsed;
            //IJ.write("noOfEntries: " + noOfEntries);
            if (noOfEntries > 0) {
                r = new byte[noOfEntries];
                g = new byte[noOfEntries];
                b = new byte[noOfEntries];
                int reserved;
                for (int i = 0; i < noOfEntries; i++) {
                    b[i] = (byte) is.read();
                    g[i] = (byte) is.read();
                    r[i] = (byte) is.read();
                    reserved = is.read();
                    curPos += 4;
                }
            }
        }

        protected void unpack(byte[] rawData, int rawOffset, int[] intData, int intOffset, int w) {
            int j = intOffset;
            int k = rawOffset;
            int mask = 0xff;
            for (int i = 0; i < w; i++) {
                int b0 = (((int) (rawData[k++])) & mask);
                int b1 = (((int) (rawData[k++])) & mask) << 8;
                int b2 = (((int) (rawData[k++])) & mask) << 16;
                intData[j] = 0xff000000 | b0 | b1 | b2;
                j++;
            }
        }

        protected void unpack(byte[] rawData, int rawOffset, int bpp, byte[] byteData, int byteOffset, int w) throws Exception {
            int j = byteOffset;
            int k = rawOffset;
            byte mask;
            int pixPerByte;
            switch (bpp) {
                case 1:
                    mask = (byte) 0x01;
                    pixPerByte = 8;
                    break;
                case 4:
                    mask = (byte) 0x0f;
                    pixPerByte = 2;
                    break;
                case 8:
                    mask = (byte) 0xff;
                    pixPerByte = 1;
                    break;
                default:
                    throw new Exception("Unsupported bits-per-pixel value");
            }
            for (int i = 0; ; ) {
                int shift = 8 - bpp;
                for (int ii = 0; ii < pixPerByte; ii++) {
                    byte br = rawData[k];
                    br >>= shift;
                    byteData[j] = (byte) (br & mask);
                    //System.out.println("Setting byteData[" + j + "]=" + Test.byteToHex(byteData[j]));
                    j++;
                    i++;
                    if (i == w) {
                        return;
                    }
                    shift -= bpp;
                }
                k++;
            }
        }

        protected int readScanLine(byte[] b, int off, int len) throws IOException {
            int bytesRead = 0;
            int l = len;
            int r = 0;
            while (len > 0) {
                bytesRead = is.read(b, off, len);
                if (bytesRead == -1) {
                    return r == 0 ? -1 : r;
                }
                if (bytesRead == len) {
                    return l;
                }
                len -= bytesRead;
                off += bytesRead;
                r += bytesRead;
            }
            return l;
        }

        protected void getPixelData() throws IOException, Exception {

            // Skip to the start of the bitmap data (if we are not already there)
            long skip = bitmapOffset - curPos;
            if (skip > 0) {
                is.skip(skip);
                curPos += skip;
            }
            int len = scanLineSize;
            if (bitsPerPixel > 8) {
                intData = new int[width * height];
            } else {
                byteData = new byte[width * height];
            }
            m_RawData = new byte[actualSizeOfBitmap];
            int rawOffset = 0;
            int offset = (height - 1) * width;
            for (int i = height - 1; i >= 0; i--) {
                int n = readScanLine(m_RawData, rawOffset, len);
                if (n < len) {
                    throw new Exception("Scan line ended prematurely after " + n + " bytes");
                }
                if (bitsPerPixel > 8) {
                    // Unpack and create one int per pixel
                    unpack(m_RawData, rawOffset, intData, offset, width);
                } else {
                    // Unpack and create one byte per pixel
                    unpack(m_RawData, rawOffset, bitsPerPixel, byteData, offset, width);
                }
                rawOffset += len;
                offset -= width;

            }
        }

        public String BMP2MemoriaGrafica() {
            // color number of lines padded with zeroes to be a multiple of one bytes (de 8)
            int colSize = ((int) (width / 8) + (width % 8 > 0 ? 1 : 0)) * 8;
            // Scan line is padded with zeroes to be a multiple of two bytes (de 16)
            int lineSize = ((int) (width / 16) + (width % 16 > 0 ? 1 : 0)) * 16;

            long tam = 32l + levels * lineSize * height * numColors / 8;

            // Header of BMT file
            // 04 DF + 01/FF zipped/unzipped + FF FF FF
            // + colSize (word) + filas (word) + colorMask + levels + 00 00 00 00 00 00 00 01 00 00
            // +tam total colors (word)+ 00 00 + tam total (word) + 00 00 00 00
            String mem = "04 DF FF FF FF FF ";
            mem = mem.concat(long2Word(colSize, false)).concat(" ").concat(long2Word(height, false)).concat(" ");
            mem = mem.concat(dec2hexStr(colorMask)).concat(" ").concat(dec2hexStr(levels)).concat(" ");
            mem = mem.concat("00 00 00 00 00 00 01 00 ").concat(long2Dword(tam - 32,false)).concat(" ");
            mem = mem.concat(long2Dword(tam,false)).concat(" 00 00 00 00");

            for (int k = 0; k < levels; k++) {
                String[][] planos = getPanelRawData(tonos[k]);
                for (int i = 0; i < numColors; i++) {
                    for (int j = 0; j < planos[i].length; j++) {
                        mem = mem.concat(" ").concat(planos[i][j]);
                    }
                }
            }
            return mem;
        }

        public String[] getMemoriaGrafica(int tonoMax) {
            String[] mem = new String[3];
            String[][] planos = getPanelRawData(tonoMax);
            for (int i = 0; i < 3; i++) {
                mem[i] = "";
                for (int j = 0; j < planos[i].length; j++) {
                    mem[i] = mem[i].concat(planos[i][j]);

                    if (j > 0 && (j + 1) % 8 == 0) {
                        mem[i] = mem[i].concat("#");
                    } else if (j < planos[i].length - 1) {
                        mem[i] = mem[i].concat(" ");
                    }
                }
            }

            return mem;
        }

        // transforms bmp to rawData, without header, three splitted planes, according tonoMax
        private String[][] getPanelRawData(int tonoMax) {
            int coloresPorPixel = 3; // 3 color planes in bmp 

            int tam = scanLineSize; // (bmp row size, bytes, eg. 74) x 3
            int colSize = ((int) (width / 8) + (width % 8 > 0 ? 1 : 0)) * 8; // bytes multiple of 8, eg. 80
            int lineSize = ((int) (width / 16) + (width % 16 > 0 ? 1 : 0)) * 16; // bytes multiple of 16, eg. 80

            //string of hexadecimals
            String[][] panelData = new String[coloresPorPixel][height * lineSize / 8];

            int[] swapBMP = {
                2,
                1,
                0
            }; //  bmp: BLUE-GREEN-RED, swap->R,G,B

            for (int k = 0; k < coloresPorPixel; k++) {
                int iPlano = swapBMP[k];
                // plane k
                int pos = 0;
                String lastBit = "";
                for (int j = height - 1; j >= 0; j--) {      // bmp row, from bottom to top
                    for (int i = k; i < lineSize * coloresPorPixel + k; i += coloresPorPixel * 8) { // columna del bmp
                        String bits = "";
                        for (int m = 0; m < 8; m++) {
                            if (i + m * coloresPorPixel < tam) {
                                if ((m_RawData[i + m * coloresPorPixel + j * tam] & 0xff) >= tonoMax) {
                                    bits = bits.concat("1");
                                    lastBit = "1";
                                } else {
                                    bits = bits.concat("0");
                                    lastBit = "0";
                                }
                            } else if (i + m * coloresPorPixel < colSize * coloresPorPixel) {
                                bits = bits.concat("0");  // filled with 0 last colSize
                            } else if (i + m * coloresPorPixel < lineSize * coloresPorPixel) {
                                bits = bits.concat("0"); // filled with 0 last gap colSize to lineSize
                            }
                        }
                        if (pos < lineSize * height / 8) {
                            String s1 = bin2Hex(bits);
                            String ss1 = ("00".substring(0, 2 - s1.length())).concat(s1);

                            panelData[iPlano][pos++] = ss1;
                        }
                    }
                }
            }
            return panelData;
        }

        public void read(InputStream is) throws IOException, Exception {
            this.is = is;
            getFileHeader();
            getBitmapHeader();
            if (compression != 0) {
                throw new Exception("BMP Compression not supported");
            }
            getPalette();
            getPixelData();
        }

        protected int readInt() throws IOException {
            int b1 = is.read();
            int b2 = is.read();
            int b3 = is.read();
            int b4 = is.read();
            curPos += 4;
            return ((b4 << 24) + (b3 << 16) + (b2 << 8) + (b1 << 0));
        }

        protected short readShort() throws IOException {
            int b1 = is.read();
            int b2 = is.read();
            curPos += 4;
            return (short) ((b2 << 8) + b1);
        }

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy