forked from ofdrw/ofdrw
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathImg.java
More file actions
216 lines (197 loc) · 6.77 KB
/
Copy pathImg.java
File metadata and controls
216 lines (197 loc) · 6.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
package org.ofdrw.layout.element;
import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.image.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Iterator;
/**
* 图片对象
* <p>
* 为了防止与Image对象命名冲突采用Img缩写
* <p>
* 绘制行为详见渲染器 {@link org.ofdrw.layout.engine.render.ImgRender}
*
* @author 权观宇
* @since 2020-02-03 03:34:31
*/
public class Img extends Div<Img> {
/**
* 图片文件路径
*/
private Path src;
private Img() {
// 图片对象不可拆分
this.setIntegrity(true);
}
/**
* 构造图片对象
* <p>
* 该构造器不会输入图片进行解析,直接将图片作为资源使用。
*
* @param width 图片在页面内的宽度,单位毫米(mm)
* @param height 图片在页面内的高度,单位毫米(mm)
* @param src 图片路径(该构造器不会解析图片大小)
* @throws IOException 读取异常
*/
public Img(double width, double height, Path src) throws IOException {
this();
if (src == null || Files.notExists(src)) {
throw new IllegalArgumentException("图片文件为空或不存在");
}
this.src = src;
this.setWidth(width);
this.setHeight(height);
}
/**
* 创建图片Div
* <p>
* 图片宽度和高度以 每 5pix/mm (像素/毫米)的比例转换。
* <p>
* 不建议使用该方式构造图片,图片的宽度和高度应该在由调用者手动指定
* 建议使用{@link Img#Img(double, double, java.nio.file.Path)}方法构造
*
* @param src 图片路径
* @throws IOException 图片解析异常
* @deprecated {@link Img#Img(double, double, java.nio.file.Path)}
*/
@Deprecated
public Img(Path src) throws IOException {
this();
if (src == null || Files.notExists(src)) {
throw new IllegalArgumentException("图片文件为空或不存在");
}
this.src = src;
parseImg();
}
/**
* 解析路径上的图片
*
* @throws IOException 读取解析异常
*/
private void parseImg() throws IOException {
final File picture = src.toFile();
BufferedImage imgObj = null;
try (FileInputStream fIn = new FileInputStream(picture)) {
imgObj = ImageIO.read(fIn);
} catch (IIOException e) {
/*
* 图片类型的问题,如果图片格式而是CMYK格式,
* 使用ImageIO.read方法有时报javax.imageio.IIOException: Unsupported Image Type
* 此处尝试将CMYK装换为 RGB。
*/
imgObj = readImage(picture);
}
if (imgObj != null) {
this.setWidth((double) imgObj.getWidth() / 5);
this.setHeight((double) imgObj.getHeight() / 5);
}
}
/**
* 尝试读取图片文件为 BufferedImage
* <p>
* 首先尝试采用RGB读取,如果失败那么将CMYK进行色彩空间转化为RGB。
*
* @param imageFile 图片文件
* @return BufferedImage
* @throws IOException 操作或转换异常
* @author zwd
*/
public static BufferedImage readImage(File imageFile) throws IOException {
try (ImageInputStream input = ImageIO.createImageInputStream(imageFile);) {
Iterator<?> readers = ImageIO.getImageReaders(input);
if (readers == null || !readers.hasNext()) {
return null;
}
ImageReader reader = (ImageReader) readers.next();
reader.setInput(input);
BufferedImage image;
try {
// 尝试读取图片 (包括颜色的转换).RGB
image = reader.read(0);
} catch (IIOException e) {
// 尝试将CMYK转换为RGB
image = convertCMYK2RGB(reader);
}
return image;
}
}
/**
* 装换CMYK图片为RGB
*
* @param reader 图片解析器
* @return BufferedImage
* @author zwd
*/
private static BufferedImage convertCMYK2RGB(ImageReader reader) throws IOException {
// 读取Raster (没有颜色的转换) CMYK
Raster raster = reader.readRaster(0, null);
int w = raster.getWidth();
int h = raster.getHeight();
byte[] rgb = new byte[w * h * 3];
// 彩色空间转换
float[] Y = raster.getSamples(0, 0, w, h, 0, (float[]) null);
float[] Cb = raster.getSamples(0, 0, w, h, 1, (float[]) null);
float[] Cr = raster.getSamples(0, 0, w, h, 2, (float[]) null);
float[] K = raster.getSamples(0, 0, w, h, 3, (float[]) null);
for (int i = 0, imax = Y.length, base = 0; i < imax; i++, base += 3) {
float k = 220 - K[i], y = 255 - Y[i], cb = 255 - Cb[i],
cr = 255 - Cr[i];
double val = y + 1.402 * (cr - 128) - k;
val = (val - 128) * .65f + 128;
rgb[base] = val < 0.0 ? (byte) 0 : val > 255.0 ? (byte) 0xff
: (byte) (val + 0.5);
val = y - 0.34414 * (cb - 128) - 0.71414 * (cr - 128) - k;
val = (val - 128) * .65f + 128;
rgb[base + 1] = val < 0.0 ? (byte) 0 : val > 255.0 ? (byte) 0xff
: (byte) (val + 0.5);
val = y + 1.772 * (cb - 128) - k;
val = (val - 128) * .65f + 128;
rgb[base + 2] = val < 0.0 ? (byte) 0 : val > 255.0 ? (byte) 0xff
: (byte) (val + 0.5);
}
raster = Raster.createInterleavedRaster(
new DataBufferByte(rgb, rgb.length),
w, h,
w * 3,
3,
new int[]{0, 1, 2},
null);
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
ColorModel cm = new ComponentColorModel(cs, false, true,
Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
return new BufferedImage(cm, (WritableRaster) raster, true, null);
}
public Path getSrc() {
return src;
}
public Img setSrc(Path src) {
this.src = src;
return this;
}
/**
* 不允许切分
*/
@Override
public Div[] split(double sHeight) {
throw new RuntimeException("图片对象不支持分割操作");
}
/**
* 元素类型
* <p>
* 关联绘制器:{@link org.ofdrw.layout.engine.render.ImgRender}
*
* @return Img
*/
@Override
public String elementType() {
return "Img";
}
}