Imagens de grandes dimensões levam a uma OufOfMemoryException
-
28-10-2019 - |
Pergunta
Estou usando o OpenMap e preciso carregar imagens de dimensões muito grandes.
Tentei carregar essas imagens como um grande raster que falhou com um OufOfMemoryException.No modo de depuração, o construtor de camada me diz que as dimensões da imagem são muito grandes.
Em uma lista de e-mails OpenMap, encontrei o MyJAIPlugin, que me permite carregar e exibir arquivos GeoTiff.
Como posso mostrar um GeoTiff de 300 MB no OpenMap?
Solução
Tive quase a mesma situação ao carregar mapas HD com pelo menos 690 MB de tamanho de arquivo.
Eu também usei o JAIPlugIn da lista de discussão e internamente eles usam o OMScalingRaster que funciona com um BufferedImage. Isso limita o tamanho da imagem e causa a mensagem de depuração.
Eu resolvi isso modificando o OMScalingRaster. Eu mudei o BufferedImage para um TiledImage para lidar com imagens grandes e consertei os próximos erros. Aqui é importante que você altere o método scaleTo (Projection thisProj) para dimensionar com JAI.
Agora posso carregar o arquivo e ele é renderizado no mapa. Mas se você estiver diminuindo muito o zoom, ele lançará uma OutOfMemoryException porque na minha modificação eu faço uma subimagem da parte da imagem que será visível e a dou como BufferedImage para o OMRaster.
Aqui está o mod. no final do método scaleTo:
// Now we can grab the bit we want out of the source
// and
// scale it to fit the intersection.
// Calc width adjustment
float widthAdj = (float) ((double) iRect.width
/ (double) clipRect.width);
// Calc height adjustment
float heightAdj = (float) ((double) iRect.height
/ (double) clipRect.height);
// Create the transform
// JAI-Version
ParameterBlock pb = new ParameterBlock();
pb.addSource(sourceImage.getSubImage(clipRect.x,
clipRect.y,
clipRect.width,
clipRect.height).getAsBufferedImage());
pb.add(widthAdj); // The xScale
pb.add(heightAdj); // The yScale
pb.add(0.0F); // The x translation
pb.add(0.0F); // The y translation
RenderedOp newImage = JAI.create("scale",pb, null);
bitmap = newImage.getAsBufferedImage();
point1.setLocation(iRect.x, iRect.y);
// setVisible(currentVisibility);
}
} else {
bitmap = null;
}
}
Para os outros erros, substituindo BufferedImage por TiledImage, use os métodos TiledImage equivalentes. Mas para economizar memória, você deve usar o construtor TiledImage com o sinalizador sharedDataBuffer= true.
Por exemplo, este mod. pode lidar com mapas (690 MB compactados) com escala de 1: 50000 e posso diminuir o zoom para 1: 600000 antes que a camada diga que ficou sem memória.