Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Dividere un'immagine con Actionscript 3

Dividere un'immagine in tante parti può tornare utile in parecchi casi come, per esempio, la creazione di un puzzle, di effetti speciali e altro. Nell'articolo vediamo come sia possibile farlo con AcrtionScript 3
Dividere un'immagine in tante parti può tornare utile in parecchi casi come, per esempio, la creazione di un puzzle, di effetti speciali e altro. Nell'articolo vediamo come sia possibile farlo con AcrtionScript 3
Link copiato negli appunti

Dividere un'immagine, in maniera dinamica, tramite Actionscript, può essere utile per tanti scopi, come ad esempio la creazione di un gioco di puzzle, la scomposizione in più elementi di una foto a grande formato oppure la creazione di particolari effetti visivi.

In questo articolo vedremo come dividere un'immagine tramite Actionscript 3, utilizzando una classe esterna.

Per aprire gli esempi allegati all'articolo è necessario Flash CS3.

Importazione dei package e dichiarazione delle variabili

I passaggi che la classe eseguirà saranno principalmente tre:

  • Impostazione dei parametri per la divisione;
  • Caricamento dell'immagine da dividere;
  • Divisione dell'immagine.

Per eseguire queste operazioni sfrutteremo alcuni package di Actionscript 3, che dovremo quindi importare nella nostra classe, precisamente avremo bisogno dei package:

  • flash.display, che sfrutteremo sia per la divisione dell'immagine (tramite le classi BitmapData e Sprite) sia per caricare l'immagine;
  • flash.geom, che sfrutteremo per la divisione dell'immagine (grazie alle classi Rectangle e Point);
  • flash.events, che useremo per rilevare il completo caricamento dell'immagine;
  • flash.net.URLRequest, comando che verrà utilizzato per caricare l'immagine esterna.

Creiamo quindi un nuovo file Actionscript (File -> New -> Actionscript file), che salveremo con nome dividi.as, e scriviamo questo codice:

package{
  // importiamo il package flash.display
  import flash.display.*;
  // importiamo il package flash.geom
  import flash.geom.*
  // importiamo il package flash.events
  import flash.events.*
  // importiamo il comando URLRequest del package flash.net
  import flash.net.URLRequest
  public class dividi extends MovieClip {

Possiamo ora impostare le variabili necessarie alla nostra classe, che saranno soltanto 3: pezzi_h e pezzi_v, che utilizzeremo per impostare il numero di parti (orizzontali e verticali) in cui dividere l'immagine, e sprite_tasselli che sarà lo sprite dove mostreremo i pezzi dell'immagine creati dalla nostra classe. Ecco il codice da aggiungere al precedente:

    // Impostiamo le variabili per il numero di tasselli
    private var pezzi_h:uint
    private var pezzi_v:uint
    // Creiamo lo sprite dove mostreremo i tasselli
    var sprite_tasselli:Sprite = new Sprite();

A questo punto possiamo passare alla dichiarazione delle funzioni della classe: partiamo dal caricamento dell'immagine.

Caricare l'immagine da dividere

Ovviamente la prima operazione che la classe dovrà eseguire sarà il caricamento dell'immagine: da notare che non mostreremo la foto sullo stage, ma ci servirà solamente come riferimento per la funzione che creerà i tasselli, questi ultimi saranno poi mostrati sullo stage.

Per caricare un'immagine o un filmato esterni in Actionscript 3 si utilizza l'oggetto Loader e il comando URLRequest, che abbiamo infatti importato ad inizio classe. Andiamo allora a creare la funzione imposta_divisione, che prevederà tre parametri: il nome dell'immagine da caricare, il numero di parti orizzontali e il numero di parti verticali da creare. Ecco il codice:

public function imposta_divisione(quale:String,po:uint,pv:uint):void{
  // impostiamo il numero di pezzi orizzontali
  pezzi_h = po
  // impostiamo il numero di pezzi verticali
  pezzi_v = pv
  var carica_foto:Loader = new Loader()
  var richiesta:URLRequest = new URLRequest(quale)
  carica_foto.contentLoaderInfo.addEventListener(Event.COMPLETE,dividi_foto)
  carica_foto.load(richiesta)
}

Possiamo notare i parametri quale (di tipo stringa) e po e pv (di tipo uint), inoltre, poiché la funzione non restituirà alcun valore il tipo del valore di ritorno è impostato su void. All'interno della funzione vediamo l'associazione di po e pi rispettivamente a pezzi_h e pezzi_v, le due variabili dichiarate precedentemente; vengono quindi creati il loader carica_foto e la URLRequest richiesta, quindi associamo al completo caricamento della foto (tramite l'evento Event.COMPLETE) la funzione dividi_foto. Come ultima operazione carichiamo l'URLRequest richiesta all'interno di carica_foto. In questo modo l'immagine verrà caricata all'interno del loader carica_foto; come già detto non vogliamo mostrare la foto sullo stage, notiamo infatti l'assenza del comando addChild.

Ora che abbiamo impostato il caricamento della foto possiamo passare alla funzione che si occuperà di ricavare i tasselli dall'immagine originale, ovvero dividi_foto, che ricordiamo verrà avviata soltanto una volta completato il caricamento dell'immagine esterna nel filmato SWF.

Effettuare la divisione dell'immagine

La funzione di divisione si occuperà, per prima cosa, di creare una copia dell'immagine caricata e di stabilire le dimensioni dei tasselli da creare, valori che verranno determinati in base alle dimensioni della foto e al numero di tasselli dichiarati nella funzione imposta_divisione. Una volta ricavati questi valori utilizzeremo due cicli for per "muoverci" all'interno dell'immagine e copiare di volta in volta il pezzo desiderato.

Vediamo per prima cosa il codice della funzione:

public function dividi_foto(chi:Event):void{
  // creiamo una copia dell'immagine
  var immagine:Bitmap = Bitmap(chi.target.loader.content);
  // stabiliamo larghezza e altezza di ogni pezzo
  var l_pezzo = Math.floor(immagine.width/pezzi_h)
  var a_pezzo = Math.floor(immagine.height/pezzi_v)
  // iniziamo il taglio dei pezzi
  for(var r:uint=0;r<pezzi_h;r++){ // percorriamo tutte le righe
    for(var c:uint=0;c<pezzi_v;c++){ // e tutte le colonne
      // creiamo una bitmap con le dimensioni del pezzo del puzzle
      var img_pezzo:Bitmap = new Bitmap(new BitmapData(l_pezzo,a_pezzo));
      // copiamo i pixel dall'immagine originale al pezzo creato
      img_pezzo.bitmapData.copyPixels(immagine.bitmapData,new Rectangle(r*l_pezzo,c*a_pezzo,l_pezzo,a_pezzo),new Point(0,0));
      // creiamo un nuovo sprite
      var sprite_pezzo:Sprite = new Sprite();
      // inseriamo nello sprite la bitmap creata
      sprite_pezzo.addChild(img_pezzo);
      // inseriamo lo sprite "sprite_pezzo" dentro a "sprite_tasselli"
      sprite_tasselli.addChild(sprite_pezzo)
    }
  }
  // aggiungiamo sprite_tasselli allo stage
  addChild(sprite_tasselli)
}

Il codice aiuterà a capire la spiegazione dei vari passaggi; abbiamo già parlato della creazione della copia dell'immagine (immagine) e dell'impostazione di larghezza e altezza dei tasselli (l_pezzo e a_pezzo); abbiamo a questo punto due cicli for annidati uno dentro l'altro: praticamente per ogni riga dell'immagine (il numero di righe da usare è stabilito dalla variabile pezzi_h) percorriamo verticalmente l'immagine per il numero di colonne (stabilito dalla variabile pezzi_v); per ogni passaggio di questo secondo ciclo avverrà la duplicazione di un tassello dell'immagine originale.

La duplicazione avviene creando un nuovo oggetto di tipo Bitmap (img_pezzo) che avrà dimensioni stabilite dalle variabili l_pezzo e a_pezzo; inizialmente questo tassello sarà vuoto, ma subito dopo vi copieremo un pezzo dell'immagine originale grazie al comando copyPixels. Questo comando, come dice già il suo nome, si occupa di copiare dei pixel in un oggetto bitmapData estrapolandoli da un altro bitmapData: in questo caso copiamo all'interno di img_pezzo i pixel dell'immagine originale (immagine.bitmapData) compresi in un rettangolo stabilito dai valori di r e c (rispettivamente riga e colonna dell'immagine attualmente analizzate) e da l_pezzo e a_pezzo. L'ultimo parametro (new Point(0,0)) serve per impostare il punto di destinazione del rettangolo copiato dall'immagine originale, che nel nostro caso sarà 0,0 dato che per ogni tassello abbiamo un nuovo sprite.

Il concetto può sembrare un po' complicato, ma osservando il comportamento del filmato sarà sicuramente più facile comprendere il procedimento.

Una volta che abbiamo la copia dentro ad img_pezzo, semplicemente inseriamo questo oggetto (che ricordiamo è di tipo Bitmap) all'interno di uno sprite creato appositamente (sprite_pezzo), che a sua volta verrà aggiunto a sprite_tasselli. Una volta conclusi i cicli di duplicazione delle parti dell'immagine andiamo a mostrare sullo stage lo sprite contenente tutti i pezzi, grazie al comando addChild(sprite_tasselli).

Ecco il codice completo della classe:

package{
  // importiamo il package flash.display
  import flash.display.*;
  // importiamo il package flash.geom
  import flash.geom.*
  // importiamo il package flash.events
  import flash.events.*
  // importiamo il comando URLRequest del package flash.net
  import flash.net.URLRequest
  
  public class dividi extends MovieClip {
    // Impostiamo le variabili per il numero di tasselli
    private var pezzi_h:uint
    private var pezzi_v:uint
    // Creiamo lo sprite dove mostreremo i tasselli
    var sprite_tasselli:Sprite = new Sprite();
    
    public function imposta_divisione(quale:String,po:uint,pv:uint):void{
      // impostiamo il numero di pezzi orizzontali
      pezzi_h = po
      // impostiamo il numero di pezzi verticali
      pezzi_v = pv
      var carica_foto:Loader = new Loader()
      var richiesta:URLRequest = new URLRequest(quale)
      carica_foto.contentLoaderInfo.addEventListener(Event.COMPLETE,dividi_foto)
      carica_foto.load(richiesta)
    }
    
    public function dividi_foto(chi:Event):void{
      // creiamo una copia dell'immagine
      var immagine:Bitmap = Bitmap(chi.target.loader.content);
      // stabiliamo larghezza e altezza di ogni pezzo
      var l_pezzo = Math.floor(immagine.width/pezzi_h)
      var a_pezzo = Math.floor(immagine.height/pezzi_v)
      // tagliamo i vari pezzi
      for(var r:uint=0;r<pezzi_h;r++){ // percorriamo tutte le righe
        for(var c:uint=0;c<pezzi_v;c++){ // e tutte le colonne
          // creiamo una bitmap con le dimensioni del pezzo del puzzle
          var img_pezzo:Bitmap = new Bitmap(new BitmapData(l_pezzo,a_pezzo));
          // copiamo i pixel dall'immagine originale al pezzo creato
          img_pezzo.bitmapData.copyPixels(immagine.bitmapData,new Rectangle(r*l_pezzo,c*a_pezzo,l_pezzo,a_pezzo),new Point(0,0));
          // creiamo un nuovo sprite
          var sprite_pezzo:Sprite = new Sprite();
          // inseriamo nello sprite la bitmap creata
          sprite_pezzo.addChild(img_pezzo);
          // inseriamo lo sprite "sprite_pezzo" dentro a "sprite_tasselli"
          sprite_tasselli.addChild(sprite_pezzo)
        }
      }
      // aggiungiamo sprite_tasselli allo stage
      addChild(sprite_tasselli)
    }
  }
}

Test del filmato

Possiamo ora creare un nuovo file Actionscript 3, dove andremo ad impostare dividi come Document Class.

Figura 1. Impostazione della Document Class
Screenshot del pannello

Salviamo il FLA nella stessa cartella di dividi.as e inseriamo questo codice sul primo fotogramma:

imposta_divisione("Tramonto.jpg",5,5)

Testando il filmato noteremo come i tasselli vengano posizionati tutti uno sopra l'altro

Figura 2. Test del filmato
Screenshot del filmato

A questo punto abbiamo varie scelte su come modificare il codice della classe e tutto dipende dalle nostre esigenze: ad esempio, potremmo optare per un posizionamento casuale, modificando in questo modo la funzione dividi_foto:

public function dividi_foto(chi:Event):void{
  // creiamo una copia dell'immagine
  var immagine:Bitmap = Bitmap(chi.target.loader.content);
  // stabiliamo larghezza e altezza di ogni pezzo
  var l_pezzo = Math.floor(immagine.width/pezzi_h)
  var a_pezzo = Math.floor(immagine.height/pezzi_v)
  // tagliamo i vari pezzi
  for(var r:uint=0;r<pezzi_h;r++){ // percorriamo tutte le righe
    for(var c:uint=0;c<pezzi_v;c++){ // e tutte le colonne
      // creiamo una bitmap con le dimensioni del pezzo del puzzle
      var img_pezzo:Bitmap = new Bitmap(new BitmapData(l_pezzo,a_pezzo));
      // copiamo i pixel dall'immagine originale al pezzo creato
      img_pezzo.bitmapData.copyPixels(immagine.bitmapData,new Rectangle(r*l_pezzo,c*a_pezzo,l_pezzo,a_pezzo),new Point(0,0));
      // creiamo un nuovo sprite
      var sprite_pezzo:Sprite = new Sprite();
      sprite_pezzo.x = Math.random()*500
      sprite_pezzo.y = Math.random()*400
      // inseriamo nello sprite la bitmap creata
      sprite_pezzo.addChild(img_pezzo);
      // inseriamo lo sprite "sprite_pezzo" dentro a "sprite_tasselli"
      sprite_tasselli.addChild(sprite_pezzo)
    }
  }
  // aggiungiamo sprite_tasselli allo stage
  addChild(sprite_tasselli)
}

Figura 3. Posizionamento casuale dei tasselli
Screenshot del filmato

In alternativa potremmo sfruttare gli eventi per rendere trascinabili i vari tasselli, o altro ancora: a voi la possibilità di sperimentare le numerose possibilità di utilizzo di questa immagine divisa.

Ti consigliamo anche