具体要求如下:一、切割掉原始图片的上四行和左四列像素,重新生成一张切割后图像。
              二、使用原始图像的压缩算法和图像质量生成切割图片。(这才是重点)PS:压缩算法为1998年公布的标准最好是能直接运行的java代码,输入一张图片-》按要求切-》输出现在只能给100分,如果能搞定再开几个贴把剩下的200分都奉上。

解决方案 »

  1.   

    切割图片的方法,应该还是不难的。例如:import java.awt.Graphics;
    import java.awt.Image;
    import java.awt.Toolkit;
    import java.awt.image.BufferedImage;
    import java.awt.image.CropImageFilter;
    import java.awt.image.FilteredImageSource;
    import java.awt.image.ImageFilter;
    import java.io.File;import javax.imageio.ImageIO;public class CutImage {

    public static void main(String[] args) {
    cut("f://tu.gif","f://cut//tu1.gif",200,200,".gif");
    } /**
     * @param srcImage   源图片存放位置
     * @param descImage  切割后图片存放位置
     * @param cutWidth   切割的宽度
     * @param cutHeight  切割的高度
     * @param imgKind    保存的文件类型
     */
    public static void cut(String srcImage, String descImage, int cutWidth,int cutHeight,String imgKind) {
    try {
    Image img;
    ImageFilter cropFilter;
    BufferedImage srcImg = ImageIO.read(new File(srcImage));

    int srcWidth = srcImg.getHeight(); // 源图宽度
    int srcHeight = srcImg.getWidth(); // 源图高度
    if (srcWidth > cutWidth && srcHeight > cutHeight) {
    Image image = srcImg.getScaledInstance(srcWidth, srcHeight,Image.SCALE_DEFAULT); int cols = 0; // 切片横向个数
    int rows = 0; // 切片纵向个数
    // 计算切片的横向和纵向数量
    if (srcWidth % cutWidth == 0) {
    cols = srcWidth / cutWidth;
    } else {
    cols = (int) Math.floor(srcWidth / cutWidth) + 1;
    }
    if (srcHeight % cutHeight == 0) {
    rows = srcHeight / cutHeight;
    } else {
    rows = (int) Math.floor(srcHeight / cutHeight) + 1;
    }

    // 循环建立切片
    for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
    cropFilter = new CropImageFilter(j * cutWidth, i * cutHeight, cutWidth, cutHeight);
    img = Toolkit.getDefaultToolkit().createImage(
    new FilteredImageSource(image.getSource(),cropFilter));
    BufferedImage tag = new BufferedImage(cutWidth,
    cutHeight, BufferedImage.TYPE_INT_RGB);
    Graphics g = tag.getGraphics();
    g.drawImage(img, 0, 0, null); // 绘制缩小后的图
    g.dispose();
    // 输出为文件
    ImageIO.write(tag, "JPEG", new File(descImage
    + "_" + i + "_" + j + imgKind));
    }
    }
    System.out.println("切割成功!");
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }
      

  2.   

    以这个为准吧,刚发的,宽和高有个地方写反了。
    这里先将上面,左边四个象素切掉,然后分割成若干个小图片。
    import java.awt.Graphics;
    import java.awt.Image;
    import java.awt.Toolkit;
    import java.awt.image.BufferedImage;
    import java.awt.image.CropImageFilter;
    import java.awt.image.FilteredImageSource;
    import java.awt.image.ImageFilter;
    import java.io.File;import javax.imageio.ImageIO;public class CutImage {

    public static void main(String[] args) {
    cut("f://tu.gif","f://cut//tu1.gif",200,200,".gif");
    } /**
     * @param srcImage   源图片存放位置
     * @param descImage  切割后图片存放位置
     * @param cutWidth   切割的宽度
     * @param cutHeight  切割的高度
     * @param imgKind    保存的文件类型
     */
    public static void cut(String srcImage, String descImage, int cutWidth,int cutHeight,String imgKind) {
    try {
    Image img;
    Image imgafter;
    ImageFilter cropFilter;
    BufferedImage tag;
    Graphics g;
    BufferedImage srcImg = ImageIO.read(new File(srcImage));

    int srcHeight = srcImg.getHeight(); // 源图宽度
    int srcWidth = srcImg.getWidth(); // 源图高度
    if (srcWidth > cutWidth && srcHeight > cutHeight) {
    //切掉上面,左边四个像素
    Image image = srcImg.getScaledInstance(srcWidth, srcHeight,Image.SCALE_DEFAULT);
    cropFilter = new CropImageFilter(4, 4, srcWidth, srcHeight);
    imgafter = Toolkit.getDefaultToolkit().createImage(
    new FilteredImageSource(image.getSource(),cropFilter));
    tag = new BufferedImage(srcWidth - 4, srcHeight - 4, BufferedImage.TYPE_INT_RGB);
    g = tag.getGraphics();
    g.drawImage(imgafter, 0, 0, null); // 绘制缩小后的图
    g.dispose();
    srcWidth -= 4;
    srcHeight -= 4; //分割成多个图片
    int cols = 0; // 切片横向个数
    int rows = 0; // 切片纵向个数
    // 计算切片的横向和纵向数量
    if (srcWidth % cutWidth == 0) {
    cols = srcWidth / cutWidth;
    } else {
    cols = (int) Math.floor(srcWidth / cutWidth) + 1;
    }
    if (srcHeight % cutHeight == 0) {
    rows = srcHeight / cutHeight;
    } else {
    rows = (int) Math.floor(srcHeight / cutHeight) + 1;
    }

    // 循环建立切片
    for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
    cropFilter = new CropImageFilter(j * cutWidth, i * cutHeight, cutWidth, cutHeight);
    img = Toolkit.getDefaultToolkit().createImage(
    new FilteredImageSource(imgafter.getSource(),cropFilter));
    tag = new BufferedImage(cutWidth,
    cutHeight, BufferedImage.TYPE_INT_RGB);
    g = tag.getGraphics();
    g.drawImage(img, 0, 0, null); // 绘制缩小后的图
    g.dispose();
    // 输出为文件
    ImageIO.write(tag, "JPEG", new File(descImage
    + "_" + i + "_" + j + imgKind));
    }
    }
    System.out.println("切割成功!");
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }
      

  3.   

    我觉得1、2楼给出的算法不对吧楼主是要“切割掉原始图片的上四行和左四列像素,重新生成一张切割后图像。”你给出来的是将其按照 4行4列像素 将其切割为一小块一小块的。至于楼主关注的“图片的质量和压缩算法如何保持与源图像一致”,这个先把图片文件的扩展名获取到;
    然后:ImageIO.write(image, 扩展名, new File(...));
    目前Java本源支持的包括:jpg、jpeg、png、gif、bmp
      

  4.   

    对了,顺便推荐个Java的图像处理组件,各类切割、模糊、锐化等操作都封装的很好,而且性能很好:
      http://www.jhlabs.com/ip/filters/index.html最后面有很多效果图可以参考。
      

  5.   

    ImageIO.write(image, 扩展名, new File(...));这个函数默认情况下肯定会压缩图片的,压缩算法也不一定是原来的
      

  6.   

    如果要更精确的判断图片类型,可以尝试用:
        /**
         * 获取指定文件格式
         * @param obj 输入源:File, RandomAccessFile, InputStream
         * @return 格式类型名,null为无法识别
         * @throws IOException 异常
         */
        public static String getFormatName(Object obj) throws IOException {
            // Create an image input stream on the image
            ImageInputStream iis = ImageIO.createImageInputStream(obj);        // Find all image readers that recognize the image format
            Iterator<ImageReader> iter = ImageIO.getImageReaders(iis);
            if (!iter.hasNext()) {
                // No readers found
                return null;
            }        // Use the first reader
            ImageReader reader = iter.next();        // Close stream
            iis.close();        // Return the format name
            return reader.getFormatName();
        }
    把所获取的格式,直接用于压缩算法名称就行了。而且 bmp 就是不压缩的。切割及保存过程很简单:    public static void main(String[] args) throws Exception {
            String filepath = "img.png";
            
            // 先获取图片的压缩格式类型
            InputStream is = ClassLoader.getSystemResourceAsStream(filepath);
            String imageType = getFormatName(is);
            System.out.println("ImageType: " + imageType);
            
            // 切割文件后保存
            InputStream source = ClassLoader.getSystemResourceAsStream(filepath);
            BufferedImage imgSource = ImageIO.read(source);
            BufferedImage imgAfterCut = imgSource.getSubimage(44, 55, imgSource.getWidth() - 44, imgSource.getHeight() - 55); // 直接完成切割:x, y, width, height
            ImageIO.write(imgAfterCut, imageType, new File(".\\new." + imageType));
        }
      

  7.   


    不能保证,各种不同软件虽然都遵循相同的压缩标准,但其所实现的压缩实际效果,是绝对不一样的。你用 rar 和 360zip ,对同一个文件进行zip压缩,结果就是完全不一样的。
    所以,除非你原始图片就是使用Java的相同算法所压缩,否则重新压缩后一定不相同。此外,你可以试着用PhotoShop打开一张 jpg 图片,然后按无损压缩直接保存像素为 bmp;最后再用PhotoShop打开该bmp,然后另存为jpg;你会看到新的这张jpg和之前原始的jpg是不一样的。
    所以,楼主你基本上不能执着于这个问题。
      

  8.   

     public static void main(String[] args) throws Exception {
            String filepath = "img.png";
            
            // 先获取图片的压缩格式类型
            InputStream is = ClassLoader.getSystemResourceAsStream(filepath);
            String imageType = getFormatName(is);
            System.out.println("ImageType: " + imageType);
            
            // 切割文件后保存
            InputStream source = ClassLoader.getSystemResourceAsStream(filepath);
            BufferedImage imgSource = ImageIO.read(source);
            BufferedImage imgAfterCut = imgSource.getSubimage(44, 55, imgSource.getWidth() - 44, imgSource.getHeight() - 55); // 直接完成切割:x, y, width, height
            ImageIO.write(imgAfterCut, imageType, new File(".\\new." + imageType));
        }这段代码,如果我不切的话能保证原图像和生成图像一样大小么(KB)
      

  9.   

    import java.io.*;
    public class BisicImageCopy {
    public static void main(String[] args) {
    FileInputStream fin = null;
    FileOutputStream fout = null;
    try {
    fin = new FileInputStream("e:\\1.jpg");
    fout = new FileOutputStream("e:\\2.jpg");
    byte[] b = new byte[512];
    int n;
    while((n = fin.read(b))!=-1){
    fout.write(b,0,n-1);
    }
    } catch (Exception e) {
    e.printStackTrace();
    }finally{
    try {
    fin.close();
    fout.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    如果我用字节流拷贝的方法确实能一样大小,可是怎么能把他切掉四行四列呢,好像我改掉一位生成的图像就不能在显示了
      

  10.   

     public static void main(String[] args) throws Exception {
            String filepath = "e:\\1.jpg";
            
            // 先获取图片的压缩格式类型
            InputStream is = ClassLoader.getSystemResourceAsStream(filepath);
            //String imageType = getFormatName(is);
            //System.out.println("ImageType: " + imageType);
            
            // 切割文件后保存
            InputStream source = ClassLoader.getSystemResourceAsStream(filepath);
            BufferedImage imgSource = ImageIO.read(source);
            BufferedImage imgAfterCut = imgSource.getSubimage(4, 5, imgSource.getWidth() - 4, imgSource.getHeight() - 5); // 直接完成切割:x, y, width, height
            ImageIO.write(imgAfterCut, "jpg", new File(".\\new." + "jpg"));
        }这段代码会产生运行错误,Exception in thread "main" java.lang.IllegalArgumentException: input == null!
    at javax.imageio.ImageIO.read(Unknown Source)
    at la.main(la.java:27)
    我源文件确实是有的,
      

  11.   

    String filepath = "e:\\1.jpg"; 这个是直接指定路径的方式,要把:
      ClassLoader.getSystemResourceAsStream(filepath);
    全部换成:
      new FileInputStream(filepath);
    我原来的写法,是假定图片在src目录中,按资源进行访问的。
      

  12.   

    楼上各位给出的切割办法最后生成的图片都能完成4行4列切割的任务,但是生成的图片基本都为原图片的四分之一大小 eg 400KB切完100KB这肯定不完全是四行四列的损失,试验要做到控制单一变量,能不能让图片的损失仅为切割掉的四行四列,这是我最需要解决的
      

  13.   

    ImageIO不支持对压缩比率进行控制。如果你要设置压缩比率以降低失真度,需要自行根据每一种图片类型使用sun提供的压缩工具,类似:
    JPEGCodec encoder= JPEGCodec.createJPEGEncoder(out); // 输出流
    JPEGEncodeParam param= encoder.getDefaultJPEGEncodeParam(imgSource); // 原始图片参数    
    param.setQuality(imageQuality, false); // 设置压缩比率
    encoder.setJPEGEncodeParam(param); // 设置图片参数         
    encoder.encode(imgSource);// 将图片进行JPEG编码并输出到out中
    out.close();
      

  14.   

    这可能是由于图像类型选择导致的,楼主可查看api,BufferedImage有一些属性,创建BufferedImage对象的时候可选择。
    另外看下Image.SCALE_DEFAULT,它也有其它属性。象素的要求达到的,颜色上,肉眼看不出的区别就可以,也不用那么精确的。
      

  15.   

    import java.io.*;
    public class BisicImageCopy {
    public static void main(String[] args) {
    FileInputStream fin = null;
    FileOutputStream fout = null;
    try {
    fin = new FileInputStream("e:\\1.jpg");
    fout = new FileOutputStream("e:\\2.jpg");
    byte[] b = new byte[512];
    int n;
    while((n = fin.read(b))!=-1){
    fout.write(b,0,n-1);
    }
    } catch (Exception e) {
    e.printStackTrace();
    }finally{
    try {
    fin.close();
    fout.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    通过字节流拷贝方法可以完整拷贝图片,那么怎么能切掉四行四列并且让图片在显示出来呢