当前位置: 首页 > 知识库问答 >
问题:

使用不带BuffereImage的PNGJ读取PNG像素

袁鸿畴
2023-03-14

我一直在努力尝试使用PNGJ做等效的代码。我不想使用ImageIO. readBufferedImage.getRGB。相反,我想纯粹使用PNGJ获取像素。下面的代码是我的ImageIO BufferedImage版本。

BufferedImage bi = ImageIO.read( imageFile );
...
int[] pixels = new int[arrSize];
bi.getRGB( 0, 0, width, height, pixels, 0, width );

我想要像PNGJ那样的东西

lint = (ImageLineInt) reader.readRow();
scanLine = lint.getScanline();
...
???

以下是我的测试图像详细信息:
ImageInfo[cols=1530,rows=1980,bitDepth=8,Channel=3,BitsPixel=24,bytesPixel=3,bytesPerRow=4590,samplesPerRow=4590,samplesPerRowP=4590,alpha=false,greyscale=false,indexed=false,packed=false]

共有3个答案

陈刚洁
2023-03-14

你可以使用BuffereImage获得像素。获取RGB是访问像素值最慢的方法之一。你想要的是访问数据缓冲区。

BufferedImage bi = ImageIO.read( imageFile );
byte[] pixels = ((DataBufferByte)bi.getRaster().getDataBuffer()).getData() ;

您只需小心图像编码(字节、Int或短)。

金昌胤
2023-03-14

到目前为止,这是我发现的。https://code.google.com/p/pngj/wiki/FAQ

如何读取/写入像素值?每个PngReader的readRow()调用都返回一个IImageLine,它代表一个PNG图像行;具体实现是可扩展的。但是默认包含的实现(PngReader或PngReaderInt)返回ImageLineInt。这个类包装了一个scaline(getScanline()),它是一个int[]数组。该数组的每个元素对应一个图像样本;因此,数组长度(至少)为列x通道。

另一种格式是ImageLineByte,除了将每个样本存储在一个字节中之外,它是相同的(优点:内存使用更少,8位图像的最佳速度;缺点:如果图像是每通道16位,则会丢失分辨率,而且做算术更麻烦——Java中的字节是有符号的)。

扫描线内示例值的布局如下:

对于真彩色图像,RGB/RGBA样本按RGB(A)顺序排列:RGB R G B。。。(没有阿尔法)或RGB A RGB A。。。(使用alpha);这些值不按比例缩放:只有当bitdepth=8时,它们才会在0-255范围内(如果bitdepth=16,则为0-65535;如果bitdepth=4,则为0-15,以此类推)。对于索引图像,每个样本值对应于调色板索引I。。。。对于灰度G/GA图像,它是灰度值G。。。(没有阿尔法)或G A G A。。。(使用alpha)。

下面是我使用的代码,可以在以后提供给BuffereImage(具有透明度。半透明):

PngReader reader = new PngReader( inputPNGFile );
arrSize = (int) reader.imgInfo.getTotalPixels();

width = reader.imgInfo.cols;
height = reader.imgInfo.rows;
channels = reader.imgInfo.channels;    

ImageLineInt lint;
while ( reader.hasMoreRows() ) {
    lint = (ImageLineInt) reader.readRow();
    scanLine = lint.getScanline();

    for ( i = 0; i < width; i++ ) {
        offset = i * channels;

        // Adjust the following code depending on your source image.
        // I need the to set the alpha channel to 0xFF000000 since my destination image
        // is TRANSLUCENT : BufferedImage bi = CONFIG.createCompatibleImage( width, height, Transparency.TRANSLUCENT );
        // my source was 3 channels RGB without transparency
        nextPixel = ( scanLine[offset] << 16 ) | ( scanLine[offset + 1] << 8 ) | ( scanLine[offset + 2] ) | 0xFF000000;

        // I'm placing the pixels on a memory mapped file
        mem.putInt( nextPixel ); 
     }

}
左丘昊天
2023-03-14

正如Zek的回答所指出的,PNGJ与BufferedImage不同:它更低级,因为它不会尝试以抽象的通用格式(独立于具体的PNG格式)表示图像像素,而是为您提供直接映射到PNG格式和颜色模型的格式值。

