Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Java中读取PGM图像?_Java_Javax.imageio_Pgm - Fatal编程技术网

如何在Java中读取PGM图像?

如何在Java中读取PGM图像?,java,javax.imageio,pgm,Java,Javax.imageio,Pgm,我觉得我错过了一些简单的东西(和往常一样) 我正在尝试使用Java读取PGM图像。Matlab做得很好-在Matlab中输出图像像素(例如,一个32x32的小图像)会得到如下结果: 1 0 11 49 94 118 118 106 95 88 85 96 124 143 142 133 P5 # MatLab PGMWRITE file, saved 27-Jun-2002 16 16 255 我敢肯定,问题在于这些图像文件既包含ASCII文本/数字,也包含二进制图像数据。但是,如果Java在读

我觉得我错过了一些简单的东西(和往常一样)

我正在尝试使用Java读取PGM图像。Matlab做得很好-在Matlab中输出图像像素(例如,一个32x32的小图像)会得到如下结果:

1 0 11 49 94 118 118 106 95 88 85 96 124 143 142 133 P5 # MatLab PGMWRITE file, saved 27-Jun-2002 16 16 255 我敢肯定,问题在于这些图像文件既包含ASCII文本/数字,也包含二进制图像数据。但是,如果Java在读取PNG方面没有问题,为什么缺少对PGM的支持呢

编辑3

好的,我发现了一个有效的实现…不幸的是,它已被弃用:

  filePath = "imagepath.pgm"
  FileInputStream fileInputStream = new FileInputStream(filePath);
  DataInputStream dis = new DataInputStream(fileInputStream);
  StreamTokenizer streamTokenizer = new StreamTokenizer(dis);

  // read header text using StreamTokenizer.nextToken()

  data2D = new int [picWidth] [picHeight];
  for (int row = 0; row < picHeight; row++) {
    for (int col = 0; col < picWidth; col++) {
      data2D[row][col] = dis.readUnsignedByte();
      System.out.print(data2D[row][col] + " ");
    }
    System.out.println();
  }
