/*******************************************************************************
* This file is part of logisim-evolution.
*
* logisim-evolution is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* logisim-evolution 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with logisim-evolution. If not, see <http://www.gnu.org/licenses/>.
*
* Original code by Carl Burch (http://www.cburch.com), 2011.
* Subsequent modifications by :
* + Haute École Spécialisée Bernoise
* http://www.bfh.ch
* + Haute École du paysage, d'ingénierie et d'architecture de Genève
* http://hepia.hesge.ch/
* + Haute École d'Ingénierie et de Gestion du Canton de Vaud
* http://www.heig-vd.ch/
* The project is currently maintained by :
* + REDS Institute - HEIG-VD
* Yverdon-les-Bains, Switzerland
* http://reds.heig-vd.ch
*******************************************************************************/
package com.bfh.logisim.fpgaboardeditor;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.PixelGrabber;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.imageio.ImageIO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ImageXmlFactory {
final static Logger logger = LoggerFactory.getLogger(ImageXmlFactory.class);
private String[] CodeTable;
private StringBuffer AsciiStream;
private String[] InitialCodeTable = { "a", "b", "c", "d", "e", "f", "g",
"h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
"u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G",
"H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
"U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6",
"7", "8", "9", "(", ")", "+a", "+b", "+c", "+d", "+e", "+f", "+g",
"+h", "+i", "+j", "+k", "+l", "+m", "+n", "+o", "+p", "+q", "+r",
"+s", "+t", "+u", "+v", "+w", "+x", "+y", "+z", "+A", "+B", "+C",
"+D", "+E", "+F", "+G", "+H", "+I", "+J", "+K", "+L", "+M", "+N",
"+O", "+P", "+Q", "+R", "+S", "+T", "+U", "+V", "+W", "+X", "+Y",
"+Z", "+0", "+1", "+2", "+3", "+4", "+5", "+6", "+7", "+8", "+9",
"+(", "+)", "-a", "-b", "-c", "-d", "-e", "-f", "-g", "-h", "-i",
"-j", "-k", "-l", "-m", "-n", "-o", "-p", "-q", "-r", "-s", "-t",
"-u", "-v", "-w", "-x", "-y", "-z", "-A", "-B", "-C", "-D", "-E",
"-F", "-G", "-H", "-I", "-J", "-K", "-L", "-M", "-N", "-O", "-P",
"-Q", "-R", "-S", "-T", "-U", "-V", "-W", "-X", "-Y", "-Z", "-0",
"-1", "-2", "-3", "-4", "-5", "-6", "-7", "-8", "-9", "-(", "-)",
"=a", "=b", "=c", "=d", "=e", "=f", "=g", "=h", "=i", "=j", "=k",
"=l", "=m", "=n", "=o", "=p", "=q", "=r", "=s", "=t", "=u", "=v",
"=w", "=x", "=y", "=z", "=A", "=B", "=C", "=D", "=E", "=F", "=G",
"=H", "=I", "=J", "=K", "=L", "=M", "=N", "=O", "=P", "=Q", "=R",
"=S", "=T", "=U", "=V", "=W", "=X", "=Y", "=Z", "=0", "=1", "=2",
"=3", "=4", "=5", "=6", "=7", "=8", "=9", "=(", "=)" };
private char V2_Identifier = '@';
private String[] CreateCodeTable(byte stream[]) {
String[] result = new String[256];
Long[] ocurances = new Long[256];
int[] index = new int[256];
for (int i = 0; i < 256; i++) {
ocurances[i] = (long) 0;
index[i] = i;
}
for (int i = 0; i < stream.length; i++) {
ocurances[stream[i] + 128]++;
}
boolean swapped = true;
while (swapped) {
swapped = false;
for (int i = 0; i < 255; i++) {
if (ocurances[i] < ocurances[i + 1]) {
swapped = true;
int temp = index[i];
index[i] = index[i + 1];
index[i + 1] = temp;
long swap = ocurances[i];
ocurances[i] = ocurances[i + 1];
ocurances[i + 1] = swap;
}
}
}
for (int i = 0; i < 256; i++) {
result[index[i]] = InitialCodeTable[i];
}
return result;
}
public void CreateStream(Image BoardPicture) {
BufferedImage result = new BufferedImage(740, 400,
BufferedImage.TYPE_3BYTE_BGR);
Graphics2D g2 = result.createGraphics();
int width = BoardPicture.getWidth(null);
int hight = BoardPicture.getHeight(null);
PixelGrabber pixelGrabber = new PixelGrabber(BoardPicture, 0, 0, width,
hight, false);
try {
pixelGrabber.grabPixels();
} catch (Exception e) {
/* TODO: handle exceptions */
logger.error("PixelGrabber exception: {}", e.getMessage());
}
ColorModel color_model = pixelGrabber.getColorModel();
if (pixelGrabber.getPixels() instanceof byte[]) {
byte[] the_pixels = (byte[]) pixelGrabber.getPixels();
int index = 0;
for (int y = 0; y < hight; y++) {
for (int x = 0; x < width; x++) {
Color PixCol = new Color(
color_model.getRed(the_pixels[index]),
color_model.getGreen(the_pixels[index]),
color_model.getBlue(the_pixels[index++]));
g2.setColor(PixCol);
g2.fillRect(x, y, 1, 1);
}
}
} else {
int[] the_pixels = (int[]) pixelGrabber.getPixels();
int index = 0;
for (int y = 0; y < hight; y++) {
for (int x = 0; x < width; x++) {
Color PixCol = new Color(
color_model.getRed(the_pixels[index]),
color_model.getGreen(the_pixels[index]),
color_model.getBlue(the_pixels[index++]));
g2.setColor(PixCol);
g2.fillRect(x, y, 1, 1);
}
}
}
ByteArrayOutputStream blaat = new ByteArrayOutputStream();
try {
ImageIO.write(result, "jpg", blaat);
} catch (IOException e) {
// TODO Auto-generated catch block
logger.error("JPEG Writer exception: {}", e.getMessage());
}
byte data[] = blaat.toByteArray();
CodeTable = CreateCodeTable(data);
AsciiStream = new StringBuffer();
AsciiStream.append(V2_Identifier);
for (int i = 0; i < data.length; i++) {
String code = CodeTable[data[i] + 128];
AsciiStream.append(code);
}
}
public String GetCodeTable() {
StringBuffer result = new StringBuffer();
for (int i = 0; i < CodeTable.length; i++) {
if (i != 0) {
result.append(" ");
}
result.append(CodeTable[i]);
}
return result.toString();
}
public String GetCompressedString() {
return AsciiStream.toString();
}
public BufferedImage GetPicture(int width, int height) {
if (AsciiStream == null)
return null;
if (CodeTable == null)
return null;
if (CodeTable.length != 256)
return null;
BufferedImage result = null;
Map<String, Integer> CodeLookupTable = new HashMap<String, Integer>();
for (int i = 0; i < CodeTable.length; i++)
CodeLookupTable.put(CodeTable[i], i);
int index = 0;
Set<String> TwoCodes = new HashSet<String>();
TwoCodes.add("-");
TwoCodes.add("+");
TwoCodes.add("=");
boolean jpegCompressed = AsciiStream.charAt(0) == V2_Identifier;
if (jpegCompressed) {
index++;
ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
while (index < AsciiStream.length()) {
if (TwoCodes.contains(AsciiStream.substring(index, index + 1))) {
bytestream.write((byte) (CodeLookupTable.get(AsciiStream
.substring(index, index + 2)) - 128));
index += 2;
} else {
bytestream.write((byte) (CodeLookupTable.get(AsciiStream
.substring(index, index + 1)) - 128));
index++;
}
}
try {
bytestream.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ByteArrayInputStream instream = new ByteArrayInputStream(
bytestream.toByteArray());
try {
result = ImageIO.read(instream);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
result = new BufferedImage(width, height,
BufferedImage.TYPE_3BYTE_BGR);
Graphics2D g2 = result.createGraphics();
g2.setBackground(Color.BLACK);
String CurRedComp, CurGreenComp, CurBlueComp;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (TwoCodes.contains(AsciiStream.substring(index,
index + 1))) {
CurRedComp = AsciiStream.substring(index, index + 2);
index += 2;
} else {
CurRedComp = AsciiStream.substring(index, index + 1);
index++;
}
if (TwoCodes.contains(AsciiStream.substring(index,
index + 1))) {
CurGreenComp = AsciiStream.substring(index, index + 2);
index += 2;
} else {
CurGreenComp = AsciiStream.substring(index, index + 1);
index++;
}
if (TwoCodes.contains(AsciiStream.substring(index,
index + 1))) {
CurBlueComp = AsciiStream.substring(index, index + 2);
index += 2;
} else {
CurBlueComp = AsciiStream.substring(index, index + 1);
index++;
}
if (!CodeLookupTable.containsKey(CurRedComp)
|| !CodeLookupTable.containsKey(CurGreenComp)
|| !CodeLookupTable.containsKey(CurBlueComp)) {
return null;
}
Color PixCol = new Color(CodeLookupTable.get(CurRedComp),
CodeLookupTable.get(CurGreenComp),
CodeLookupTable.get(CurBlueComp));
g2.setColor(PixCol);
g2.fillRect(x, y, 1, 1);
}
}
}
return result;
}
public void SetCodeTable(String[] Table) {
CodeTable = Table.clone();
}
public void SetCompressedString(String stream) {
AsciiStream = new StringBuffer();
AsciiStream.append(stream);
}
}