2016-05-30 3 views
1

J'ai besoin de lire et d'écrire des images pixel par pixel (je produisais des fractales). Comme j'ai expérimenté avec les tailles d'image, j'ai réalisé que l'écriture à une image en utilisant BufferedImage lorsque la taille de l'image est énorme (disons 24000x18000), conduit à un . Pour y remédier, j'ai utilisé -Xmx -Xms pour augmenter la taille du tas.Lire et écrire une grande image

Existe-t-il un moyen d'écrire sur une image avec des pixels sans avoir à charger l'intégralité de l'image dans la mémoire? Il en va de même pour la lecture (et la modification) de grandes images.

EDIT

Je fais pixel par pixel, de gauche à droite, de haut en bas.

+2

Êtes-vous _générant_ l'image pixel par pixel, de gauche à droite, de haut en bas?Si oui, vous pourriez être en mesure de l'écrire en série. Cependant, si vous devez générer l'image complètement avant de l'écrire, vous devrez d'abord la mémoriser. Votre question n'est pas claire ... –

+0

@JimGarrison Oui, je le fais pixel par pixel, de gauche à droite, de haut en bas. Pourriez-vous s'il vous plaît répondre comment le faire en série? –

+1

Vous devrez probablement contourner le code d'image standard et écrire le format d'image directement. Ce sera probablement un peu de travail, et est en dehors de mon expertise. Peut-être que quelqu'un d'autre va répondre. Plutôt que de virer de bord, je vous suggère de réécrire la question pour expliquer plus clairement ce que vous faites. –

Répondre

4

La solution la plus simple consiste généralement à ajouter plus de mémoire. :-)

Cependant, il y a quelques options (je ne trouve pas assez d'informations dans votre question de décider lequel est le meilleur, pensez à mettre à jour):

  • Ecrire un en-tête de format minimal (BMP est assez facile, TIFF est également faisable) pour votre image, allouer l'espace disque nécessaire pour votre image dans ce format, et la carte de la mémoire de cette région. Ce sera similaire à travailler avec de la mémoire virtuelle. Le système va copier les zones du fichier dans la mémoire à la fois, donc vous devriez travailler sur des régions limitées à la fois pour éviter trop de permutation.

  • J'ai écrit quelques classes pour permettre l'utilisation d'un tel fichier en tant que (plutôt lent) BufferedImage, MappedImageFactory et . Ceux-ci peuvent soit être combinés avec ce qui précède, avoir un fichier de mise à jour "live", ou utiliser l'API ImageIO plus familière pour lire/écrire des fichiers volumineux (code spécial nécessaire pour lire dans une telle image, voir MappedImageFactory.createCompatibleMappedImage(w, h, type) et ImageReadParam.setDestination(image)).

  • Utilisez l'API ImageIO pour lire et écrire des mosaïques (régions de taille fixe). Le seul format d'image que je connaisse supporte nativement les tuiles, c'est le format TIFF. Je pense que le TIFFImageReader et le TIFFImageWriter de ja_imageio.jar prendront en charge le pavage. L'API RenderedImage prend également en charge le pavage. La mosaïque pourrait probablement être également combinée avec la technique de mappage de la mémoire, pour de meilleures performances (c'est-à-dire copier les mosaïques à BufferedImage pour des opérations Java2D plus rapides).

  • Utilisez l'API ImageIO pour lire et écrire des sous-régions arbitraires. La lecture d'une région est facile, en utilisant ImageReadParam.setSourceRegion(...). La méthode ImageWriter.canReplacePixels() vous indiquera si l'enregistreur prend en charge l'écriture de régions. Malheureusement, je ne connais aucune implémentation de ImageWriter qui supporte actuellement cela, mais en théorie cela devrait être assez facile pour n'importe quel format non compressé, si vous voulez l'implémenter vous-même.

Cette liste n'est probablement pas exhaustive.

+0

Merci pour votre réponse. C'est très détaillé. Je vais attendre un certain temps et marquera ceci comme réponse si je n'en obtiens pas une meilleure. –

1

Je suis d'accord avec les solutions proposées par haraldK. 18Kx24K peut facilement être chargé dans la mémoire. Mais comme vous allez pixel par pixel, vous pouvez également utiliser un BigBufferedImage qui a été présenté dans this post. L'image n'est pas chargée dans la mémoire, mais stockée dans un fichier.