实现类Img,参考形式如下: Class Img { Img(){} void readImg(string file);//从参数file指定的路径读取图像文件,有合理的函数体即可 void writeImg(string file);//将图像数据写出到参数file指定的路径,有合理的函数体即可 enum IMG_STORE_TYPE{GRAY,GRAY_A,RGB,RGB_A;};//图像的存储形式有四种: 灰度通道,灰度通道+透明度通道,RGB通道,RGB通道+透明度通道 IMG_STORE_TYPE store_type;//根据readImg的信息设定具体的store_type。 short[] pixel_data;存储的像素颜色数据 Img UnaryOperation(ShortUnaryOperator unary_op); Img BinaryOperation(Img img, ShortBinaryOperator binary_op); } 相同维度大小的图像与图像之间存在算术运算关系:是指对两幅或两幅以上的输入图像中对应像素值作加、减、乘或除等运算 后,将运算结果作为输出图像相应像素的灰度值。这种运算的特点在于:其―,输出图像像素的值仅取决于两幅或两幅以上的输入图像的对应像素值,算术运算结果和参与运算像素的邻域内像素的灰度值无关;其二,算术运算不会改变像素的空间位置。实现方法UnaryOperation和BinaryOperation,根据上述图像运算关系的定义,对pixel_data中的数据进行遍历运算,参数img是另一个参与运算的相同大小的图像,binary_op是具体运算的形式,对UnaryOperation实现反色操作(使用颜色的最大值255减去当前像素值得到新的像素值),对BinaryOperation实现加减两种运算形式(减法结果小于0的情况,截断到0)。
时间: 2024-02-11 18:09:07 浏览: 98
以下是实现类Img的代码:
```java
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Objects;
import java.util.function.ShortBinaryOperator;
import java.util.function.ShortUnaryOperator;
class Img {
private int width;
private int height;
private int channels;
private IMG_STORE_TYPE store_type;
private short[] pixel_data;
enum IMG_STORE_TYPE {
GRAY, GRAY_A, RGB, RGB_A
}
Img() {
}
void readImg(String file) {
try (InputStream is = new FileInputStream(file)) {
byte[] header = new byte[54];
is.read(header, 0, 54);
width = bytesToInt(Arrays.copyOfRange(header, 18, 22));
height = bytesToInt(Arrays.copyOfRange(header, 22, 26));
channels = bytesToInt(Arrays.copyOfRange(header, 28, 30)) / 8;
int data_size = width * height * channels;
byte[] data = new byte[data_size];
is.read(data, 0, data_size);
pixel_data = new short[data_size];
for (int i = 0; i < data_size; i++) {
pixel_data[i] = (short) (data[i] & 0xff);
}
if (channels == 1) {
store_type = IMG_STORE_TYPE.GRAY;
} else if (channels == 2) {
store_type = IMG_STORE_TYPE.GRAY_A;
} else if (channels == 3) {
store_type = IMG_STORE_TYPE.RGB;
} else if (channels == 4) {
store_type = IMG_STORE_TYPE.RGB_A;
}
} catch (IOException e) {
e.printStackTrace();
}
}
void writeImg(String file) {
try (OutputStream os = new FileOutputStream(file)) {
byte[] header = new byte[54];
header[0] = (byte) 'B';
header[1] = (byte) 'M';
int data_size = width * height * channels;
int file_size = data_size + 54;
byte[] file_size_bytes = intToBytes(file_size);
System.arraycopy(file_size_bytes, 0, header, 2, 4);
header[10] = 54;
header[14] = 40;
byte[] width_bytes = intToBytes(width);
byte[] height_bytes = intToBytes(height);
System.arraycopy(width_bytes, 0, header, 18, 4);
System.arraycopy(height_bytes, 0, header, 22, 4);
header[26] = (byte) (channels * 8);
header[28] = (byte) (data_size & 0xff);
header[29] = (byte) ((data_size >> 8) & 0xff);
header[30] = (byte) ((data_size >> 16) & 0xff);
header[31] = (byte) ((data_size >> 24) & 0xff);
os.write(header);
byte[] data = new byte[data_size];
for (int i = 0; i < data_size; i++) {
data[i] = (byte) (pixel_data[i] & 0xff);
}
os.write(data);
} catch (IOException e) {
e.printStackTrace();
}
}
Img UnaryOperation(ShortUnaryOperator unary_op) {
Img result = new Img();
result.width = width;
result.height = height;
result.channels = channels;
result.store_type = store_type;
result.pixel_data = Arrays.stream(pixel_data).map(unary_op::applyAsShort).toArray();
return result;
}
Img BinaryOperation(Img img, ShortBinaryOperator binary_op) {
Objects.requireNonNull(img);
if (width != img.width || height != img.height || channels != img.channels) {
throw new IllegalArgumentException("The two images must have the same size and number of channels.");
}
Img result = new Img();
result.width = width;
result.height = height;
result.channels = channels;
result.store_type = store_type;
result.pixel_data = new short[width * height * channels];
for (int i = 0; i < result.pixel_data.length; i++) {
result.pixel_data[i] = binary_op.applyAsShort(pixel_data[i], img.pixel_data[i]);
if (result.pixel_data[i] < 0) {
result.pixel_data[i] = 0;
}
}
return result;
}
private static int bytesToInt(byte[] bytes) {
int result = 0;
for (int i = 0; i < bytes.length; i++) {
result |= ((bytes[i] & 0xff) << (i * 8));
}
return result;
}
private static byte[] intToBytes(int n) {
byte[] bytes = new byte[4];
for (int i = 0; i < 4; i++) {
bytes[i] = (byte) ((n >> (i * 8)) & 0xff);
}
return bytes;
}
}
```
其中,`readImg`方法从指定路径读取图像文件,并根据文件头信息确定图像的宽、高、通道数和存储形式。`writeImg`方法将图像数据写出到指定路径,并根据图像宽、高、通道数和存储形式生成文件头信息。`UnaryOperation`方法对图像进行一元运算,其中`unary_op`是一个接收一个short类型参数并返回一个short类型结果的函数,用于对每个像素值进行运算。`BinaryOperation`方法对图像进行二元运算,其中`img`是另一个参与运算的相同大小的图像,`binary_op`是一个接收两个short类型参数并返回一个short类型结果的函数,用于对每个像素值进行运算。在二元运算中,如果结果小于0,则将其截断到0。
阅读全文