filePath=“imagepath.pgm”
FileInputStream FileInputStream=新的FileInputStream(filePath);
DataInputStream dis=新的DataInputStream(fileInputStream);
StreamTokenizer StreamTokenizer=新的StreamTokenizer(dis);
//使用StreamTokenizer.nextToken()读取标题文本
data2D=新整数[picWidth][picHeight];
对于(int row=0;row
根据Java文档,
StreamTokenizer(InputStream)
构造函数被弃用,因为
DataInputStream.readLine()
方法不能正确地将原始字节转换为字符。然而,在这种特定的情况下,它似乎对报头有效,并且显然对随后的二值图像数据有效


不幸的是,它仍然是不推荐使用的,而且,按照文档的建议混合使用
BufferedReader
似乎只会在读取头并尝试使用
DataInputStream
读取原始字节后导致
EOFEException
s。仍在寻找解决方案…

代码的问题在于使用错误的类从文件中读取原始数据。正如
BufferedReader
文档所述:

public int read()抛出IOException

读取单个字符

返回:读取的字符,范围为0到65535(0x00-0xffff)之间的整数,如果已到达流的结尾,则返回-1

因此,对
BufferedReader
read()
方法的每次调用实际上都会消耗输入流中的一到两个字节(基于字符编码),这不是您想要的。这也解释了为什么你会得到很多-1:流结束的时间比你想象的要早得多

由于PGM包含ASCII十进制值,因此使用该类很容易解析

下面是一段几乎未经测试的代码,演示了如何读取PGM图像,假设:

  • 它在幻数后包含一条注释(即除了第二条注释外,它没有以#开头的行)
  • PGM文件正好有4行长
代码如下:

String filePath = "image.pgm";
fileInputStream = new FileInputStream(filePath);
Scanner scan = new Scanner(fileInputStream);
// Discard the magic number
scan.nextLine();
// Discard the comment line
scan.nextLine();
// Read pic width, height and max value
int picWidth = scan.nextInt();
int picHeight = scan.nextInt();
int maxvalue = scan.nextInt();

fileInputStream.close();
            
 // Now parse the file as binary data
 fileInputStream = new FileInputStream(filePath);
 DataInputStream dis = new DataInputStream(fileInputStream);
 
 // look for 4 lines (i.e.: the header) and discard them
 int numnewlines = 4;
 while (numnewlines > 0) {
     char c;
     do {
         c = (char)(dis.readUnsignedByte());
     } while (c != '\n');
     numnewlines--;
 }

 // read the image data
 int[][] data2D = new int[picHeight][picWidth];
 for (int row = 0; row < picHeight; row++) {
     for (int col = 0; col < picWidth; col++) {
         data2D[row][col] = dis.readUnsignedByte();
         System.out.print(data2D[row][col] + " ");
     }
     System.out.println();
 }
stringfilepath=“image.pgm”;
fileInputStream=新的fileInputStream(filePath);
扫描仪扫描=新扫描仪(fileInputStream);
//放弃这个神奇的数字
scan.nextLine();
//放弃注释行
scan.nextLine();
//读取图片宽度、高度和最大值
int picWidth=scan.nextInt();
int picHeight=scan.nextInt();
int maxvalue=scan.nextInt();
fileInputStream.close();
//现在将文件解析为二进制数据
fileInputStream=新的fileInputStream(filePath);
DataInputStream dis=新的DataInputStream(fileInputStream);
//查找4行(即页眉)并丢弃它们
int numnewlines=4;
而(数值线>0){
字符c;
做{
c=(char)(dis.readUnsignedByte());
}而(c!='\n');
Numnewline——;
}
//读取图像数据
int[][]data2D=新的int[picHeight][picWidth];
对于(int row=0;row
需要实现:支持注释行,每个元素的值应除以
maxvalue
,错误检查格式错误的文件,异常处理。我使用UNIX终端在PGM文件上测试了它,但它也应该在Windows上工作

我要强调的是,这不是PGM解析器的健壮且不完整的实现。这段代码只是作为概念的证明,也许可以满足您的需要


如果您真的需要一个健壮的PGM解析器,您可以使用。

Done and Done提供的工具,让我知道您还需要什么。这很好,但会产生一个新问题:解析头文件。我使用了BufferedReader/StreamTokenizer来读取头字符,出于某种原因,一旦读取完成,对dis.readByte()的第一次调用就会抛出一个EOFEException。如果我从文件中删除头并直接从二进制文件中读取,我会遇到另一个问题:它读取的前55个字节是垃圾数字;第56个字节是“1”,在我的原始帖子中首先出现,然后是所有相应的数字(由于垃圾引入,最多短55个字节)。有什么想法吗?呃,对不起,忽略55字节的部分;如果我删除了头(因此,BufferedReader/StreamTokenizer,并且有一个文件句柄——DataInputStream——从文件中读取),那么它就可以正常工作。我会在几分钟内尝试一下。我修改了代码段,现在它可以与您的示例PGM文件一起使用。嗯,我仍然有问题:当我尝试运行您的新代码时,我遇到了InputMismatchException。它正确地读取头行,但是在读取二进制图像数据的第一次遍历两个循环时,它抛出异常。有什么想法吗? P5 # MatLab PGMWRITE file, saved 27-Jun-2002 16 16 255 Skipping unknow token: "" Skipping unknow token: "1^vvj_XU`|���" Skipping unknow token: "" Skipping unknow token: "9`z}rf^[e���`UFKe��~ojjp������r]cx�{nq|������ÕiXcroj{��������sQRdmu��������٪sNNqudSP�����]DN{�jME�����rn\@6QkiS;8�����OPG47aC7)!*�����>BA4?s" Skipping unknow token: "" Skipping unknow token: "" Skipping unknow token: "�Ů��(/4,7m�ļ���ڳ�k" Skipping unknow token: "&,%+Y������۳�i04839[��ux��Ȩ�i@CFIWrkOQv���{h?CISk��[66X���{j" Exception in thread "main" java.util.NoSuchElementException at java.util.Scanner.throwFor(Scanner.java:838) at java.util.Scanner.next(Scanner.java:1347) at Test.main(Test.java:49)
System.out.println(String.format("Skipping unknow token: \"%s\"", scan.next()));
  filePath = "imagepath.pgm"
  FileInputStream fileInputStream = new FileInputStream(filePath);
  DataInputStream dis = new DataInputStream(fileInputStream);
  StreamTokenizer streamTokenizer = new StreamTokenizer(dis);

  // read header text using StreamTokenizer.nextToken()

  data2D = new int [picWidth] [picHeight];
  for (int row = 0; row < picHeight; row++) {
    for (int col = 0; col < picWidth; col++) {
      data2D[row][col] = dis.readUnsignedByte();
      System.out.print(data2D[row][col] + " ");
    }
    System.out.println();
  }
String filePath = "image.pgm";
fileInputStream = new FileInputStream(filePath);
Scanner scan = new Scanner(fileInputStream);
// Discard the magic number
scan.nextLine();
// Discard the comment line
scan.nextLine();
// Read pic width, height and max value
int picWidth = scan.nextInt();
int picHeight = scan.nextInt();
int maxvalue = scan.nextInt();

fileInputStream.close();
            
 // Now parse the file as binary data
 fileInputStream = new FileInputStream(filePath);
 DataInputStream dis = new DataInputStream(fileInputStream);
 
 // look for 4 lines (i.e.: the header) and discard them
 int numnewlines = 4;
 while (numnewlines > 0) {
     char c;
     do {
         c = (char)(dis.readUnsignedByte());
     } while (c != '\n');
     numnewlines--;
 }

 // read the image data
 int[][] data2D = new int[picHeight][picWidth];
 for (int row = 0; row < picHeight; row++) {
     for (int col = 0; col < picWidth; col++) {
         data2D[row][col] = dis.readUnsignedByte();
         System.out.print(data2D[row][col] + " ");
     }
     System.out.println();
 }