前段时间项目里用到了画图,发布到服务器之后,图片处理程序报错:java.lang.IncompatibleClassChangeError:Found class com.sun.image.codec.jpeg.JPEGImageEncoder, but interface was expected
查了下服务器的JRE是用的openjdk,将openjdk换成SUN的标准JDK就可以了。
下面是个画图的简单例子:
import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGImageEncoder; @SuppressWarnings("restriction") public class Example { public static void draw(){ /** * BufferedImage(int width, int height, int imageType) * 构造一个类型为预定义图像类型之一的 BufferedImage。 */ BufferedImage bufferedImage = new BufferedImage(500, 300, BufferedImage.TYPE_3BYTE_BGR); /** * createGraphics() 创建一个 Graphics2D,可以将它绘制到此 BufferedImage 中。 */ Graphics2D graphics2d = bufferedImage.createGraphics(); /** * setBackground(Color color) 设置 Graphics2D 上下文的背景色。 */ graphics2d.setBackground(Color.WHITE); /** * public abstract void clearRect(int x,int y,int width,int height) * 通过使用当前绘图表面的背景色进行填充来清除指定的矩形。此操作不使用当前绘图模式。 * 从 Java 1.1 开始,离屏图像的背景色可能与系统相关。 * 应用程序应该使用 setColor,然后使用 fillRect,以确保离屏图像被清除为指定颜色。 * 参数: * x - 要清除矩形的 x 坐标。 * y - 要清除矩形的 y 坐标。 * width - 要清除矩形的宽度。 * height - 要清除矩形的高度。 * */ graphics2d.clearRect(0, 0, 500, 300); /** * public abstract void setColor(Color c) * 将此图形上下文的当前颜色设置为指定颜色。 * 使用此图形上下文的所有后续图形操作均使用这个指定的颜色。 * 参数: * c - 新的呈现颜色。 * */ graphics2d.setColor(Color.RED); Font font = new Font("sansserif", Font.PLAIN, 18); /** * 将此图形上下文的字体设置为指定字体。 * 使用此图形上下文的所有后续文本操作均使用此字体。忽略 null 参数 */ graphics2d.setFont(font); /** * public abstract void fillRect(int x,int y,int width,int height) * 填充指定的矩形。该矩形左边缘和右边缘分别位于 x 和 x + width - 1。 * 上边缘和下边缘分别位于 y 和 y + height - 1。 * 得到的矩形覆盖 width 像素宽乘以 height 像素高的区域。 * 使用图形上下文的当前颜色填充该矩形。 * */ graphics2d.fillRect(0, 0, 500, 30); graphics2d.setColor(Color.WHITE); graphics2d.drawString("简单的例子", 200, 20); font = new Font("sansserif", Font.PLAIN, 16); graphics2d.setFont(font); graphics2d.setColor(Color.RED); /** * public abstract void fillOval(int x,int y,int width,int height) * 使用当前颜色填充外接指定矩形框的椭圆。 * 参数: * x - 要填充椭圆的左上角的 x 坐标。 * y - 要填充椭圆的左上角的 y 坐标。 * width - 要填充椭圆的宽度。 * height - 要填充椭圆的高度。 * */ graphics2d.fillOval(20, 40, 20, 20); graphics2d.setColor(Color.ORANGE); graphics2d.fillOval(40, 60, 20, 20); graphics2d.setColor(Color.YELLOW); graphics2d.fillOval(60, 80, 20, 20); graphics2d.setColor(Color.GREEN); graphics2d.fillOval(80, 100, 20, 20); graphics2d.setColor(Color.CYAN); graphics2d.fillOval(100, 120, 20, 20); graphics2d.setColor(Color.BLUE); graphics2d.fillOval(120, 140, 20, 20); graphics2d.setColor(Color.MAGENTA); graphics2d.fillOval(140, 160, 20, 20); graphics2d.setColor(Color.MAGENTA); graphics2d.fillOval(340, 160, 20, 20); graphics2d.setColor(Color.BLUE); graphics2d.fillOval(360, 140, 20, 20); graphics2d.setColor(Color.CYAN); graphics2d.fillOval(380, 120, 20, 20); graphics2d.setColor(Color.GREEN); graphics2d.fillOval(400, 100, 20, 20); graphics2d.setColor(Color.YELLOW); graphics2d.fillOval(420, 80, 20, 20); graphics2d.setColor(Color.ORANGE); graphics2d.fillOval(440, 60, 20, 20); graphics2d.setColor(Color.RED); graphics2d.fillOval(460, 40, 20, 20); /** * public abstract void drawLine(int x1,int y1,int x2,int y2) * 在此图形上下文的坐标系中,使用当前颜色在点 (x1, y1) 和 (x2, y2) 之间画一条线。 * 参数: * x1 - 第一个点的 x 坐标。 * y1 - 第一个点的 y 坐标。 * x2 - 第二个点的 x 坐标。 * y2 - 第二个点的 y 坐标。 * */ graphics2d.setColor(Color.RED); for(int m=0;m<5;m++){ graphics2d.drawLine(0, 190+m*20, 500, 190+m*20); } graphics2d.setColor(Color.RED); for(int n=0;n<25;n++){ graphics2d.drawLine(0+n*20, 190, 0+n*20, 270); } /** * public abstract void dispose()释放此图形的上下文以及它使用的所有系统资源。 * 调用 dispose 之后,就不能再使用 Graphics 对象。 * Java 程序运行时,可以在一个短时间帧内创建大量的 Graphics 对象。 * 尽管垃圾回收器的终止进程也能够进行相同的系统资源释放, * 但是最好通过调用此方法来手工释放相关资源,而不是依靠终止进程, * 因为终止进程需要很长时间才能结束运行。 * 作为组件 paint 和 update 方法的参数提供的 Graphics 对象, * 在这些方法返回时将被系统自动释放。 * 为了提高效率,仅当所使用的 Graphics 对象 * 是由组件或另一个 Graphics 对象直接创建时, * 程序员才应在使用完此 Graphics 后调用 dispose。 * */ graphics2d.dispose(); /** * public void flush() * 刷新此 Image 对象正在使用的所有可重构的资源。 * 这包括为呈现到屏幕而缓存的所有像素数据, * 以及用来存储图像数据或像素的所有系统资源(如果可以重新创建它们)。 * 图像被重置为与初始创建时类似的状态,因此如果再次呈现图像, * 则必须重新创建图像数据或再次从源中获取这些数据。 * 此方法如何影响特定类型的 Image 对象的示例如下: * BufferedImage 对象不改动存储其像素的主要 Raster,但是刷新有关像素的缓存信息, * 比如上传到用于加速位图的显示硬件的副本。 * Image 对象由带有 width 和 height 参数的 Component 方法创建, * 该方法不改动像素的主要缓冲区,但是释放所有缓存的信息, * 这与对 BufferedImage 对象的操作非常类似。 * VolatileImage 对象释放其所有像素资源, * 这些资源包括通常存储在缺乏资源的显示硬件上的主要副本。 * 这些对象稍后可以使用其 validate 方法还原。 * 卸载从文件、URL 中加载或由 ImageProducer 生成的 Toolkit * 和 Component 类创建的 Image 对象,并释放所有本地资源。 * 稍后可在呈现这些对象时根据需要从初始源重新加载它们,就像第一次创建它们时那样。 * */ bufferedImage.flush(); String filepath = "D:/draw.jpeg"; File imgfile = new File(filepath); FileOutputStream fos; try{ fos = new FileOutputStream(imgfile); BufferedOutputStream bos = new BufferedOutputStream(fos); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bos); encoder.encode(bufferedImage); bos.close(); }catch (FileNotFoundException e){ e.printStackTrace(); }catch (IOException e){ e.printStackTrace(); } } public static void main(String[] args) { draw(); } }