Huffman code for image compression - Java - encoding

Since I started my Codification Theory course, I've started to feel curious about practical implementations of information theory algorithms. I've researched about Huffman code and how this is used for data compress. I am specially curious about building an image (JPG, JPEG) compressor using Huffman codes but I'm struggling in the implementation.
My idea for this program goes like this:
1. Implement a HuffmanCode class, which is used to encode and decode a string input (Find the char frequency for all characters in string, build Huffman tree, generate Huffman code, etc.). I found this implementation "here".
2. Having the Huffman code implementation, I read an image input and convert it to a byte array. Then, I use this byte array to build a string having all of these bytes. Now, I apply the Huffman code for the previous string.
3. The result of the previous step is a binary string, then I convert this binary string to a byte array.
4. Finally, write the corresponding image to the previous byte array and output.
Following this reasoning, I got a RasterFormatException : Data array too small (should be > 749999 ). I've tried others implementations for writing the image but I am still getting some other Exceptions such as image == null exception.
I was wondering if someone has a better approach for building this program, or if I am missing something related to writing/reading images in Java (I'm new with this tools), or if I am misunderstanding something related to Huffman codes.
The HuffmanCode class is the following (I made some changes):
public class HuffmanCode {
public static void main(String[] args){
String test = "AndersonAndresLlanosQuintero";
System.out.println(countFrequency(test));
}
// Clase nodo para las construcción del árbol.
class HuffmanNode{
public int frecuencia;
public char caracter;
public HuffmanNode leftNode;
public HuffmanNode rightNode;
public HuffmanNode(){}
public int getFrecuencia() {
return frecuencia;
}
public void setFrecuencia(int frecuencia) {
this.frecuencia = frecuencia;
}
public char getCaracter() {
return caracter;
}
public void setCaracter(char caracter) {
this.caracter = caracter;
}
public HuffmanNode getLeftNode() {
return leftNode;
}
public void setLeftNode(HuffmanNode leftNode) {
this.leftNode = leftNode;
}
public HuffmanNode getRightNode() {
return rightNode;
}
public void setRightNode(HuffmanNode rightNode) {
this.rightNode = rightNode;
}
}
// Clase comparadora para saber cuando un nodo está por encima de otro.
class HuffmanComparator implements Comparator<HuffmanNode> {
public int compare(HuffmanNode x, HuffmanNode y) {
return x.frecuencia - y.frecuencia;
}
}
/* Procedemos a implementar el algoritmo : */
/* Necesitaremos la raíz del árbol de Huffman y un Map para
hacer match entre un símbol y su frecuencia de aparición.
*/
private Map<Character,String> charToBinaryMap;
private HuffmanNode root;
private String nuevaSalida;
public HuffmanNode getRoot(){
return this.root;
}
public String getNuevaSalida(){
return this.nuevaSalida;
}
public HuffmanCode(){
this.root = null;
this.charToBinaryMap = new HashMap<Character, String>();
}
public HuffmanNode getTree(){
return this.root;
}
/* Teniendo el código de Huffman, decodificar simplemente asigna a cada arista
* del árbol el símbolo de 0 o 1. Para esta implementación, las aristas a la izq.
* tendrán el símbolo "0" y para la derecha el símbolo "1". */
public String Decodificar(String binaryString, HuffmanNode root){
HuffmanNode current = root;
StringBuilder build = new StringBuilder();
for(int i = 0; i < binaryString.length(); i++){
if(current != null){
if((current.rightNode == null && binaryString.charAt(i) == '1') || (current.leftNode == null && binaryString.charAt(i) == '0')){
i--;
build.append(current.caracter);
current = root;
continue;
}
if(binaryString.charAt(i) == '1'){
current = current.rightNode;
}else {
current = current.leftNode;
}
}
}
if(current != null){
build.append(current.caracter);
}
return build.toString();
}
/*Codificar : Crear el árbol más óptimo para nuestra cadena de bits. */
public String Codificar(String strToCode){
Map<Character, Integer> charOcurrence = countFrequency(strToCode);
int n = charOcurrence.size();
/* Creamos una cola de prioridad con el mapeo de la ocurrencia de símbolos
que organice los símbolos de acuerdo al comparador de Huffman. */
PriorityQueue<HuffmanNode> huffmanHeap = new PriorityQueue<>(n, new HuffmanComparator());
// Recorremos el HashMap y creamos la cola de prioridad de acuerdo a la frecuencia del símbolo:
charOcurrence.forEach((key, value) -> {
HuffmanNode node = new HuffmanNode();
node.caracter = key;
node.frecuencia = value;
node.leftNode = null;
node.rightNode = null;
huffmanHeap.add(node);
});
/* Transformamos la cola prioritaria (minHeap) en un árbol de Huffman mediante
el algoritmo visto en clase. */
while(huffmanHeap.size() > 1){
HuffmanNode leaf1 = huffmanHeap.peek();
huffmanHeap.poll();
HuffmanNode leaf2 = huffmanHeap.peek();
huffmanHeap.poll();
HuffmanNode ptr = new HuffmanNode();
ptr.frecuencia = leaf1.frecuencia + leaf2.frecuencia;
ptr.caracter = '-';
ptr.leftNode = leaf1;
ptr.rightNode = leaf2;
huffmanHeap.add(ptr);
}
this.root = huffmanHeap.peek();
/* Teniendo el árbol de Huffman, buscamos las palabras código
y mostramos al usuario como se han codificado los símbolos : */
System.out.println(" Caracter | Palabra Código | Frecuencia");
System.out.println("----------------------------------");
codeWords(root, "");
/* Codificamos el input con las nuevas palabras código obtenidas : */
StringBuilder build = new StringBuilder();
for(Character ch : strToCode.toCharArray()){
build.append(this.charToBinaryMap.get(ch));
}
this.nuevaSalida = build.toString();
int pesoOriginal = strToCode.getBytes().length*8;
int pesoComprimido = nuevaSalida.length();
System.out.println("Peso original (bits) :" + pesoOriginal);
/*System.out.println("Codificación de Huffman: " + nuevaSalida);
*/
System.out.println("Longitud de la codificación de Huffman: " + nuevaSalida.length());
System.out.println("Peso post-codificación: " + pesoComprimido);
return nuevaSalida;
}
/* countFrequency : Cuenta número de ocurrencias de un caracter. */
public static Map<Character, Integer> countFrequency(String input){
HashMap<Character, Integer> mapFrequency = new HashMap<>();
for(int i = 0; i < input.length(); i++){
if(!mapFrequency.containsKey(input.toCharArray()[i])){
mapFrequency.put(input.toCharArray()[i], 1);
}else{
mapFrequency.put(input.toCharArray()[i], mapFrequency.get(input.toCharArray()[i])+1);
}
}
return mapFrequency;
}
/* Como queremos las hojas del árbol de Huffman, hacemos un simple
* recorrido in-order sobre el árbol, imprimiendo únicamente las hojas. */
public void codeWords(HuffmanNode root, String str){
if(root.leftNode != null){
codeWords(root.leftNode, str + 0);
}
if(root.leftNode == null && root.rightNode == null){
this.charToBinaryMap.put(root.caracter, str);
System.out.println(root.caracter + " | " + str + " | " + root.frecuencia);
return;
}
if(root.rightNode != null){
codeWords(root.rightNode, str + 1);
}
}
public String charList(HuffmanNode root, String str){
if(root.leftNode != null){
charList(root.leftNode, str);
}
if(root.leftNode == null && root.rightNode == null){
str = str + root.caracter;
}
if(root.rightNode != null){
charList(root.rightNode, str);
}
return str;
}
}
The ImageProcessing class, where the whole reasoning is developed, is the following:
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.image.*;
import java.io.*;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import javax.imageio.ImageIO;
public class ImageProcessing {
public static void main(String args[]) throws Exception{
/* Convert image to byte array and then, to a string */
StringBuilder build = new StringBuilder();
BufferedImage bImage = ImageIO.read(new File("/WorkSpace/HuffmanCompression/src/draken.jpg"));
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ImageIO.write(bImage, "jpg", bos );
byte [] data = bos.toByteArray();
for(int i = 0; i < data.length; i++){
build.append(data[i]);
}
/* Use Huffman code to the previous string.*/
HuffmanCode huffman = new HuffmanCode();
String prueba = huffman.Codificar(build.toString());
String pruebaDecodificada = huffman.Decodificar(prueba, huffman.getTree());
String strToByte = huffman.getNuevaSalida();
/*
String inputString = strToByte;
Charset dictionaryMap = StandardCharsets.UTF_16;
byte[] newImage = inputString.getBytes(dictionaryMap);
*/
/*Convert the binary string to a byte array and then, output the corresponding image. I copied and paste this part of the code from this blog. */
byte[] bval = new BigInteger(strToByte, 2).toByteArray();
OutputStream stream = new FileOutputStream("output.jpg");
BufferedImage image = createRGBImage(bval, bImage.getWidth(), bImage.getHeight());
try {
ImageIO.write(image, "jpg", stream);
}
finally {
stream.close();
}
}
public static BufferedImage createRGBImage(byte[] bytes, int width, int height) {
DataBufferByte buffer = new DataBufferByte(bytes, bytes.length);
ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[]{8, 8, 8}, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
return new BufferedImage(cm, Raster.createInterleavedRaster(buffer, width, height, width * 3, 3, new int[]{0, 1, 2}, null), false, null);
}
}
I will be grateful if someone can help me, Thanks in advance!

Related

Network Lobby manager

I'm developing a multiplayer online application with unity3D, and I'm using networkLobbyManager, I managed to create a match and allow the players to join the match by running matchMaker.JoinMatch so I have all the players in "Lobby Scene" but I did not understand how we can join them in "play scene".
(I have found that we can move to play scene only if all players are ready, but I do not understand how I can put them all ready). my code :
public InputField impF;
public InputField impF1;
public Dropdown d;
List<MatchInfoSnapshot> m;
MatchInfoSnapshot ma;
public int n = 1;
// Use this for initialization
public void enableMatch()
{
Debug.Log("# MMStart ");
this.StartMatchMaker();
}
public override void OnStartHost()
{
base.OnStartHost();
Debug.Log("the game has created");
}
public void crereMatch()
{
string nom = impF.text;
Debug.Log(nom);
MMCreateMateches(nom);
n = 2;
}
public void findMtches()
{
MMListMateches();
}
public void joinMatch()
{
Debug.Log(d.options[d.value].text);
foreach (var match in this.matches)
{
Debug.Log("dans la boucle des matches");
Debug.Log(match.name);
if ((d.options[d.value].text).Equals(match.name))
{
//on récupere
ma = match;
Debug.Log("dans le if " + ma.name);
break;
}
}
// this.f
m = this.matches;
ma = m.Find(x => (x.name).Equals(ma.name));
Debug.Log("apres recuperation de la liste" + ma.name);
MMjoinMateches(ma);
}
void MMListMateches()
{
Debug.Log("# MMListMateches ");
this.matchMaker.ListMatches(0, 20, "", true, 0, 0, OnMatchList);
}
public override void OnMatchList(bool success, string extendedInfo, List<MatchInfoSnapshot> matchList)
{
Debug.Log("# OnMatchList ");
base.OnMatchList(success, extendedInfo, matchList);
if (!success)
{
Debug.Log("liste failed " + extendedInfo);
}
else
{
if (matches.Count > 0)
{ //les matches en cours > 0 ms on doit le joiner
Debug.Log("succesfully listed match 1 er match :" + matchList[0]);
Debug.Log(matchList[0].name);
foreach (var match in this.matches)
{
Debug.Log("dans la boucle");
Debug.Log(match.name);
Debug.Log(" wééééééééééééééééééé ");
}
d.ClearOptions();
foreach (var match in this.matches)
{
Debug.Log(match.name);
// impF1.text = match.name;
List<string> m_DropOptions = new List<string> { match.name };
d.AddOptions(m_DropOptions);
}
// MMjoinMateches(matchList[0]);
}
else
{
Debug.Log("no mateches");
// MMCreateMateches();
}
}
}
void MMjoinMateches(MatchInfoSnapshot firstMatch)
{
Debug.Log("# MMjoinMateches ");
this.matchMaker.JoinMatch(firstMatch.networkId, "", "", "", 0, 0, OnMatchJoined);
}
public override void OnMatchJoined(bool success, string extendedInfo, MatchInfo matchInfo)
{
Debug.Log("# OnMatchJoined ");
base.OnMatchJoined(success, extendedInfo, matchInfo);
if (!success)
{
Debug.Log("failed to join match " + extendedInfo);
impF1.text = "failed";
}
else
{
Debug.Log("succesfuly joined match " + matchInfo.networkId);
impF1.text = "succes";
this.StartClient(matchInfo);
}
}
void MMCreateMateches(string nom)
{
Debug.Log("# MMCreateMateches ");
Debug.Log(nom);
this.matchMaker.CreateMatch(nom, 15, true, "", "", "", 0, 0, OnMatchCreate);
}
public override void OnMatchCreate(bool success, string extendedInfo, MatchInfo matchInfo)
{
Debug.Log("# OnMatchCreate ");
base.OnMatchCreate(success, extendedInfo, matchInfo);
if (!success)
{
Debug.Log("failed to create match " + extendedInfo);
}
else
{
Debug.Log("succesfuly created match " + matchInfo.networkId);
OnStartHost();
}
}
public override void OnLobbyServerPlayersReady()
{
base.OnLobbyServerPlayersReady();
}
Watch this tutorial by Holistic 3D on how to setup Unity Network Lobby (Free in the Asset Store). https://www.youtube.com/watch?v=jklWlm5v21k
In the settings, you determine Max Players needed to enter a room. You can set it to '1' so anyone can enter at anytime.
Change Max Players from 4 to 1 See Link

How to setSelected by name some JMenuItem in a JPopUpMenu?

I have a JPopUpMenu with several JCheckBoxMenuItem's on it.
I also have a properties files (config.properties) where I put a parameter which save every JCheckBoxMenuItem the user has checked on this JPopUpMenu , when i close the application.
So this file is like :
config.properties :
listeFiltres =Autres,Afrique du sud,Algérie
What I would like to do is , on the start of my application, to setSelected every item that is saved in my properties parameter.
For exemple, if "Afrique,Algérie,Allemagne" are stored in my parameter listeFiltres in config.properties, I want these 3 JCheckBoxMenuItem to be checked at the start of my application.
The problem is that I only know the setSelected method which allows to select an item with a specific index(like 2), but here I need to select an item with a specific name (like "Afrique"), so this method isn't appropriate for me.
Here's the code of my JPopUpMenu :
MainVue.java:
public class MainVue extends JFrame implements ActionListener {
private static final JScrollPopupMenu menuProduit = new JScrollPopupMenu();
private static final JScrollPopupMenu menuPays = new JScrollPopupMenu();
private static List<String> listeFiltres = new ArrayList<String>();
private String listeDeFiltres;
private String[] tableauFiltrePermanent;
private String listeFiltrePermanent;
private String[] tableauPays = { "Autres", "Afrique du sud", "Algérie", "Allemagne", "Arabie Saoudite", "Argentine",
"Australie", "Bangladesh", "Belgique", "Brésil", "Bulgarie", "Canada", "Chine", "Corée du sud", "Egypte",
"Emirats-Arabes Unis", "Espagne", "Etats-Unis", "Ethiopie", "Europe", "France", "Hongrie", "Inde",
"Indonésie", "Irak", "Iran", "Israél", "Italie", "Japon", "Jordanie", "Kazakhstan", "Koweit", "Liban",
"Libye", "Malaisie", "Maroc", "Mexique", "Monde", "Oman", "Pakistan", "Pays-Bas", "Philippines", "Poligne",
"Portugal", "Qatar", "République tchéque", "Roumanie", "Russie", "Taïwan", "Tunisie", "Turquie",
"Ukraine" };
private String[] tableauProduit = { "Blé", "Colza", "Mais", "Orge", "Orge de Brasserie", "Palme", "Soja",
"Tournesol", "Tourteaux De Colza", "Tourteaux de Soja", "Huile de Soja", "Huile De Colza" };
private List<JCheckBoxMenuItem> listJCBProduit = new ArrayList<JCheckBoxMenuItem>();
private List<JCheckBoxMenuItem> listJCBPays = new ArrayList<JCheckBoxMenuItem>();
public static PropertiesConfiguration prop;
public MainVue(Modele modele, Controleur controleur) throws ClassNotFoundException, SQLException, IOException {
prop = new PropertiesConfiguration("config.properties");
for (int i = 0; i < tableauProduit.length; i++) {
listJCBProduit.add(new JCheckBoxMenuItem(tableauProduit[i]));
}
for (int j = 0; j < listJCBProduit.size(); j++) {
JCheckBoxMenuItem produitActuel = listJCBProduit.get(j);
menuProduit.add(produitActuel);
produitActuel.addActionListener(new OpenAction(menuProduit, boutonProduit));
}
for (int i = 0; i < tableauPays.length; i++) {
listJCBPays.add(new JCheckBoxMenuItem(tableauPays[i]));
}
for (int j = 0; j < listJCBPays.size(); j++) {
JCheckBoxMenuItem paysActuel = listJCBPays.get(j);
menuPays.add(paysActuel);
paysActuel.addActionListener(new OpenAction(menuPays, boutonPays));
}
listeDeFiltres = "";
for (int p = 0; p < listeFiltres.size(); p++) {
String filtreActuel = listeFiltres.get(p);
if (listeDeFiltres == "") {
listeDeFiltres += filtreActuel;
} else {
listeDeFiltres += "," + filtreActuel;
}
}
prop.setProperty("listeFiltres", listeDeFiltres);
}
}
You can get the index of name from tableauPays array as follows and can pass it to the setSelected() method
public int getIndex(String name){
int index = 0;
for(String p : tableauPays){
if(p.equals(name)){
return index;
}
index++;
}
}

Creating custom plugin for chinese tokenization

I'm working towards properly integrating the stanford segmenter within SOLR for chinese tokenization.
This plugin involves loading other jar files and model files. I've got it working in a crude manner by hardcoding the complete path for the files.
I'm looking for methods to create the plugin where the paths need not be hardcoded and also to have the plugin in conformance with the SOLR plugin architecture. Please let me know if there are any recommended sites or tutorials for this.
I've added my code below :
public class ChineseTokenizerFactory extends TokenizerFactory {
/** Creates a new WhitespaceTokenizerFactory */
public ChineseTokenizerFactory(Map<String,String> args) {
super(args);
assureMatchVersion();
if (!args.isEmpty()) {
throw new IllegalArgumentException("Unknown parameters: " + args);
}
}
#Override
public ChineseTokenizer create(AttributeFactory factory, Reader input) {
Reader processedStringReader = new ProcessedStringReader(input);
return new ChineseTokenizer(luceneMatchVersion, factory, processedStringReader);
}
}
public class ProcessedStringReader extends java.io.Reader {
private static final int BUFFER_SIZE = 1024 * 8;
//private static TextProcess m_textProcess = null;
private static final String basedir = "/home/praveen/PDS_Meetup/solr-4.9.0/custom_plugins/";
static Properties props = null;
static CRFClassifier<CoreLabel> segmenter = null;
private char[] m_inputData = null;
private int m_offset = 0;
private int m_length = 0;
public ProcessedStringReader(Reader input){
char[] arr = new char[BUFFER_SIZE];
StringBuffer buf = new StringBuffer();
int numChars;
if(segmenter == null)
{
segmenter = new CRFClassifier<CoreLabel>(getProperties());
segmenter.loadClassifierNoExceptions(basedir + "ctb.gz", getProperties());
}
try {
while ((numChars = input.read(arr, 0, arr.length)) > 0) {
buf.append(arr, 0, numChars);
}
} catch (IOException e) {
e.printStackTrace();
}
m_inputData = processText(buf.toString()).toCharArray();
m_offset = 0;
m_length = m_inputData.length;
}
#Override
public int read(char[] cbuf, int off, int len) throws IOException {
int charNumber = 0;
for(int i = m_offset + off;i<m_length && charNumber< len; i++){
cbuf[charNumber] = m_inputData[i];
m_offset ++;
charNumber++;
}
if(charNumber == 0){
return -1;
}
return charNumber;
}
#Override
public void close() throws IOException {
m_inputData = null;
m_offset = 0;
m_length = 0;
}
public String processText(String inputText)
{
List<String> segmented = segmenter.segmentString(inputText);
String output = "";
if(segmented.size() > 0)
{
output = segmented.get(0);
for(int i=1;i<segmented.size();i++)
{
output = output + " " +segmented.get(i);
}
}
System.out.println(output);
return output;
}
static Properties getProperties()
{
if (props == null) {
props = new Properties();
props.setProperty("sighanCorporaDict", basedir);
// props.setProperty("NormalizationTable", "data/norm.simp.utf8");
// props.setProperty("normTableEncoding", "UTF-8");
// below is needed because CTBSegDocumentIteratorFactory accesses it
props.setProperty("serDictionary",basedir+"dict-chris6.ser.gz");
props.setProperty("inputEncoding", "UTF-8");
props.setProperty("sighanPostProcessing", "true");
}
return props;
}
}
public final class ChineseTokenizer extends CharTokenizer {
public ChineseTokenizer(Version matchVersion, Reader in) {
super(matchVersion, in);
}
public ChineseTokenizer(Version matchVersion, AttributeFactory factory, Reader in) {
super(matchVersion, factory, in);
}
/** Collects only characters which do not satisfy
* {#link Character#isWhitespace(int)}.*/
#Override
protected boolean isTokenChar(int c) {
return !Character.isWhitespace(c);
}
}
You can pass the argument through the Factory's args parameter.

CheckBoxCell in CellTable

I have a CheckBoxCell I want to add my CellTable but not when I'm wrong because when I run it does not show me the Check
THIS IS MY CODE
public class TablaEntryPoint extends Composite implements EntryPoint{
private SingleSelectionModel sm = new SingleSelectionModel();
{
// Añade un objeto que recibe notificaciones cuando cambia la selección.
sm.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
#Override
public void onSelectionChange(SelectionChangeEvent event) {
AuxParametro c = sm.getSelectedObject();
if (c != null) {
Window.alert(c.getNomParametro());
}
}
});
}
/** La tabla trabaja por páginas. En este caso la longitud de página se pasa en el
* constructor. También hay un constructor sin parámetros que define una longitud
* por defecto de 15 renglones por página. */
private final CellTable<AuxParametro> tblConocidos = new CellTable<AuxParametro>(10);
{
// asigna el objeto que controla las selecciones.
tblConocidos.setSelectionModel(sm);
// Agrega columnas.
// Columna numérica. El constructor de "NumberCell"puede recibir un"NumberFormat".
tblConocidos.addColumn(new Column<AuxParametro, Number>(new NumberCell()) {
{
setHorizontalAlignment(HasAlignment.ALIGN_RIGHT);
}
#Override
public Long getValue(final AuxParametro objeto) {
return objeto.getIdParametro();
}
}, "ID Unico");
// Columna de texto fijo con encabezado y pie de página.
tblConocidos.addColumn(new TextColumn<AuxParametro>() {
#Override
public String getValue(final AuxParametro objeto) {
return objeto.getNomParametro();
}
}, "Nombre Parametro");
/* Columna modificable. El método "update" de la interfaz "FieldUpdater" recibe
* los cambios a un objeto de la columna. */
tblConocidos.addColumn(new Column<AuxParametro,String>(new TextInputCell()) {
{
/* Asigna la referencia al objeto que recibe las notificaciones de cambio. */
setFieldUpdater(new FieldUpdater<AuxParametro, String>() {
#Override
public void update(int index, AuxParametro objeto, String valor) {
objeto.setCodContable(Integer.parseInt(valor));
}
});
}
#Override
public String getValue(final AuxParametro objeto) {
return String.valueOf(objeto.getCodContable());
}
}, "Codigo Contable");
// Columna de fecha.
tblConocidos.addColumn(new Column<AuxParametro, Number>(new NumberCell()) {
#Override
public Integer getValue(final AuxParametro objeto) {
return objeto.getCodUno();
}
}, "Codigo Uno");
// Columna de fecha.
tblConocidos.addColumn(new Column<AuxParametro, Number>(new NumberCell()) {
#Override
public Integer getValue(final AuxParametro objeto) {
return objeto.getCodDos();
}
}, "Codigo Dos");
Column<AuxParametro, Boolean> checkColumn = new Column<AuxParametro, Boolean>(
new CheckboxCell(true, false)) {
#Override
public Boolean getValue(AuxParametro object) {
// Get the value from the selection model.
return sm.isSelected(object);
}
};
tblConocidos.addColumn(checkColumn, SafeHtmlUtils.fromSafeConstant("<br/>"));
}
private final SimplePager pager = new SimplePager();
{
pager.setDisplay(tblConocidos);
}
public TablaEntryPoint(List<AuxParametro> tabla) {
ListDataProvider<AuxParametro> dataProvider = new ListDataProvider<AuxParametro>(tabla);
dataProvider.addDataDisplay(tblConocidos);
FlowPanel panel = new FlowPanel();
panel.add(new Label("Seleccione un contacto o edite su teléfono."));
panel.add(tblConocidos);
panel.add(pager);
initWidget(panel);
}
public void onModuleLoad() {
RootPanel.get().add(this);
}
}
I think you need to set the column width for each of your columns. If you look at the GWT showcase CellTable example (here) you can see that the checkbox column width is set with the statement cellTable.setColumnWidth(checkColumn, 40, Unit.PX).

