注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

千鸟

本blog所有日志均系原创 转载请注明出处

 
 
 

日志

 
 

用java实现图片渐变叠加(3种方法)  

2007-06-15 21:18:20|  分类: J2SE |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

用java实现图片渐变叠加(3种方法) - souljava - 千鸟

用java实现图片渐变叠加是件很酷的事情,中文的实现资料几乎为0,搞了我好几天时间。

原理上是2种方法,但是可以用3种方法实现(没想到花了我那么多时间):1.是根据alpha值计算,象素的各单色分量衰减后相加;2.是修改一张图片的透明度,然后用画到另一张图片上面;3.是象素点的插值,不涉及透明度的使用。做的时候先试的第3种方法的,花的时间最多,结果发现效果最烂,象素差别过大看起来就像麻子一样。代码里的渐变范围是图片的1/4到3/4.自己可以修改的^_^。

最简单的是第2种方法。第3种效果最差,但是最容易想到。我最喜欢的是第1种。

代码和上一篇blog《用java分离象素》有很多重复的地方,但是为了众看客运行方便,重复的部分还是写了出来。

实现过程描述如下:

一。根据alpha值计算

  把图片的象素分离出来。原图的alpha值都设为0xff。确定一张图片A渐变的衰减系数div(0~1),另一张图片B的衰减就是1-div。

div=row/range; row是递增的行,range是渐变范围。

合成渐变的象素的公式我发现是:

color=(A.blue+A.green+A.red)*div+(B.blue+B.green+B.red)*(1-div)

A表示图片A的某点象素,B表示图片B的某点象素。当然实现上各种颜色不能直接相加,要位移相应的位,然后 进行或运算。

二。修改透明度

   修改图片B的渐变范围象素的alpha值,alpha为0就是透明,0xff为不透明。渐变就是alpha的值的递变。然后以图片B的大小,新建一个图像缓冲bi

Graphics2D g2= (Graphics2D)bi.getGraphics();
        g2.drawImage(imageA.getImage(),0,0,null)//将图片A画入缓冲区bi

        最后把修改好的半透明图片画入bi
        g2.drawImage(image,0,0,null);

最后完整的图片渐变叠加就保存在了这个缓冲区内。最后输出图片即可。

javax.imageio.ImageIO.write(bi, "JPEG", new java.io.File(filename));

我想应该还有别的办法可以实现:对两张图片的象素,基于alpha值进行计算,是可以合成渐变效果的象素 的。目前还没有试验出这个计算方法。

三。象素插值。等差数列的原理。

 有两张图片A,B,图片A的象素密度随横坐标的的增加减小,图片B的密度与图片A变化相反。

 我用的方法是,描述每一列相隔row行,需要插入一个象素。row这个变量的取值,在纸面上画出来的曲线,是在渐变区先增后减的一次函数。转折点是渐变区的中点。

 

下面的代码按顺序对应的上面的每种方法。每个程序用图片分割。

用java实现图片渐变叠加(3种方法) - souljava - 千鸟 

//SpliceCount.java
/*
 *author by liuke
 *email:  soulnew@gmail.com
 *blog:  souljava.blog.163.com
 **/

package com.soulnew.Pixel;
import java.awt.image.PixelGrabber;
import java.awt.Image;
import java.awt.image.ImageObserver;
import  javax.swing.ImageIcon;
import java.io.FileWriter;
import javax.swing.JFrame;
import java.awt.image.MemoryImageSource;
import  java.awt.Graphics2D;
import java.io.File;
public class SpliceCount{
 int pixels[];
 int Aw,Ah,Bw,Bh;
 int Wmax,Hmax;  //the size of splice image
 int arrayImageA[],arrayImageB[];   //arrays used to save the pixels
 String imagepathA="images/try.gif"; //you can change the image path here
 String imagepathB="images/fruit1.jpg";
 String outputimage="SpliceCount.jpg";
 FileWriter fw;  //used to write log
 int index=0;
 ImageIcon imageA,imageB;
 public SpliceCount(){
  
  imageA=new ImageIcon(imagepathA);
  imageB=new ImageIcon(imagepathB);
  
  Aw=imageA.getIconWidth();
  Ah=imageA.getIconHeight();
  Bw=imageB.getIconWidth();
  Bh=imageB.getIconHeight();
  arrayImageA=handlepixels(imageA.getImage(),0,0,Aw,Ah);
  arrayImageB=handlepixels(imageB.getImage(),0,0,Bw,Bh);
  if(arrayImageA!=null&&arrayImageB!=null){
   
   doSplice(arrayImageA,arrayImageB);   
   Image image=createImage(pixels);
   saveImage(image,outputimage);
  }
  if(fw!=null){
   try{
    fw.close();
   }catch(Exception e){
    e.printStackTrace();
   }   
  }
 }
 