这意味着,例如,如果PNG图像是RGB,您将获得三个RGB组件作为连续(整数)值。如果PNG图像被索引,您将获得索引(指向调色板的整数值)。如果PNG图像是灰度的,那么灰度值将作为单个整数。等

如果您想以更一般的方式处理像素值(无论基础颜色模型如何,都给我RGB值),您可以自己进行转换,或者利用ImageLineHelper类中的helper方法。具体来说,请查看方法convert2rgba()getPixelARGB8()

不过,请记住,这个类只是一组助手方法,可能对您有用,也可能没有。很难对RGB进行完全通用的转换,因为有很多复杂的问题和启发——PNG允许多种透明模式、深度、颜色空间。。。(如果图像深度为2比特怎么办?如果是16比特怎么办?如果它有一个非标准的颜色轮廓或伽马校正,或者它有一个单一的透明块,或者…等等)?如果你想支持完整的PNG图像集,几乎需要了解其基本格式和复杂性。

(但是,但是......BufferedImage这样做,完全笼统,没有歧义,没有问题,你说?不完全是)

如果你可以限制你的颜色模型(RGB,8位,没有alpha)(并且你没有透明度TRNS块或gamma特性,或者不在乎),那么它非常简单:

 for (int i = 0,j=0 ; i <  reader.imgInfo.cols; i++, j+=channels ) {
      int r = scanLine[j];
      int g = scanLine[j+1];
      int b = scanLine[j+2];
     // ...
 }

免责声明:我是PNGJ编码员。

 类似资料:
  • 问题内容: 我正在做一些图像处理,我想分别读取JPEG和PNG图像中的每个像素值。 在我的部署方案中,使用第3方库对我来说很尴尬(因为我对目标计算机的访问受到限制),但是我假设没有用于读取JPEG / PNG的标准C或C ++库… 因此,如果您知道 不 使用库的方法,那就太好了,如果没有,那么仍然欢迎回答! 问题答案: C标准中没有标准库可以读取文件格式。 但是,大多数程序,尤其是在Linux平台

  • 问题内容: 如何使用PIL检测PNG图像是否具有透明的Alpha通道? 通过上面的代码,我们知道PNG图像是否不具有Alpha通道,但是如何获得Alpha值? 我没有在PIL网站上描述的img.info词典中找到“透明”键 我正在使用Ubuntu和zlib1g,已经安装了zlibc软件包。 问题答案: 要获取RGBA图像的alpha层,您需要做的是: 要么 有一种设置Alpha层的方法: 透明度键

  • 问题内容: 我正在使用Tensorflow构建标准的图像分类模型。为此,我有输入图像,每个图像都分配了一个标签({0,1}中的数字)。因此,可以使用以下格式将数据存储在列表中: 我想使用TensorFlow的排队系统读取我的数据并将其输入到我的模型中。忽略标签,可以使用和轻松实现。这里的代码: 但是,在该过程中标签丢失了,因为图像数据作为输入管道的一部分被有意地改组了。通过输入队列将标签和图像数据

  • 我有一个大问题,试图将一个大的科学图像(7MB)16位PNG图像转换为JPG,以便压缩它并检查Python中的任何最终工件。原始图像可在以下位置找到:https://postimg.cc/p5PQG8ry在这里阅读其他答案时,我尝试了枕头和OpenCV,但没有成功。我得到的唯一东西是一张白色的床单。我做错了什么?注释行是使用Python读取16位PNG图像文件的尝试,但似乎不适用于生成数据类型错误

  • 我试图用处理docx文件。只是简单地读取然后写入文件(现在)。这是我的简单代码: 问题是输入文件的头文件中有一个小图像。因此,在使用POI处理输入文件并在Microsoft Word中打开输出文件后,我收到损坏的文件错误: 一切工作在OO Writer,但不是在办公室。 问题是:怎么了?apache POI是否不处理头文件中包含图像的文件?你知道解决这个问题的方法吗? 我需要使用,我不考虑其他工具

  • 问题内容: 我正在使用Tkinter编写GUI,并希望在中显示png文件。所以我有一些这样的代码: 这段代码 可以在我的Linux机器上正确运行 。但是,当我在Windows计算机上运行它时,它会失败。我还在其他几台机器(包括Windows和Linux)上进行了测试,但始终失败。 追溯为: 如果删除源代码,则回溯将变为: 那么,我应该怎么做才能使其支持png文件? 问题答案: tkinter仅支持