java AffineTransformOp 的奇怪行为
Strange behaviour of java AffineTransformOp
我可以在 png/jpeg 图像上正确使用 AffineTransformOp.filter。但是当我将 AffineTransformOp 子类化时,它会抛出异常!以下最小示例显示了这一点:
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.image.*;
import java.awt.geom.*;
import javax.imageio.*;
import java.io.*;
public class Strange extends JPanel {
public static void main(String args[]) throws Exception {
BufferedImage from = (BufferedImage) ImageIO.read(new File(args[0]));
MyTrans at = new MyTrans();
AffineTransformOp at2 = new AffineTransformOp(new AffineTransform(), AffineTransformOp.TYPE_BILINEAR);
System.err.println("Bad = "+at.getTransform());
System.err.println("Good = "+at2.getTransform());
BufferedImage bi1 = at.filter(from,null);//1
BufferedImage bi2 = at2.filter(from,null);//2
}
}
class MyTrans extends AffineTransformOp {
public MyTrans() {
super(new AffineTransform(), TYPE_BILINEAR);
}
}
标有 1 的行抛出 ImagingOpException:Unable to transform src image
。但是我注释掉了那一行,然后下一行(做完全相同的事情)运行顺利。这里的变换只是恒等变换。我在 Ubuntu 16.04 上使用 java 8。任何 png 或 jpeg 图像都会导致此问题,所以我没有附加图像。
AffineTransformOp.filter(src, dst) 在第 284 行从包 sun.awt.image.ImagingLib 内部调用 ImagingLib.filter(this, src, dst)。
...
if (ImagingLib.filter(this, src, dst) == null) {
throw new ImagingOpException ("Unable to transform src image");
}
...
我们观察到的行为与 ImagingLib.filter() 的实现方式有关。此方法检查第一个参数是否对应于以下任何一个 classes:
- 查找操作
- 仿射变换运算
- 卷积运算
当调用 ImagingLib.filter 时,传递给函数的第一个参数是 this。在您编写的示例代码中:at.class 等于 "MyTrans" 并且 at2.class 等于 "AffineTransformOp".
看看下面的代码,它属于ImagingLib.filter()源代码。
public static BufferedImage filter(BufferedImageOp var0, BufferedImage var1, BufferedImage var2) {
...
BufferedImage var3 = null;
switch(getNativeOpIndex(var0.getClass())) {
case 0:
LookupTable var4 = ((LookupOp)var0).getTable();
if (var4.getOffset() != 0) {
return null;
}
if (var4 instanceof ByteLookupTable) {
ByteLookupTable var9 = (ByteLookupTable)var4;
if (lookupByteBI(var1, var2, var9.getTable()) > 0) {
var3 = var2;
}
}
break;
case 1:
AffineTransformOp var5 = (AffineTransformOp)var0;
double[] var6 = new double[6];
AffineTransform var7 = var5.getTransform();
var5.getTransform().getMatrix(var6);
if (transformBI(var1, var2, var6, var5.getInterpolationType()) > 0) {
var3 = var2;
}
break;
case 2:
ConvolveOp var8 = (ConvolveOp)var0;
if (convolveBI(var1, var2, var8.getKernel(), var8.getEdgeCondition()) > 0) {
var3 = var2;
}
}
if (var3 != null) {
SunWritableRaster.markDirty(var3);
}
return var3;
}
}
因此,当调用 getNativeOpIndex(var0.getClass()) 时,因为 "MyTrans" 不是预期的 class 类型,它 returns -1 因此它不会处理开关上的任何情况,并返回 null。
我可以在 png/jpeg 图像上正确使用 AffineTransformOp.filter。但是当我将 AffineTransformOp 子类化时,它会抛出异常!以下最小示例显示了这一点:
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.image.*;
import java.awt.geom.*;
import javax.imageio.*;
import java.io.*;
public class Strange extends JPanel {
public static void main(String args[]) throws Exception {
BufferedImage from = (BufferedImage) ImageIO.read(new File(args[0]));
MyTrans at = new MyTrans();
AffineTransformOp at2 = new AffineTransformOp(new AffineTransform(), AffineTransformOp.TYPE_BILINEAR);
System.err.println("Bad = "+at.getTransform());
System.err.println("Good = "+at2.getTransform());
BufferedImage bi1 = at.filter(from,null);//1
BufferedImage bi2 = at2.filter(from,null);//2
}
}
class MyTrans extends AffineTransformOp {
public MyTrans() {
super(new AffineTransform(), TYPE_BILINEAR);
}
}
标有 1 的行抛出 ImagingOpException:Unable to transform src image
。但是我注释掉了那一行,然后下一行(做完全相同的事情)运行顺利。这里的变换只是恒等变换。我在 Ubuntu 16.04 上使用 java 8。任何 png 或 jpeg 图像都会导致此问题,所以我没有附加图像。
AffineTransformOp.filter(src, dst) 在第 284 行从包 sun.awt.image.ImagingLib 内部调用 ImagingLib.filter(this, src, dst)。
...
if (ImagingLib.filter(this, src, dst) == null) {
throw new ImagingOpException ("Unable to transform src image");
}
...
我们观察到的行为与 ImagingLib.filter() 的实现方式有关。此方法检查第一个参数是否对应于以下任何一个 classes:
- 查找操作
- 仿射变换运算
- 卷积运算
当调用 ImagingLib.filter 时,传递给函数的第一个参数是 this。在您编写的示例代码中:at.class 等于 "MyTrans" 并且 at2.class 等于 "AffineTransformOp".
看看下面的代码,它属于ImagingLib.filter()源代码。
public static BufferedImage filter(BufferedImageOp var0, BufferedImage var1, BufferedImage var2) {
...
BufferedImage var3 = null;
switch(getNativeOpIndex(var0.getClass())) {
case 0:
LookupTable var4 = ((LookupOp)var0).getTable();
if (var4.getOffset() != 0) {
return null;
}
if (var4 instanceof ByteLookupTable) {
ByteLookupTable var9 = (ByteLookupTable)var4;
if (lookupByteBI(var1, var2, var9.getTable()) > 0) {
var3 = var2;
}
}
break;
case 1:
AffineTransformOp var5 = (AffineTransformOp)var0;
double[] var6 = new double[6];
AffineTransform var7 = var5.getTransform();
var5.getTransform().getMatrix(var6);
if (transformBI(var1, var2, var6, var5.getInterpolationType()) > 0) {
var3 = var2;
}
break;
case 2:
ConvolveOp var8 = (ConvolveOp)var0;
if (convolveBI(var1, var2, var8.getKernel(), var8.getEdgeCondition()) > 0) {
var3 = var2;
}
}
if (var3 != null) {
SunWritableRaster.markDirty(var3);
}
return var3;
}
}
因此,当调用 getNativeOpIndex(var0.getClass()) 时,因为 "MyTrans" 不是预期的 class 类型,它 returns -1 因此它不会处理开关上的任何情况,并返回 null。