 public void doSplice(int[] imageA,int[] imageB){
  pixels=imageB;
  Hmax=Bh;
  Wmax=Bw;
  int rangeFrom=Bw/4;
  int rangeTo=Bw*3/4;
     int range=Bw>>1;
      
  for(int i=rangeFrom;i<Bw;i++){
      float div=(float)(rangeTo-i)/(float)range;
      if(i>rangeTo){   //渐变范围以外,不衰减
       div=0;       
      }                
      float div1=1-div;  //渐变左边范围以外,不衰减,用imgeA填充
     
     
      for(int j=0;j<Bh;j++){
       int pixel=pixels[j*Bw+i];
       int alpha = (pixel >> 24) & 0xff; //分离imageB象素好相加
             int red   = (pixel >> 16) & 0xff;       
             int green = (pixel >>  8) & 0xff;
             int blue  = (pixel     ) & 0xff;
             
             int alpha1,red1,green1,blue1;
             pixel=imageA[j*Aw+i];  //准备分离imageA象素
             if(i>Aw||j>Ah){    //imageA 的大小不够,用白色填充
              alpha1 = 0xff;
               red1 = 0xff;
               green1= 0xff;
               blue1= 0xff;
             }else{
               alpha1 = (pixel >> 24) & 0xff;
                  red1   = (pixel >> 16) & 0xff;       
                  green1 = (pixel >>  8) & 0xff;
                  blue1  = (pixel     ) & 0xff;
             }            
             
       alpha=0xff;
       red =Math.round(red*div+red1*div1); //象素按每种颜色的衰减相加
       green =Math.round(green*div+green1*div1);
       blue =Math.round(blue*div+blue1*div1);
       
          pixels[j*Bw+i]=(alpha<<24)|(red<<16)|(green<<8)|(blue); //合成颜色  
         
   }
  } 
 }
 public void writePixel2File(int color){
     index++;
     
     if(fw==null){
      try{
     fw =new FileWriter("pixel.txt");
     }catch(Exception e){
      e.printStackTrace();
     }
     }             
        try{
         if(index%100==0)
         fw.write("\n");
         
         fw.write("\t"+color);
        }catch(Exception e){
         e.printStackTrace();
        }
    }
 
 public Image createImage(int[] colors){
     JFrame jf=new JFrame();
        Image modImg = jf.createImage(
              new MemoryImageSource(           
             Wmax,Hmax,colors,0,Wmax));
        return modImg;
    }
   
 
 public void saveImage(Image image,String filename){     
     java.awt.image.BufferedImage bi = new java.awt.image.BufferedImage(Wmax, Hmax, java.awt.image.BufferedImage.TYPE_INT_BGR);
        Graphics2D g2= (Graphics2D)bi.getGraphics();
      
        g2.drawImage(image,0,0,null);
       
        try{
         javax.imageio.ImageIO.write(bi, "JPEG", new java.io.File(filename));
        }catch(Exception e){
         e.printStackTrace();
        }       
    }
   
 public int[] handlepixels(Image img, int x, int y, int w, int h) {
        int[] pixel = new int[w * h];               
        PixelGrabber pg = new PixelGrabber(img, x, y, w, h, pixel, 0, w);
        try {
            pg.grabPixels();
        } catch (InterruptedException e) {
            System.err.println("interrupted waiting for pixels!");
           
        }
        if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
            System.err.println("image fetch aborted or errored");
        }      
        return pixel;
    }
 public static void main(String[] args){
  SpliceCount splice=new SpliceCount();
 }
}

用java实现图片渐变叠加(3种方法) - souljava - 千鸟

用java实现图片渐变叠加(3种方法) - souljava - 千鸟用java实现图片渐变叠加(3种方法) - souljava - 千鸟

/*
 *author by liuke
 *email:  soulnew@gmail.com
 *blog:  souljava.blog.163.com
 **/

package com.soulnew.Pixel;
import java.awt.image.PixelGrabber;
import java.awt.Image;
import java.awt.image.ImageObserver;
import  javax.swing.ImageIcon;
import java.io.FileWriter;
import javax.swing.JFrame;
import java.awt.image.MemoryImageSource;
import  java.awt.Graphics2D;
import java.io.File;
public class SpliceAlpha{
 int pixels[];
 int Aw,Ah,Bw,Bh;
 int Wmax,Hmax;  //the size of splice image
 int arrayImageA[],arrayImageB[];   //arrays used to save the pixels
 String imagepathA="images/try.gif"; //you can change the image path here
 String imagepathB="images/fruit1.jpg";
 String outputimage="splicealpha.jpg";
 FileWriter fw;  //used to write log
 int index=0;
 ImageIcon imageA,imageB;
 public SpliceAlpha(){
  
  imageA=new ImageIcon(imagepathA);
  imageB=new ImageIcon(imagepathB);
  
  Aw=imageA.getIconWidth();
  Ah=imageA.getIconHeight();
  Bw=imageB.getIconWidth();
  Bh=imageB.getIconHeight();
  arrayImageA=handlepixels(imageA.getImage(),0,0,Aw,Ah);
  arrayImageB=handlepixels(imageB.getImage(),0,0,Bw,Bh);
  if(arrayImageA!=null&&arrayImageB!=null){
   
   doSplice(arrayImageA,arrayImageB);   
   Image image=createImage(pixels);
   saveImage(image,outputimage);
  }
  if(fw!=null){
   try{
    fw.close();
   }catch(Exception e){
    e.printStackTrace();
   }   
  }
 }
 
