我目前正在制作一种将 ppm 文件转换为 jpg、png 和 bmp 文件的方法。我这样做的方式是读取 ppm 文件的内容,创建 BufferedImage,并将 ppm 文件中的每个像素分配给 BufferedImage 中的相应像素。我的 bmp 和 png 文件看起来正确。但是,jpg 文件看起来完全不同。
下面是我的代码:
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import javax.imageio.ImageIO;
public class readPPMOutputOthers {
public static void main(String[] args) throws InterruptedException {
// read a ppm file
Scanner sc;
// if the file is not found, it will throw an exception
try {
sc = new Scanner(new FileInputStream("res/test2.ppm"));
} catch (FileNotFoundException e) {
throw new IllegalArgumentException("File not found!");
}
// the file now is a StringBuilder
// read line by line to get information
StringBuilder builder = new StringBuilder();
while (sc.hasNextLine()) {
String s = sc.nextLine();
// ignore comment #
if (s.charAt(0) != '#') {
builder.append(s).append(System.lineSeparator());
}
}
// throw an exception if the raw file doesn't begin with P3
sc = new Scanner(builder.toString());
String token;
token = sc.next();
if (!token.equals("P3")) {
throw new IllegalArgumentException("Invalid PPM file: plain RAW file should begin with P3.");
}
// set the fields
// initial load image
int width = sc.nextInt();
int height = sc.nextInt();
int maxValue = sc.nextInt();
List<Integer> pixels = new ArrayList<>();
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int r = sc.nextInt();
int g = sc.nextInt();
int b = sc.nextInt();
int rgb = r;
rgb = (rgb << 8) + g;
rgb = (rgb << 8) + b;
pixels.add(rgb);
}
}
// make a BufferedImage from pixels
BufferedImage outputImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
int[] outputImagePixelData = ((DataBufferInt) outputImg.getRaster().getDataBuffer()).getData();
for (int i = 0; i < pixels.size(); i++) {
outputImagePixelData[i] = pixels.get(i);
}
try {
ImageIO.write(outputImg, "png",
new File("res/test.png"));
ImageIO.write(outputImg, "jpg",
new File("res/test2.jpg"));
ImageIO.write(outputImg, "bmp",
new File("res/test.bmp"));
} catch (IOException e) {
System.out.println("Exception occurred :" + e.getMessage());
}
System.out.println("Images were written successfully.");
}
}
奇怪的是它适用于非常大的图像,但不适用于这个小图像。由于测试,我需要使它适用于如此小的图像。我一直在谷歌上挖掘关于这个的帖子,但仍然没有找到解决这个问题的方法。任何帮助,将不胜感激!
奇怪颜色的原因是JPEG 编码使用的YUV420色度子采样。
在 YUV420 中,每 2x2 像素具有相同的色度信息(2x2 像素具有相同的颜色)。
2x2 像素具有相同的颜色,但每个像素具有不同的亮度(亮度)。
Wikipedia中演示了 YUV420 Chroma subsumpling :
在我们的例子中:
变为棕色是原始红色、青色洋红色和黄色的混合(棕色由 4 个像素“共享”)。
常用的 JPEG 颜色格式是 YUV420,但 JPEG 标准确实支持 YUV444 Chroma subsumpling。
GIMP设法使用 YUV444 Chroma subsumpling 保存 JPEG 图像。
我找不到在 JAVA 中保存 YUV444 JPEG 的示例...
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句