如何在Java中处理RAM中的海量数据/图像? 总结 我正在读一个包含图像数据的大二进制文件 对数据执行累积计数切割分析[它需要另一个与图像大小相同的数组] 将存储在buffereImage中的数据逐像素拉伸到0到255之间,以便在JPanel上绘制图像 在此图像上,使用仿射变换执行缩放 问题
小图像(1.5GB)如何在Java中处理RAM中的海量数据/图像? 总结 我正在读一个包含图像数据的大二进制文件 对数据执行累积计数切割分析[它需要另一个与图像大小相同的数组] 将存储在buffereImage中的数据逐像素拉伸到0到255之间,以便在JPanel上绘制图像 在此图像上,使用仿射变换执行缩放 问题,java,graphics2d,Java,Graphics2d,小图像(1.5GB) 当加载一个巨大的图像(>1.5GB)时,会出现与中相同的异常 1.1,即使图像小到可以加载,有时也会出现同样的错误 尝试过的解决方案 我尝试使用替代BuffereImage来存储拉伸数据BigBufferedImage image=BigBufferedImage.create(newCol,newRow,BufferedImage.TYPE_INT_ARGB) 但无法将其传递给g2d.drawImage(image,0,0,this) 因为JPanel的重新绘制方法由
- 当加载一个巨大的图像(>1.5GB)时,会出现与中相同的异常 1.1,即使图像小到可以加载,有时也会出现同样的错误
BigBufferedImage image=BigBufferedImage.create(newCol,newRow,BufferedImage.TYPE_INT_ARGB)代码>
g2d.drawImage(image,0,0,this)代码>
因为JPanel的重新绘制方法由于某种原因而停止
图像大小
Xmx
Xms
问题
83Mb
512m
256m
工作
83Mb
3096米
2048米
系统挂起
3.84Gb
512m
256m
java.lang.OutOfMemoryError:java堆空间
3.84Gb
3096米
512m
java.lang.OutOfMemoryError:java堆空间
OutOfMemoryError
这是自我解释-您的内存不足。也就是说,不是机器上的物理RAM,而是JVM达到了-xmx
设置设置的内存分配上限仔细查看API所建议的(
readTile
method)可能只读取图像区域(例如用于放大)您可以读取图像的特定部分,然后为显示目的以降低分辨率缩放它
因此,在您的例子中,您可以在块中读取图像(读取图像部分,就像我们逐行从db读取数据一样)
例如:
// Define the portion / row size 50px or 100px
int rowHeight = 50;
int rowsToScan = imageHeight / rowHeight;
if(imageHeight % rowHeight > 0) rowsToScan++;
int x = 0;
int y = 0;
int w = imageWidth;
int h = rowHeight;
ArrayList<BufferedImage> scaledImagePortions = new ArrayList<>();
for(int i = 1; i <= rowsToScan; i++) {
// Read the portion of an image scale it
// and push the scaled version in lets say array
BufferedImage scalledPortionOfImage = this.getScaledPortionOfImage(img, x, y, w, h);
scaledImagePortions.add(scalledPortionOfImage);
y = (rowHeight * i);
}
// Create single image out of scaled images portions
//定义部分/行大小50px或100px
整数行高=50;
int rowsToScan=图像高度/行高度;
如果(imageHeight%rowHeight>0)行扫描++;
int x=0;
int y=0;
int w=图像宽度;
int h=行高;
ArrayList ScaleImage部分=新ArrayList();
对于(int i=1;我请在您的问题中添加您尝试过的Xmx值。4.在这种情况下,将Xmx设置为任意大的数字(100 GB)如何?当系统无法提供时,JVM将简单地消亡。使用oracle JVM获取系统内存的方法在这里。但是,如果您不需要内存中的整个图像(我想是原始的?)为什么不逐行(或逐像素)阅读呢.CCC不需要内存中的整个图像IIRC如果您需要内存中的整个图像该怎么办。要在面板上使用图形绘制它,您需要整个图像,对吗?@Ellen Spertus使用手动设置Xmx值意味着,您不能像上面提到的那样拥有任意大的图像。此外,我们可以在启动JVM后设置Xmx值吗?如果存在无法重新启动JVM的情况?@EllenSpertus我已在问题中添加了值。
MappedByteBuffer buffer = inChannel.map(FileChannel.MapMode.READ_ONLY,0, inChannel.size());
buffer.order(ByteOrder.LITTLE_ENDIAN);
FloatBuffer floatBuffer = buffer.asFloatBuffer();
for(int i=0,k=0;i<nrow;i=i+jump) /*jump is the value to be skipped, nrow is height of image*/
{
for(int j=0,l=0;j<ncol1;j=j+jump) //ncol is width of image
{
index=(i*ncol)+j;
oneDimArray[(k*ncolLessRes)+l] = floatBuffer.get(index);//oneDimArray is initialised to size of Low Resolution image.
l++;
}
k++;
}
// Define the portion / row size 50px or 100px
int rowHeight = 50;
int rowsToScan = imageHeight / rowHeight;
if(imageHeight % rowHeight > 0) rowsToScan++;
int x = 0;
int y = 0;
int w = imageWidth;
int h = rowHeight;
ArrayList<BufferedImage> scaledImagePortions = new ArrayList<>();
for(int i = 1; i <= rowsToScan; i++) {
// Read the portion of an image scale it
// and push the scaled version in lets say array
BufferedImage scalledPortionOfImage = this.getScaledPortionOfImage(img, x, y, w, h);
scaledImagePortions.add(scalledPortionOfImage);
y = (rowHeight * i);
}
// Create single image out of scaled images portions