 public void doSplice(int[] imageA,int[] imageB){
  pixels=imageB;
  Hmax=Bh;
  Wmax=Bw;
  int rangeFrom=Bw/4;
  int rangeTo=Bw*3/4;
     int range=Bw>>1;
      
  for(int i=rangeFrom;i<Bw;i++){
      float div=(float)(rangeTo-i)/(float)range;
      int alpha=(int)(0xff*div);
      alpha=alpha<<24;
     
      for(int j=0;j<Bh;j++){
       if(i>=rangeTo){
         pixels[j*Bw+i]=0;
           continue;
          }
      pixels[j*Bw+i]=pixels[j*Bw+i]&0xffffff;    
      pixels[j*Bw+i]=pixels[j*Bw+i]|(alpha);
     
   }
  } 
 }
 public void writePixel2File(int color){
     index++;
     
     if(fw==null){
      try{
     fw =new FileWriter("pixel.txt");
     }catch(Exception e){
      e.printStackTrace();
     }
     }             
        try{
         if(index%100==0)
         fw.write("\n");
         
         fw.write("\t"+color);
        }catch(Exception e){
         e.printStackTrace();
        }
    }
 
 public Image createImage(int[] colors){
     JFrame jf=new JFrame();
        Image modImg = jf.createImage(
              new MemoryImageSource(           
             Wmax,Hmax,colors,0,Wmax));
        return modImg;
    }
   
 
 public void saveImage(Image image,String filename){     
     java.awt.image.BufferedImage bi = new java.awt.image.BufferedImage(Wmax, Hmax, java.awt.image.BufferedImage.TYPE_INT_BGR);
        Graphics2D g2= (Graphics2D)bi.getGraphics();
        g2.drawImage(imageA.getImage(),0,0,null);
        g2.drawImage(image,0,0,null);
       
        try{
         javax.imageio.ImageIO.write(bi, "JPEG", new java.io.File(filename));
        }catch(Exception e){
         e.printStackTrace();
        }       
    }
   
 public int[] handlepixels(Image img, int x, int y, int w, int h) {
        int[] pixel = new int[w * h];               
        PixelGrabber pg = new PixelGrabber(img, x, y, w, h, pixel, 0, w);
        try {
            pg.grabPixels();
        } catch (InterruptedException e) {
            System.err.println("interrupted waiting for pixels!");
           
        }
        if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
            System.err.println("image fetch aborted or errored");
        }      
        return pixel;
    }
 public static void main(String[] args){
  SpliceAlpha splice=new SpliceAlpha();
 }
}

 

用java实现图片渐变叠加(3种方法) - souljava - 千鸟

用java实现图片渐变叠加(3种方法) - souljava - 千鸟用java实现图片渐变叠加(3种方法) - souljava - 千鸟

用象素交错填充的办法实现的图片叠加。

效果不怎么好

/*
 *author by liuke
 *email:  soulnew@gmail.com
 *blog:  souljava.blog.163.com
 **/

package com.soulnew.Pixel;
import java.awt.image.PixelGrabber;
import java.awt.Image;
import java.awt.image.ImageObserver;
import  javax.swing.ImageIcon;
import java.io.FileWriter;
import javax.swing.JFrame;
import java.awt.image.MemoryImageSource;
import  java.awt.Graphics2D;
import java.io.File;


