Chargement rapide et le dessin de données RVB dans BufferedImage
Dans certains code Java en cours d'exécution sur Windows, je suis en train de lire quelques gros blocs de données RVB à partir d'un disque et que vous voulez afficher ce à écran aussi vite que possible. Les données RVB 8 bits par canal, sans alpha. Actuellement, j'ai le code suivant pour créer le BufferedImage.
BufferedImage getBufferedImage(File file, int width, int height) {
byte[] rgbData = readRGBFromFile(file);
WritableRaster raster = Raster.createInterleavedRaster(
rgbData, width, height,
width * 3, //scanlineStride
3, //pixelStride
new int[]{0, 1, 2}, //bandOffsets
null);
ColorModel colorModel = new ComponentColorModel(
ColorSpace.getInstance(ColorSpace.CS_sRGB),
new int[]{8, 8, 8}, //bits
false, //hasAlpha
false, //isPreMultiplied
ComponentColorModel.OPAQUE,
DataBuffer.TYPE_BYTE);
return new BufferedImage(colorModel, raster, false, null);
}
Le problème est que les performances de rendu présent à l'écran est assez lent. Environ 250 - 300 ms. J'ai lu que pour la meilleure performance dont vous avez besoin dans un BufferedImage compatible avec l'écran. Pour ce faire, je passe de la mémoire tampon de l'image renvoyée de la méthode ci-dessus pour une méthode de ce genre.
BufferedImage createCompatibleImage(BufferedImage image)
{
GraphicsConfiguration gc = GraphicsEnvironment.
getLocalGraphicsEnvironment().
getDefaultScreenDevice().
getDefaultConfiguration();
BufferedImage newImage = gc.createCompatibleImage(
image.getWidth(),
image.getHeight(),
Transparency.TRANSLUCENT);
Graphics2D g = newImage.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
return newImage;
}
Cette méthode convertit essentiellement à partir de l'espace RVB à l'ARGB sur Windows et il accélère vraiment, l'affichage, mais cette méthode prend ~300 ms pour un 1600 x 1200 RVB bloc de données. Alors maintenant, j'ai essentiellement négociés les performances du dessin problème à une conversion de problème.
300ms est d'environ le même temps qu'il faut pour charger les données RVB en données à partir du disque. Je pense que je pourrais faire quelque chose de plus rapide.
Est-il une meilleure façon que je peux faire la conversion? Ou serait-il aider si j'ai modifié les données RVB et ajouter un canal alpha moi-même à l'avance? Si oui, quel serait mon Raster et modèle colorimétrique. Aussi, depuis mon RVB de données ne contient pas de transparence puis-je obtenir toutes les améliorations de performances par l'utilisation de pré multiplié alpha ou quelque chose?
Désolé, bits, je suis un peu perdu sur ce modèle colorimétrique, Raster choses.
Merci!
OriginalL'auteur awinbra | 2011-06-12
Vous devez vous connecter pour publier un commentaire.
Je réalise que c'est une très vieille question, je suis en train de poster ce pour quelqu'un d'autre qui pourrait trébucher sur cette question à la recherche pour plus d'options. J'ai eu un problème récemment, où j'ai été de tenter de prendre un grand (720p) RGB byte[] et le rendre à un
BufferedImage
. La mise en œuvre d'origine j'ai été en utilisant cherché quelque chose comme ceci (simplifiée ici):Même avec les optimisations comme la création de la
BufferedImage
etComponentSampleModel
une fois et de les réutiliser, la dernière étape de l'appel d'setData
sur leBufferedImage
toujours de l'ordre de 50 à 60 millisecondes, ce qui est inacceptable.Ce que j'ai conscience, c'est que, au moins pour mon scénario, vous pouvez écrire à la sauvegarde de tableau d'octets de la
BufferedImage
directement et de contourner la plupart des intermédiaires de traitement (en supposant que la sauvegarde des métadonnées de l'image est déjà correct). J'ai donc modifié mon code ressemble à ceci:Juste en faisant cela, ma performance améliorée par un facteur d'environ 20. Je vais maintenant traiter les mêmes images en 3 à 5 millisecondes au lieu de 50 à 60 millisecondes.
Cela peut ne pas être applicable à tous les cas, mais je pensais que je partage au cas où quelqu'un d'autre le trouve utile.
BufferedImage
pour obtenir cette stupidesetData()
de travailler plus vite. Vous m'avez sauvé, merci! 🙂Je suis confus... Ce qui se passe exactement ici? que
System.arraycopy()
semble écraser laimgData
. Ne devrait-elle pas être l'inverse?Il a été un moment depuis que j'ai posté, donc pardon si ce manque...
imgData
est une référence à la réalité debyte[]
(stocké comme une variable de membre de la BufferedImage de WritableRaster), qui est utilisé pour afficher l'image par l'BufferedImage
classe.frame
est unbyte[]
j'ai construit que je veux rendre via un BufferedImage. Si le Système.arraycopy(...) les copies de l'image que j'ai construit (contenues dansframe
) à la sauvegarde debyte[]
dans les entrailles de laBufferedImage
. Maintenant, quand leBufferedImage
est rendu, c'est fait en utilisant les données deframe
que j'ai copié dans leBufferedImage
lui-mêmeOriginalL'auteur Brent Writes Code
Après avoir joué un peu avec ce que j'ai une vie décente réponse qui fonctionne pour Windows si la configuration graphique est à l'aide de ARGB entier emballé rasters.
Ce que j'ai à faire est de créer le compatible BufferedImage d'abord, puis-je convertir manuellement mon RVB tableau d'octets à un ARGB tableau int. Puis-je obtenir la trame du compatible BufferedImage et d'écrire ma ARGB ints. C'est beaucoup plus rapide.
Moi aussi j'ai une classe qui vérifie si le compatible BufferedImage est dans le format que j'attends, si ce n'est pas la valeur par défaut est l'ancienne approche plus lente.
Ici, c'est la classe. Espérons qu'il vous aide.
Compatabile
->Compatible
dans la source. 2) la Marque de votre réponse "correcte".+1... j'allais oublier que le modèle colorimétrique retardedness vraiment ralentit tout (jusqu'à 3 ORDRES DE GRANDEUR SUR CERTAINES VERSIONS OS X, oui, plus de 1000 fois plus lentes**!**) et prévoit rien sur le fond (sérieusement, comment de nombreux professionnels de l'image/la vidéo de la manipulation de l'édition écrite en Java sont là-bas? C'est vrai, zéro...) par rapport au fait de travailler directement avec int[]. C'est un autre cas de "zomg nous avons des objets, nous allons overthink et suremballage tout pour aucune raison". int[] primitives de manipulation pour la victoire: c'est la façon dont vous le faites lorsque la vitesse est un sujet de préoccupation.
Oui ma vitesse jusqu'passée d'environ 300ms à moins de 15ms.
Excellent merci, cela fonctionne aussi pour OPAQUE si vous ignorez l'Alpha, et elle fonctionne sur Linux. Augmentation considérable de la vitesse sur les deux. Note sur Win7, j'ai trouvé la BufferedImage.TYPE_INT_ARGB est TYPE_INT_ARGB_PRE, mais doit encore fonctionner si vous indemniser.
eh bien, dans ce cas, vous obtenez une belle 66.6666666667 FPS dans un jeu, de sorte que c'est, de loin, excellent. Toutefois, j'ai le pire CPU jamais. Je serais probablement obtenir seulement 44 🙁
OriginalL'auteur awinbra