displaying an uploded image 404 error

I'm trying to upload an image from the signup form using InscriptionForm.java to check the respectieve fields. The upload has no problem (Thanks to BalusC's tutorials), but, when I try to display the uploaded image, I can't; refering to the HTTP network monitor I got 404 error as response. Also, when I try to enter the above link into the browser's adress bar http://localhost:8080/projetForum/images/bd/Id_21082013184506.png I've got a 404 error.
InscriptionForm.java
public final class InscriptionForm {
private static final String CHAMP_EMAIL = "email";
private static final String CHAMP_PASS = "motdepasse";
private static final String CHAMP_CONF = "confirmation";
private static final String CHAMP_NOM = "nom";
private static final String CHAMP_DESC = "description";
private static final String CHAMP_LOC = "localisation";
private static final String CHAMP_SW = "siteweb";
public static final String CHAMP_IMAGE = "avatar";
public static final String CHAMP_JOURDENAISS = "jourdenaissance";
public static final String CHAMP_MOISDENAISS = "moisdenaissance";
public static final String CHAMP_ANNEEDENAISS = "anneedenaissance";
public static final String CHAMP_DATEDENAISS = "datedenaissance";
public static final int TAILLE_TAMPON = 10240; // 10 ko
public static final String CHEMIN = "E:\\Bibliothèque logicielle\\workspace\\projetForum\\WebContent\\images\\bd\\";
private String resultat;
private static Map<String, String> erreurs = new HashMap<String, String>();
public String getResultat() {
return resultat;
}
public Map<String, String> getErreurs() {
return erreurs;
}
public Utilisateur inscrireUtilisateur(HttpServletRequest request) {
String email = getValeurChamp(request, CHAMP_EMAIL);
String motDePasse = getValeurChamp(request, CHAMP_PASS);
String confirmation = getValeurChamp(request, CHAMP_CONF);
String nom = getValeurChamp(request, CHAMP_NOM);
String description = getValeurChamp(request, CHAMP_DESC);
String localisation = getValeurChamp(request, CHAMP_LOC);
String siteweb = getValeurChamp(request, CHAMP_SW);
String image = getValeurChamp(request, CHAMP_IMAGE);
String jourdenaissance = getValeurChamp(request, CHAMP_JOURDENAISS);
String moisdenaissance = getValeurChamp(request, CHAMP_MOISDENAISS);
String anneedenaissance = getValeurChamp(request, CHAMP_ANNEEDENAISS);
Integer datedenaissance = null;
try {
validationEmail(email);
} catch (Exception e) {
setErreur(CHAMP_EMAIL, e.getMessage());
}
try {
validationMotsDePasse(motDePasse, confirmation);
} catch (Exception e) {
setErreur(CHAMP_PASS, e.getMessage());
}
try {
validationNom(nom);
} catch (Exception e) {
setErreur(CHAMP_NOM, e.getMessage());
}
try {
image = validationImage(request, CHEMIN);
} catch (Exception e) {
setErreur(CHAMP_IMAGE, e.getMessage());
}
if (!jourdenaissance.equals("defaut")
&& !moisdenaissance.equals("defaut")
&& !anneedenaissance.equals("defaut")) {
try {
validationDateDeNaiss(Integer.parseInt(jourdenaissance),
Integer.parseInt(moisdenaissance),
Integer.parseInt(anneedenaissance));
} catch (Exception e) {
setErreur(CHAMP_DATEDENAISS, e.getMessage());
}
datedenaissance = Integer.parseInt((jourdenaissance + ""
+ moisdenaissance + "" + anneedenaissance));
}
if (jourdenaissance.equals("defaut")
&& moisdenaissance.equals("defaut")
&& anneedenaissance.equals("defaut")) {
} else {
setErreur(CHAMP_DATEDENAISS,
"Merci de vérifier votre date de naissance.");
}
Utilisateur utilisateur = new Utilisateur(email, motDePasse, nom,
localisation, siteweb, description, datedenaissance, image);
if (erreurs.isEmpty()) {
resultat = "Succès de l'inscription.";
createORupdate(utilisateur, request);
} else {
resultat = "Échec de l'inscription.";
}
return utilisateur;
}
private String validationImage(HttpServletRequest request, String chemin)
throws Exception {
File uploadFilePath = new File(chemin);
// Validate file.
Object fileObject = request.getAttribute("avatar");
if (fileObject == null) {
// No file uploaded.
throw new Exception("Please select file to upload.");
} else if (fileObject instanceof FileUploadException) {
// File upload is failed.
FileUploadException fileUploadException = (FileUploadException) fileObject;
throw new Exception(fileUploadException.getMessage());
}
// If there are no errors, proceed with writing file.
FileItem fileItem = (FileItem) fileObject;
// Get file name from uploaded file and trim path from it.
// Some browsers (e.g. IE, Opera) also sends the path, which is
// completely irrelevant.
String fileName = FilenameUtils.getName(fileItem.getName());
// Prepare filename prefix and suffix for an unique filename in upload
// folder.
String prefix = FilenameUtils.getBaseName(fileName) + "_";
String suffix = "." + FilenameUtils.getExtension(fileName);
File file = null;
try {
// Prepare unique local file based on file name of uploaded file.
file = File.createTempFile(prefix, suffix, uploadFilePath);
// Write uploaded file to local file.
fileItem.write(file);
} catch (Exception e) {
// Can be thrown by uniqueFile() and FileItem#write().
throw new Exception(e.getMessage());
}
return file.getName();
}
private void setErreur(String champ, String message) {
erreurs.put(champ, message);
}
private static String getValeurChamp(HttpServletRequest request,
String nomChamp) {
String valeur = request.getParameter(nomChamp);
if (valeur == null || valeur.trim().length() == 0) {
return null;
} else {
return valeur;
}
}
private static void createORupdate(Utilisateur u, HttpServletRequest request) {
Session s = HibernateUtils.getSession();
Transaction tx = s.beginTransaction();
Query q = s
.createQuery("from Utilisateur where Utilisateur_email = :email");
q.setString("email", u.getEmail());
Utilisateur userUpdt = (Utilisateur) q.uniqueResult();
if (userUpdt != null) {
userUpdt.setNom(u.getNom());
userUpdt.setEmail(u.getEmail());
userUpdt.setSiteweb(u.getSiteweb());
userUpdt.setLocalisation(u.getLocalisation());
userUpdt.setDescription(u.getDescription());
s.update(userUpdt);
} else {
SimpleDateFormat formater = new SimpleDateFormat(
"dd-MM-yyyy hh:mm:ss");
Date aujourdhui = new Date();
u.setDateInscrit(formater.format(aujourdhui));
s.persist(u);
}
tx.commit();
}
private void validationEmail(String email) throws Exception {
UtilisateurDAO<Utilisateur, String> ud = new UtilisateurDAO<Utilisateur, String>();
if (ud.findByID(email) != null)
throw new Exception("Adresse mail déjà utilisée.");
else if (email == null || ud.findByID(email) != null
|| !email.matches("([^.#]+)(\\.[^.#]+)*#([^.#]+\\.)+([^.#]+)")) {
throw new Exception("Merci de saisir une adresse mail valide.");
}
}
private void validationDateDeNaiss(Integer jj, Integer mm, Integer aaaa)
throws Exception {
switch (mm) {
case 2:
if (jj > 28 && ((aaaa / 4) % 100 == 0 && aaaa % 400 == 0))
throw new Exception(
"Merci de vérifier votre date de naissance.");
break;
case 4:
if (jj == 31)
throw new Exception(
"Merci de vérifier votre date de naissance.");
break;
case 6:
if (jj == 31)
throw new Exception(
"Merci de vérifier votre date de naissance.");
break;
case 9:
if (jj == 31)
throw new Exception(
"Merci de vérifier votre date de naissance.");
break;
case 11:
if (jj == 31)
throw new Exception(
"Merci de vérifier votre date de naissance.");
break;
}
}
private void validationMotsDePasse(String motDePasse, String confirmation)
throws Exception {
if (motDePasse != null && confirmation != null) {
if (!motDePasse.equals(confirmation)) {
throw new Exception(
"Les mots de passe entrés sont différents, merci de les saisir à nouveau.");
} else if (motDePasse.length() < 6) {
throw new Exception(
"Les mots de passe doivent contenir au moins 6 caractères.");
}
} else {
throw new Exception(
"Merci de saisir et confirmer votre mot de passe.");
}
}
private static void validationNom(String nom) throws Exception {
ConfigFDAO<ConfigF, Integer> cfd = new ConfigFDAO<ConfigF, Integer>();
UtilisateurDAO<Utilisateur, String> ud = new UtilisateurDAO<Utilisateur, String>();
if (ud.findByNom(nom) != null)
throw new Exception("Nom d'utilisateur déjà utilisée.");
else if (nom == null
|| nom.length() < cfd.findByID(0).getPseudominsize()
|| nom.length() > cfd.findByID(0).getPseudomaxsize()) {
throw new Exception("Le nom d'utilisateur doit contenir au moins "
+ cfd.findByID(0).getPseudominsize() + " et au maximum "
+ cfd.findByID(0).getPseudomaxsize() + " caractères.");
}
}
private static String getNomFichier(Part part) {
for (String cd : part.getHeader("content-disposition").split(";")) {
if (cd.trim().startsWith("filename")) {
String filename = cd.substring(cd.indexOf('=') + 1).trim()
.replace("\"", "");
return filename.substring(filename.lastIndexOf('/') + 1)
.substring(filename.lastIndexOf('\\') + 1);
}
}
return null;
}
}
MultipartFilter.java
public class MultipartFilter implements Filter {
// Init
// ---------------------------------------------------------------------------------------
private long maxFileSize;
// Actions
// ------------------------------------------------------------------------------------
/**
* Configure the 'maxFileSize' parameter.
*
* #throws ServletException
* If 'maxFileSize' parameter value is not numeric.
* #see javax.servlet.Filter#init(javax.servlet.FilterConfig)
*/
public void init(FilterConfig filterConfig) throws ServletException {
// Configure maxFileSize.
String maxFileSize = filterConfig.getInitParameter("maxFileSize");
if (maxFileSize != null) {
if (!maxFileSize.matches("^\\d+$")) {
throw new ServletException(
"MultipartFilter 'maxFileSize' is not numeric.");
}
this.maxFileSize = Long.parseLong(maxFileSize);
}
}
/**
* Check the type request and if it is a HttpServletRequest, then parse the
* request.
*
* #throws ServletException
* If parsing of the given HttpServletRequest fails.
* #see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,
* javax.servlet.ServletResponse, javax.servlet.FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws ServletException, IOException {
// Check type request.
if (request instanceof HttpServletRequest) {
// Cast back to HttpServletRequest.
HttpServletRequest httpRequest = (HttpServletRequest) request;
// Parse HttpServletRequest.
HttpServletRequest parsedRequest = parseRequest(httpRequest);
// Continue with filter chain.
chain.doFilter(parsedRequest, response);
} else {
// Not a HttpServletRequest.
chain.doFilter(request, response);
}
}
/**
* #see javax.servlet.Filter#destroy()
*/
public void destroy() {
// I am a boring method.
}
// Helpers
// ------------------------------------------------------------------------------------
/**
* Parse the given HttpServletRequest. If the request is a multipart
* request, then all multipart request items will be processed, else the
* request will be returned unchanged. During the processing of all
* multipart request items, the name and value of each regular form field
* will be added to the parameterMap of the HttpServletRequest. The name and
* File object of each form file field will be added as attribute of the
* given HttpServletRequest. If a FileUploadException has occurred when the
* file size has exceeded the maximum file size, then the
* FileUploadException will be added as attribute value instead of the
* FileItem object.
*
* #param request
* The HttpServletRequest to be checked and parsed as multipart
* request.
* #return The parsed HttpServletRequest.
* #throws ServletException
* If parsing of the given HttpServletRequest fails.
*/
#SuppressWarnings("unchecked")
// ServletFileUpload#parseRequest() does not return generic type.
private HttpServletRequest parseRequest(HttpServletRequest request)
throws ServletException {
// Check if the request is actually a multipart/form-data request.
if (!ServletFileUpload.isMultipartContent(request)) {
// If not, then return the request unchanged.
return request;
}
// Prepare the multipart request items.
// I'd rather call the "FileItem" class "MultipartItem" instead or so.
// What a stupid name ;)
List<FileItem> multipartItems = null;
try {
// Parse the multipart request items.
multipartItems = new ServletFileUpload(new DiskFileItemFactory())
.parseRequest(request);
// Note: we could use ServletFileUpload#setFileSizeMax() here, but
// that would throw a
// FileUploadException immediately without processing the other
// fields. So we're
// checking the file size only if the items are already parsed. See
// processFileField().
} catch (FileUploadException e) {
throw new ServletException("Cannot parse multipart request: "
+ e.getMessage());
}
// Prepare the request parameter map.
Map<String, String[]> parameterMap = new HashMap<String, String[]>();
// Loop through multipart request items.
for (FileItem multipartItem : multipartItems) {
if (multipartItem.isFormField()) {
// Process regular form field (input
// type="text|radio|checkbox|etc", select, etc).
processFormField(multipartItem, parameterMap);
} else {
// Process form file field (input type="file").
processFileField(multipartItem, request);
}
}
// Wrap the request with the parameter map which we just created and
// return it.
return wrapRequest(request, parameterMap);
}
/**
* Process multipart request item as regular form field. The name and value
* of each regular form field will be added to the given parameterMap.
*
* #param formField
* The form field to be processed.
* #param parameterMap
* The parameterMap to be used for the HttpServletRequest.
*/
private void processFormField(FileItem formField,
Map<String, String[]> parameterMap) {
String name = formField.getFieldName();
String value = formField.getString();
String[] values = parameterMap.get(name);
if (values == null) {
// Not in parameter map yet, so add as new value.
parameterMap.put(name, new String[] { value });
} else {
// Multiple field values, so add new value to existing array.
int length = values.length;
String[] newValues = new String[length + 1];
System.arraycopy(values, 0, newValues, 0, length);
newValues[length] = value;
parameterMap.put(name, newValues);
}
}
/**
* Process multipart request item as file field. The name and FileItem
* object of each file field will be added as attribute of the given
* HttpServletRequest. If a FileUploadException has occurred when the file
* size has exceeded the maximum file size, then the FileUploadException
* will be added as attribute value instead of the FileItem object.
*
* #param fileField
* The file field to be processed.
* #param request
* The involved HttpServletRequest.
*/
private void processFileField(FileItem fileField, HttpServletRequest request) {
if (fileField.getName().length() <= 0) {
// No file uploaded.
request.setAttribute(fileField.getFieldName(), null);
} else if (maxFileSize > 0 && fileField.getSize() > maxFileSize) {
// File size exceeds maximum file size.
request.setAttribute(fileField.getFieldName(),
new FileUploadException(
"File size exceeds maximum file size of "
+ maxFileSize + " bytes."));
// Immediately delete temporary file to free up memory and/or disk
// space.
fileField.delete();
} else {
// File uploaded with good size.
request.setAttribute(fileField.getFieldName(), fileField);
}
}
// Utility (may be refactored to public utility class)
// ----------------------------------------
/**
* Wrap the given HttpServletRequest with the given parameterMap.
*
* #param request
* The HttpServletRequest of which the given parameterMap have to
* be wrapped in.
* #param parameterMap
* The parameterMap to be wrapped in the given
* HttpServletRequest.
* #return The HttpServletRequest with the parameterMap wrapped in.
*/
private static HttpServletRequest wrapRequest(HttpServletRequest request,
final Map<String, String[]> parameterMap) {
return new HttpServletRequestWrapper(request) {
public Map<String, String[]> getParameterMap() {
return parameterMap;
}
public String[] getParameterValues(String name) {
return parameterMap.get(name);
}
public String getParameter(String name) {
String[] params = getParameterValues(name);
return params != null && params.length > 0 ? params[0] : null;
}
public Enumeration<String> getParameterNames() {
return Collections.enumeration(parameterMap.keySet());
}
};
}
}
Thanks in advance.