MokaByte Numero 27  -  Febbraio 1999
 
Codifica di un oggetto
Image in formato GIF
di 
Paolo Milani
Poter salvare immagini, create direttamente dal programma Java,  in un formato universale come il gif è sicuramente una utile funzioanlità da aggigunere ai propri programmi


Un problema molto comune ai programmatori Java consiste nel salvare un oggetto Image (o ImageProducer) in un formato di interscambio per altre applicazioni. 
In questo articolo vedremo come è semplice effettuare questa operazione utilizzando le classi messe a disposizione dal package JPM di ACME (reperibile al sito http://www.acme.com/java).

Il package ACME

Il package ACME viene distribuito con i sorgenti commentati in formato Javadoc e comprende numerose classi:
    Package Acme.Crypto: implementa i principali algoritmi di crittografia
    Package Acme.JPM
    Acme.JPM.Decoders: istanzia un oggetto Image a partire da un file in formato GIF o JPG.
    Acme.JPM.Encoders: salva un oggeto Image in formato GIF o JPG.
    Acme.JPM.Filter: effettua operazioni di filtro su oggetti di tipo Image o ImageProducer (smoothing, flip, gamma correction, ecc…).
    Package Acme.Nnrpd: realizza un demone NNRP multi-threaded
    Acme.Serve: insieme di classi utili per realizzare CGI in tecnologia servlet
    Acme.Widgets: classi di interfaccia grafica che realizzano le principali dialog per la comunicazione con gli utenti (OkDialog, YesNoBox, YesNoCancelBox, ecc…).
Nel presente articolo ci limiteremo a vedere come funzionano le classi presenti nel package Acme.JPM.Encoders. Considerazioni analoghe varranno anche per i package Decoders e Filters.

Scrivere un oggetto Image su file
Utilizzare le classi ACME per scrivere un oggetto Image su file è molto semplice. Le operazioni da eseguire sono le seguenti:
 

1 try{
2 DataOutputStream dos = new DataOutputStream(new FileOutputStream( new File("snapshot.gif")));
3 Acme.Jpm.encoders.ImageEncoder ie = new Acme.Jpm.encoders.GifEncoder(myImage, dos );
4 ie.encode();
5 } catch (Exception ee) {
6 System.out.println(ee.toString());
7 }


Vale un analogo discorso per i formati Jpeg e Ppm. Le classi che realizzano la codifica, infatti, sono estensioni della classe astratta ImageEncoder e come tali sono state specializzate in relazione al formato di codifica.. Sostituendo la riga 3 con le seguenti si ottiene rispettivamente la codifica in formato Jpeg e Ppm.
 

Acme.Jpm.encoders.ImageEncoder ie = new Acme.Jpm.encoders.JpegEncoder(myImage, dos );
Acme.Jpm.encoders.ImageEncoder ie = new Acme.Jpm.encoders.PpmEncoder(myImage, dos );


Se l'oggetto Image non è pronto subito?
Osservando i costruttori delle classi ACME che realizzano la codifica si nota che accettano in ingresso oggetti di tipo ImageProducer. Oggetti di questo tipo sono molto utili nel caso in cui l'immagine non è subito pronta per essere salvata su file (ad esempio potrebbe essere in fase di scaricamento dalla Rete). In questo caso cercando di codificare un oggetto Image (quando ancora non è "pronto" per essere codificato) si otterrebbe un file grafico distorto (l'immagine non sarebbe quella voluta). E' necessario che l'encoder abbia a disposizione un sistema per capire quando l'immagine è pronta per essere salvata su file. Questo meccanismo può essere realizzato in Java attraverso oggetti di tipo ImageProducer.
 

ImageProducer prod = myObject.getProducer();
Acme.JPM.Encoders.ImageEncoder ie = new Acme.JPM.Encoders.GifEncoder( prod, out );
ie.encode();

Un esempio

Nel seguente esempio viene mostrato come può essere utilizzato l'encoder ACME per salvare un'immagine scaricata dalla rete utilizzando un oggetto di tipo ImageProducer.
 
// ToGif - dump out an image URL as GIF
//
// Given a URL as argument, it fetches the file and writes it onto stdout
// in the GIF image file format.
//
// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. 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.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 THE AUTHOR OR CONTRIBUTORS 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.
//
// Visit the ACME Labs Java page for up-to-date versions of this and other
// fine Java utilities: http://www.acme.com/java/
import java.net.*;
import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.image.*;
public class ToGif extends Acme.Application{
  static final String progName = "ToGif";
  // Old-style main() routine. Calls compatibility routine for newMain().
  public static void main( String[] args ){
   (new ToGif()).compat( args );
  }
  public int newMain( String[] args ){
   int argc = args.length;
   if ( argc != 1 ){
    usage();
  return -1;
  }
  dump( args[0] );
  return 0;
  }
  private void usage(){
   err.println( "usage: " + progName + " URL" );
  }
// Got to make one of these even if we don't use it, cause it loads
// in some necessary native methods.
private Toolkit tk = new Acme.JPM.StubToolkit();
private void dump( String urlStr ){
  try{
   URL url = new URL( urlStr );
   URLConnection uc = url.openConnection();
   uc.connect();
   // Got to open a stream to get around Java NullPointerException bug.
   InputStream f = uc.getInputStream();
   String mimeType = uc.getContentType();
   // Java prints (not throws!) a ClassNotFoundException if you try
   // a getContent on text.html or audio/basic (or no doubt many
   // other types).
  if ( ! mimeType.startsWith( "image/" ) )
    err.println( progName + ": " + urlStr + " is not an image" );
  else{
    Object content = uc.getContent();
      if ( ! ( content instanceof ImageProducer ) )
        err.println(progName + ": " + urlStr +" is not a known image type" );
      else{
         ImageProducer prod = (ImageProducer) content;
         Acme.JPM.Encoders.ImageEncoder ie = new Acme.JPM.Encoders.GifEncoder( prod, out );
         ie.encode();
      }
    }
   // Done with unnecessary stream.
   f.close();
  }
  catch ( Exception e ){
    err.println( progName + ": " + e );
  }
 }
}


 

 
MokaByte ricerca nuovi collaboratori. Chi volesse mettersi in contatto con noi può farlo scrivendo a mokainfo@mokabyte.it