public class Splice{
 int arrayImageA[],arrayImageB[];   //arrays used to save the pixels
 String imagepathA="images/try.gif"; //you can change the image path here
 String imagepathB="images/fruit1.jpg";
 int rangeFrom,rangeTo; //the transition range from one position to another
 int splicePixel[];
 int Aw,Ah,Bw,Bh;
 int Wmax,Hmax;  //the size of splice image
 String outputimage="splice.jpg";
 int index=0;
 FileWriter fw;
 
 
 public Splice(){
  
  ImageIcon imageA=new ImageIcon(imagepathA);
  ImageIcon imageB=new ImageIcon(imagepathB);
  
  Aw=imageA.getIconWidth();
  Ah=imageA.getIconHeight();
  Bw=imageB.getIconWidth();
  Bh=imageB.getIconHeight(); 
   
  arrayImageA=handlepixels(imageA.getImage(),0,0,Aw,Ah);
  arrayImageB=handlepixels(imageB.getImage(),0,0,Bw,Bh);
  if(arrayImageA!=null&&arrayImageB!=null){
   doSplice2(arrayImageA,arrayImageB);   
   Image image=createImage(splicePixel);
   saveImage(image,outputimage);
  }
  if(fw!=null){
   try{
    fw.close();
   }catch(Exception e){
    e.printStackTrace();
   }   
  }    
  
 }
 public Image createImage(int[] colors){
     JFrame jf=new JFrame();
        Image modImg = jf.createImage(
              new MemoryImageSource(           
             Wmax,Hmax,colors,0,Wmax));
        return modImg;
    }
   
    public void saveImage(Image image,String filename){     
     java.awt.image.BufferedImage bi = new java.awt.image.BufferedImage(Wmax, Hmax, java.awt.image.BufferedImage.TYPE_INT_BGR);
        Graphics2D g2= (Graphics2D)bi.getGraphics();
        g2.drawImage(image,0,0,null);
       
        try{
         javax.imageio.ImageIO.write(bi, "JPEG", new java.io.File(filename));
        }catch(Exception e){
         e.printStackTrace();
        }       
    }
 /*
  *the method can splice two image(array) into one image(array)
  *the the range smaller than the the image size
  *@all parameter must not to be null!!!
  *
  **/

    public void doSplice2(int[] imageA,int[] imageB){
     //first of all,you should check whether the condition fill this method
     if(Aw>Bw){
      Wmax=Aw;          
     }else{
      Wmax=Bw;
     }
     
     rangeFrom=Wmax/4;  // you can set range here
     rangeTo=Wmax*3/4;   
     if(rangeFrom>Wmax)
        return;
     if(rangeFrom>=rangeTo)
        return;  
     if(Ah>Bh){
       Hmax=Ah;
     }else{
       Hmax=Bh; 
     }
     splicePixel=new int[Wmax*Hmax];
     int range=rangeTo-rangeFrom;
     float sp=((float)Hmax/(float)range);    //step 
    
      
      
     for(int i=0;i<Wmax;i++){   //col
      
      float rownumber=sp*(rangeTo-i);
         float row=((float)Hmax)/rownumber;
            int start=(int)Math.round(Math.random()*row);
            float point=start;
      //System.out.print("\n"+row);
      for(int j=0;j<Hmax;j++){   //row       
       start=Math.round(point);
      // start=start+(int)Math.round((Math.random()-0.5)*row);
          if(start<0)
         start=0;       
                 
       if(i<rangeFrom){
        if(j>=Bh||i>=Bw){
         splicePixel[j*Wmax+i]=0xffffffff;
         continue;
        }
           splicePixel[j*Wmax+i]=imageB[j*Bw+i]; 
         continue;
       }else if(i>=rangeTo){
        if(j>=Ah||i>=Aw){
          splicePixel[j*Wmax+i]=0xffffffff;
          continue;
         }
           splicePixel[j*Wmax+i]=imageA[j*Aw+i]; 
           continue; 
       }
      // this.writePixel2File((int)Math.round((Math.random()-0.5)*row));
       if(j==start){
        
         if(j>=Ah||i>=Aw){
          splicePixel[j*Wmax+i]=0xffffffff;
          continue;
         }       
            splicePixel[j*Wmax+i]=imageB[j*Bw+i];
            point=point+row;  
       }else{       
        if(j>=Bh||i>=Bw){
          splicePixel[j*Wmax+i]=0xffffffff;
          continue;
        }
        splicePixel[j*Wmax+i]=imageA[j*Aw+i];
       }    
      }
     }
   }
  
    public void writePixel2File(int color){
     index++;
     
     if(fw==null){
      try{
     fw =new FileWriter("pixel.txt");
     }catch(Exception e){
      e.printStackTrace();
     }
     }             
        try{
         if(index%100==0)
         fw.write("\n");
         
         fw.write("\t"+color);
        }catch(Exception e){
         e.printStackTrace();
        }
    }
 public int[] handlepixels(Image img, int x, int y, int w, int h) {
        int[] pixels = new int[w * h];               
        PixelGrabber pg = new PixelGrabber(img, x, y, w, h, pixels, 0, w);
        try {
            pg.grabPixels();
        } catch (InterruptedException e) {
            System.err.println("interrupted waiting for pixels!");
           
        }
        if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
            System.err.println("image fetch aborted or errored");
        }      
        return pixels;
    }
 public static void main(String[] args){
  Splice splice=new Splice();
 }
}

  评论这张
 
阅读(3852)| 评论(2)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017