`
Jen
  • 浏览: 57526 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

缩略图与原图不一致的java实现

    博客分类:
  • java
阅读更多

07年写的文章,这个博客开了很久了一直没写,把旧博客上的这篇移到这里。从现在开始用这个博客

     昨天早上朋友传给我一张图片,曾被此君的一些恶作剧图片吓倒过,这次刚开始也不敢打开。这张图片在winxp下缩略图显示与打开后的内容不一样,让几个同学看了一下,他们都说看过了。就是前段时间网上流传的‘一张令所有人吃惊的图片’,是一张椅子的图片,但是,如果你的系统是XP,把它下载后保存到任意一个文件夹中,打开文件夹,用缩略图的方式查看,会看到图片的缩略图是一个机器女人坐在地上。



很惊奇,但直觉的反映就是这张图片可能被存储了别的信息或修改了头文件信息。
      经过一番研究之后,知道了原理:JPEG标准在文件中记录了一些EXIF信息,缩略图是一幅较小的JPEG图片,存储在EXIF信息段。而Windows在第一次显示缩略图时先读当前目录中的"Thumbs.db"这个文件,其实这是一个缩略图数据库,从而来判断是否有该图片的缩略图。如果不存在"Thumbs.db"文件或者该库中不存在该图片的缩略图,那么Windows会尝试取图片中的EXIF信息,判断是否存在缩略图数据。如果图片中EXIF信息中不存在缩略图信息或信息错误,那么Windows就会用插值的方法重新生成缩略图(如果可能则保存到当前目录中的"Thumbs.db"缩略图数据库中)。 对于修改缩略图方法有用ultraEdit直接编辑文件替换EXIF信息或用exifer这样的工具,这不是本文关心的内容,本文介绍用java实现的方法。
      程序把一张jpg格式图片的缩略图用另一张图的内容替换,实现的效果跟上面一样

 

      实现原理就是抽取一张图片的信息,然后替换掉另一张图片EXIF的Thumbnail。注意抽取的图片长宽比例要与原图一致,否则没有效果,在程序中我已经自动判断并调整了。下面是抽取信息的一个主要方法:
public static byte[] getThumbnailImage(InputStream ip,int widthRate,int heightRate) throws IOException

//根据文件名字符串,按长宽比例放缩抽取该文件的ThumbnailImage,此方法调用到getThumbnailImage(),返回byte数组
private byte[] extractThumbnail(String fileStr,int widthRate,int heightRate)

向另一张图片写入Thumbnail的方法,用到mediautil库:
public void writeThumbnail(byte newThumbnail[],String fileStr)

主方法,thumbnailFile为要抽取缩略图信息的图片,destfile为目标图片也就是把它的缩略图用thumbnailFile信息替换掉
public void test(String thumbnailFile,String destfile){
     BufferedImage buf=null;
     int wRate=0;
     int hRate=0;
     try{
         //获取destfile的长和宽,供放缩thumbnailFile使用
         buf=readImage(destfile);
         wRate=buf.getWidth();
         hRate=buf.getHeight();
     }catch(Exception e){e.printStackTrace();}
     finally{
         byte[] bt=extractThumbnail(thumbnailFile,wRate,hRate);//抽取thumbnailFile数据,存入bt中
         writeThumbnail(bt,destfile);//向文件名为destfile的图片中写入bt中的thumbnail数据
     }
———————————————下面是全部源代码———————————————
import java.io.*;
import java.util.Date;
import java.awt.*;
import java.awt.image.*;
import java.util.*;
import javax.imageio.*;
import javax.imageio.stream.ImageInputStream;
import mediautil.gen.directio.*;
import mediautil.gen.Log;
import java.awt.geom.AffineTransform;
import mediautil.image.ImageResources;
import mediautil.image.jpeg.LLJTran;
import mediautil.image.jpeg.AbstractImageInfo;
import mediautil.image.jpeg.Exif;
import mediautil.image.jpeg.Entry;
import mediautil.image.jpeg.LLJTranException;
public class TestExif {
/**
     * Utility Method to get a Thumbnail Image in a byte array from an
     * InputStream to a full size image. The full size image is read and scaled
     * to a Thumbnail size using Java API.
     */
    private static byte[] getThumbnailImage(InputStream ip) throws IOException{
        return getThumbnailImage(ip,0,0);
    }

public static byte[] getThumbnailImage(InputStream ip,int widthRate,int heightRate) throws IOException {
        ImageReader reader;
        ImageInputStream iis = ImageIO.createImageInputStream(ip);
        reader = (ImageReader) ImageIO.getImageReaders(iis).next();
        reader.setInput(iis);
        BufferedImage image = reader.read(0);
        iis.close();

        int t, longer, shorter;
        if(widthRate>0&&heightRate>0){
             longer = widthRate;
             shorter = heightRate;
        }else{
             longer = image.getWidth();
             shorter = image.getHeight();
        }
              
       //按传入参数的长宽比例放缩
       double factor = 160/(double)image.getWidth();
        double factor2 =(160* (double)shorter)/((double)longer*image.getHeight());
        AffineTransform tx = new AffineTransform();
        tx.scale(factor, factor2);
        AffineTransformOp affineOp = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
        image = affineOp.filter(image, null);

         // Write Out the Scaled Image to a ByteArrayOutputStream and return the bytes
         ByteArrayOutputStream byteStream = new ByteArrayOutputStream(2048);
         String format = "JPG";
         ImageIO.write(image, format, byteStream);
         System.out.println(byteStream.toByteArray());
         return byteStream.toByteArray();
}
    public byte[] extractThumbnail(String fileStr){
     return extractThumbnail(fileStr,0,0);
    }

//根据文件名字符串,按长宽比例放缩抽取该文件的ThumbnailImage,返回byte数组
private byte[] extractThumbnail(String fileStr,int widthRate,int heightRate) {
  byte newThumbnail[]=null;
     try{
      InputStream fip = new FileInputStream(fileStr); // No need to buffer
      SplitInputStream sip = new SplitInputStream(fip);
      //Create a substream for LLJTran to use
      InputStream subIp = sip.createSubStream();
      LLJTran llj = new LLJTran(subIp);
      llj.initRead(LLJTran.READ_HEADER, true, true);  
      sip.attachSubReader(llj, subIp);
      newThumbnail= getThumbnailImage(sip,widthRate,heightRate);
      sip.wrapup();
      fip.close();
      llj.freeMemory();
      String msg = llj.getErrorMsg();
      if(msg != null){
         System.out.println("Error in LLJTran While Loading Image: " + msg);
         Exception e = llj.getException();
         if(e != null){
            System.out.println("Got an Exception, throwing it..");
             throw e;
          }
             System.exit(1);
      }
     }catch(Exception e){System.out.println("extractThumbnail"+e);}
      return newThumbnail;
}
//向另一张图片写入Thumbnail的方法,用到mediautil库:
public void writeThumbnail(byte newThumbnail[],String fileStr){
     try{
      InputStream fip = new FileInputStream(fileStr);
      LLJTran llj = new LLJTran(fip);
      llj.read(LLJTran.READ_ALL,true);
      
      AbstractImageInfo imageInfo = llj.getImageInfo();
      //important!!!!  If the Image does not have an Exif Header create a dummy Exif
      //Header
      if(!(imageInfo instanceof Exif)){
                System.out.println("Adding a Dummy Exif Header");
                llj.addAppx(LLJTran.dummyExifHeader, 0,
                            LLJTran.dummyExifHeader.length, true);
      }

       //  Set the new Thumbnail
      if(llj.setThumbnail(newThumbnail, 0, newThumbnail.length,ImageResources.EXT_JPG))
       System.out.println("Successfully Set New Thumbnail");
      fip = new BufferedInputStream(new FileInputStream(fileStr));
      OutputStream out = new BufferedOutputStream(new FileOutputStream("3.jpg"));
      //
      llj.xferInfo(fip, out, LLJTran.REPLACE, LLJTran.REPLACE);
      fip.close();
      out.close();
     // Cleanup
      llj.freeMemory();
     }catch(Exception e){System.out.println("writeThumbnail"+e);}
    }
    
  public BufferedImage readImage(InputStream in,String type)throws IOException{
       Iterator readers = ImageIO.getImageReadersByFormatName(type);
       ImageReader reader = (ImageReader)readers.next();
       ImageInputStream iis = ImageIO.createImageInputStream(in);
       reader.setInput(iis,true);
       BufferedImage img = reader.read(0);  
       return img;
  }
  public BufferedImage readImage(String fileName) throws IOException{
       String type = fileName.substring(fileName.lastIndexOf(".")+1);
       return readImage(new FileInputStream(fileName), type);
  }
    
   public void test(String thumbnailFile,String destfile){         BufferedImage buf=null;
        int wRate=0;
        int hRate=0;
        try{
         buf=readImage(destfile);
         wRate=buf.getWidth();
         hRate=buf.getHeight();
     }catch(Exception e){e.printStackTrace();}
     finally{
         byte[] bt=extractThumbnail(thumbnailFile,wRate,hRate);
         writeThumbnail(bt,destfile);
      }  
    }
        
    public static void main(String arg[]){
      TestExif t= new TestExif();
       t.test("11.jpg", "22.jpg"); //用11.jpg的数据替换22.jpg的缩略图
    }

  • 大小: 12.5 KB
  • 大小: 34.4 KB
分享到:
评论

相关推荐

    java 图片生成缩略图

    "java 图片生成缩略图" Java 图片生成缩略图是Java程序开发中一个常见的需求,通过将图片以缩略图形式展示,可以提高用户体验和网站性能。在本文中,我们将介绍使用Java生成缩略图的方法。 缩略图生成方法 在 ...

    java 上传图片生成缩略图

    本文介绍了使用Java实现上传图片并生成缩略图的方法,包括获取文件路径、读取图像、创建缩略图及保存缩略图等步骤。通过这种方式,可以在不损失原图质量的前提下,有效地减少加载时间,提升用户体验。此外,本文还...

    动态缩略图实现方案

    动态缩略图是一种在网页或应用中常见的技术,它允许用户根据需要查看不同尺寸的图片,通常是缩小版的原图,以节省加载时间并优化用户体验。在Java中实现动态缩略图涉及到图像处理和流媒体技术。下面我们将深入探讨这...

    Java实现图片等比例缩略图

    本篇文章将深入探讨如何使用Java实现图片的等比例缩略图,并提供相关代码示例。 首先,我们需要了解等比例缩略图的概念。等比例缩略图是指在保持原图宽高比的基础上,根据指定的最大尺寸进行缩小或放大。这样可以...

    plupload和java后台实现多图上传并把缩略图跟上传的url显示到画面上

    plupload和java后台实现多图上传并把缩略图跟上传的url显示到画面上 1、使用jQuery的plupload实现上传功能,前台无需太多配置,简单修改即可符合您的要求。虽然是jQuery虽然是plupload,但是大多需要手动修改的地方...

    java生成缩略图

    根据提供的文件信息,我们可以总结出以下关于“Java生成缩略图”的相关知识点: ### Java生成缩略图基础知识 ...以上是对“Java生成缩略图”这一主题的详细解析和技术实现,希望对理解和应用相关技术有所帮助。

    java缩略图

    一个不错的工具类,上传的图片根据长宽的判断,按比例缩放生成另一张小图,可以减少浏览的浪费

    Java 高清缩略图

    在这个场景下,我们关注的是如何在Java中生成缩略图,同时确保缩略图与原图的根目录不同,但其他路径保持一致。我们将探讨`simpleimage`库,它是一个用于图像处理的简洁工具,以及如何使用它来实现等比例缩放,以...

    java实现将图片和缩略图存储到数据库中.pdf

    ### Java 实现将图片和缩略图存储到数据库中的详细解析 #### 一、知识点概述 本文档主要介绍如何使用Java编程语言实现将图片及其对应的缩略图存储到数据库中的功能。这一技术在多种场景下都非常有用,比如在线商城...

    上传图片(缩略图)

    - **延迟生成**:如果缩略图不是立即需要,可以先保存原图,等需要时再生成缩略图,减少服务器负载。 - **缓存机制**:对于已经生成的缩略图,可以缓存起来,下次请求时直接返回,提高响应速度。 - **CDN分发**:...

    ImageScale java 缩略图 算法

    缩略图是指按照一定的比例缩小原图尺寸的图片,通常用于预览或快速浏览。在Java中,生成缩略图主要涉及到图像处理库,如Java的`java.awt.image`和`javax.imageio`包。 `ImageScale`算法的核心在于如何有效地调整...

    缩略图水印组件源代码

    此组件应包含了根据原图生成缩略图的算法,可能支持多种图像格式如JPEG、PNG等。 3. **Web开发**:组件以`.aspx`文件结尾,表明它是基于ASP.NET平台的,使用C#语言(`.cs`文件)进行后端逻辑处理。`.aspx`页面是ASP...

    jSP上传图片生成缩略图

    "bianxiaotu"可能是用于生成缩略图的Java类或工具的名称,具体实现可能因项目而异,但核心思想与上述步骤一致。总的来说,这个任务结合了JSP页面交互、文件上传处理以及图像处理技术,是Web开发中的一个典型应用场景...

    javapng透明图片缩略

    在Java编程中,生成PNG透明图片的缩略图是一项常见的任务,特别是在开发图形用户界面、网站或移动应用时。PNG格式因其支持透明度而受到欢迎,但缩略图的生成需要考虑保持图像质量和透明效果。以下是一些关于如何在...

    jsp上传图片并生成缩略图

    综上所述,实现"jsp上传图片并生成缩略图"的过程涉及到文件上传处理、图片的读取与缩放、文件存储以及错误处理等多方面技术。通过合理的设计和选用合适的工具库,可以在JSP中有效地实现这一功能。在实际开发中,还...

    java生成缩略图.zip

    在这个"java生成缩略图.zip"压缩包中,我们可能找到了一份Java源代码,用于演示如何在Java环境下创建图像的缩略图。 首先,我们要了解在Java中生成缩略图的关键概念和技术。Java的`java.awt.image`和`javax.imageio...

    缩略图的显示

    3. **裁剪与比例保持**:如果原图像宽高比与缩略图宽高比不同,可能需要进行裁剪以保持原始比例。这可以通过中心裁剪或基于特定区域的裁剪实现。 4. **质量优化**:为了减小存储和加载时间,缩略图通常会降低色彩...

    struts2图片上传并生成缩略图,展示缩略图点击显示大图

    生成缩略图后,将其保存到服务器,并更新文件名以区别于原图。例如,可以添加"thumbnail_"前缀。 为了在前端展示图片,可以创建一个JSP页面,用HTML和JavaScript来显示缩略图。这里我们可以使用jQuery的FancyBox...

    生成缩略图(压缩图片)

    这可以通过计算缩放比例来实现,确保缩略图不会失真。 3. 缩放操作:利用库提供的方法对图像进行缩放,如Java中的`AffineTransformOp`或PIL的`thumbnail`函数。 4. 写入新图像:最后,将缩放后的图像保存为新的...

Global site tag (gtag.js) - Google Analytics