2013-04-18 3 views
10

È possibile eseguire il rendering di un'immagine ridimensionata in un ImageView in JavaFX 2.2 senza applicare alcun livellamento? Sto riproducendo un'immagine 50x50 in un ImageView 200x200, con setSmooth (falso), quindi ogni pixel dell'immagine sorgente dovrebbe essere mappato su un quadrato 4x4 sullo schermo.JavaFX ImageView senza livellamento

Tuttavia, il rendering risultante liscia ancora il pixel di origine su tutti i 16 pixel di destinazione. Qualcuno sa di un modo per farlo senza copiare manualmente su ogni pixel una nuova immagine?

+0

Si può provare Canvas per ottenere il massimo controllo. –

+0

Purtroppo non penso che ci sia un modo per farlo anche su una tela. Quello che devono realmente fare è permetterci di creare i nostri filtri 2D (suppongo che siano chiamati "Effetti" in JavaFX). – ajselvig

+0

Aggiornato la mia risposta con idee sull'implementazione del proprio filtro immagine. – jewelsea

risposta

15

In JavaFX 2.2 ImageView è sempre possibile eseguire un livellamento indipendentemente dall'indicazione smooth fornita allo ImageView.

(Basato su test utilizzando Java 7u15 e Windows 7 con una scheda grafica ATI HD4600).

forse è un bug che ImageView sarà sempre lisciare il Image, ma la documentazione in realtà non specificano esattamente cosa lisciatura fa o non fa, quindi è difficile dire quale sia la sua vera intenzione è. Si consiglia di inviare un riferimento a questa domanda allo openjfx-dev mailing list o registrare un problema nello JavaFX issue tracker per ottenere un parere più esperto da uno sviluppatore.


ho provato un paio di metodi diversi per ridimensionare l'immagine:

  1. Scala nella Image constructor.
  2. Scala in ImageView con fitWidth/fitHeight.
  3. Scala utilizzando le proprietà scaleX/scaleY su un ImageView.
  4. Scala campionando Image con un PixelReader e creando una nuova immagine con un PixelWriter.

ho scoperto che i metodi 1 & 4 comportato un immagine nitida pixel come si desidera e 2 & 3 ha comportato un'immagine sfocata alias.

robot-sampling

Sample code per generare l'uscita di cui sopra.


aggiornamento con le idee su l'implementazione del proprio filtro immagine

Un Effetto JavaFX non è lo stesso del filtro utilizzato per le routine di caricamento delle immagini, anche se un effetto a filtrare l'immagine potrebbe essere creato. In JavaFX 2.2 API documentate pubblicamente per supportare la creazione di effetti personalizzati, quindi la creazione di un effetto personalizzato potrebbe risultare difficile.

Il native code for image support è stato aperto di recente come parte del openjfx project, quindi è possibile vedere che per vedere come il filtro è attualmente implementato.

Si consiglia inoltre di archiviare un feature request against the JavaFX runtime project in "consentirci di creare i propri filtri 2D".

+1

Hai sempre dato risposte così impressionanti jewelsea: D –

+1

Sì, grazie per la risposta dettagliata. Sono arrivato alla stessa conclusione e ho finito per implementare il n. L'implementazione stessa è banale, ma temo che sia molto più lenta di # 2 o # 3 (anche se non l'ho ancora verificato). – ajselvig

+2

Sono passati due anni da questa risposta. Qualcuno sa se questo è stato risolto in JavaFX? –

1

So che questo è un po 'più vecchio, ma di recente ho avuto bisogno di tale ImageView, e il seguente piccolo hack fa esattamente quello che voglio sulla mia macchina (Windows). Non garantisce che funzioni ovunque.

import com.sun.javafx.sg.prism.NGImageView; 
import com.sun.javafx.sg.prism.NGNode; 
import com.sun.prism.Graphics; 
import com.sun.prism.Texture; 
import com.sun.prism.impl.BaseResourceFactory; 

import com.sun.prism.Image; 
import javafx.scene.image.ImageView; 

@SuppressWarnings("restriction") 
public class PixelatedImageView extends ImageView { 
    @Override protected NGNode impl_createPeer() { 
     return new NGImageView() { 
      private Image image; 

      @Override public void setImage(Object img) { 
       super.setImage(img); 
       image = (Image) img; 
      } 

      @Override protected void renderContent(Graphics g) { 
       BaseResourceFactory factory = (BaseResourceFactory) g.getResourceFactory(); 
       Texture tex = factory.getCachedTexture(image, Texture.WrapMode.CLAMP_TO_EDGE); 
       tex.setLinearFiltering(false); 
       tex.unlock(); 
       super.renderContent(g); 
      } 
     }; 
    } 
} 

Il trucco è che la trama viene riutilizzato, per cui l'impostazione filtraggio lineare rimane "appiccicoso". Perché il NGImageView non può semplicemente passare il flag "liscio" all'impostazione del filtro lineare della trama, tuttavia è al di là di me.

+0

Sembra che non vogliono che tu faccia questo. – Nolan

+0

Questo ha funzionato per Java 8, ma sembra che le funzioni qui menzionate siano state rinominate e impostate su funzioni private in Java 9. Non sembra che possa essere sovrascritto allo stesso modo senza modifiche significative a 'ImageView' e' ImageViewHelper' . Qualcuno ha capito come aggirare le nuove restrizioni in Java 9? – ddukki

0

Quando si aggiunge il seguente costruttore alla risposta di Martin Sojka, è sufficiente passare l'immagine javafx al costruttore. Inoltre, nonostante gli avvertimenti sulle funzioni deprecate, la sua risposta funziona ancora bene (su JDK 1.8_121).

public PixelatedImageView (javafx.scene.image.Image image) { 
    super(image); 
}