`
Hooopo
  • 浏览: 327863 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

基于jquery和mini_magick的图片裁剪

阅读更多
jquery imgAeraSelect插件地址:http://odyniec.net/projects/imgareaselect/
原理很简单,就是将鼠标框住的区域两个定点坐标值传回服务器端,在服务器端用image magick处理。
由于rmagick存在内存泄露问题。这里选择了mini_magick。mini_magick是一个非常小的库,源代码不过300行。主要是通过调用系统命令行来处理图片。只要系统安装了image magick就可以。

view:主要是加四个隐藏域来传递裁剪区域。在form提交时候一起传递到服务器。
<input id="x1" type="hidden" value="0" name="x1"/>
        <input id="y1" type="hidden" value="0" name="y1"/>
        <input id="x2" type="hidden" value="150" name="x2"/>
        <input id="y2" type="hidden" value="150" name="y2"/>

初始化裁剪框在待处理图片的中央和一些验证:


<script type="text/javascript">
    $(document).ready(function(){
      var pos = initValue();


      $('#avatar').imgAreaSelect({aspectRatio: '1:1',
        x1: pos.x1,
        y1: pos.y1,
        x2: pos.x2,
        y2: pos.y2,
        handles: true,
       
        onSelectEnd: function (img, selection) {
          $('input[name=x1]').val(selection.x1);
          $('input[name=y1]').val(selection.y1);
          $('input[name=x2]').val(selection.x2);
          $('input[name=y2]').val(selection.y2);
        }
      });
    });

    function initValue(){
      var o    = new Object();
      var x    = $("#avatar").width();
      var y    = $("#avatar").height();
      var size = x >= y ? y : x;
      size     = size >= 100 ? 100 : size;
      o.x1 = (x - size) / 2;
      o.y1 = (y - size) / 2;
      o.x2 = o.x1 + size;
      o.y2 = o.y1 + size;
      return o;
    }



    function checkImage(){
      var image_name = $("#photo").val();
      var reg = /\.png|jpeg|jpg|bmp|gif$/i
      if (reg.test(image_name)){
        return true;
      }else if(image_name == "") {
        alert("没有选择图片!");
        return false;
      }else{
        alert("图片格式不正确!");
        return false;
      }
    }
    
  </script>


后台处理,主要就是做以下几件事情:
1.把上传来的照片压缩到200x200
2.通过content-type判断图片是否合法。以防用户自己改扩展名。
3.把gif和png格式转换成jpg,不然在裁剪时候后出问题。
4.裁剪
5.把裁剪后图片缩放成几种比例

def upload_avatar
    if request.post?
      avatar_200_200 = RAILS_ROOT + "/public/files/avatar/200_200/"
      photo_name     = "#{current_user.hash_id}.jpg"
      
      avatar_100_100 = RAILS_ROOT + "/public/files/avatar/100_100/"
      avatar_64_64   = RAILS_ROOT + "/public/files/avatar/64_64/"
      avatar_50_50   = RAILS_ROOT + "/public/files/avatar/50_50/"
      avatar_40_40   = RAILS_ROOT + "/public/files/avatar/40_40/"


      if params[:commit] == "上传照片"
        #TODO Validate Image Size!
        #TODO 增加白色背景,以防不规则图片!
        
        photo = params[:photo]
        
        raise "image type Error!" if photo.content_type !~ /^image\/.*?jpeg|jpg|png|bmp|gif$/i
        Dir.chdir avatar_200_200

        img  = MiniMagick::Image.from_blob(photo.read)
        img.format("jpg") if photo.content_type =~ /gif|png$/i
        
        img.resize "200x200"
        img.write photo_name

        redirect_to request.referer
      elsif params[:commit] == "保存设置"
        
        
        Dir.chdir avatar_200_200
        if File.exist?(photo_name)
          width = params[:x2].to_i - params[:x1].to_i
          height= params[:y2].to_i - params[:y1].to_i

          img = MiniMagick::Image.open(photo_name)
          
          img.crop "#{width}x#{height}+#{params[:x1]}+#{params[:y1]}"
        
          img.resize 100 and Dir.chdir avatar_100_100 and img.write photo_name
          img.resize 64  and Dir.chdir avatar_64_64   and img.write photo_name
          img.resize 50  and Dir.chdir avatar_50_50   and img.write photo_name
          img.resize 40  and Dir.chdir avatar_40_40   and img.write photo_name
        end
      end
    end
  end



效果预览:


分享到:
评论
26 楼 hexawing 2010-06-22  
kamama 写道
请问有用mini_magick在图片上画中文字的么?
如在照片上,写上“你好”,“你好Hooopo”

我发现纯中文字是可以的,一旦字符串中夹杂数字或者字母就整个字符串打出来是乱码

纯中文也不一定可以吧,我目前发现“路”字,怎么写都是乱码……这可是常用字呢
25 楼 guodong66 2010-06-11  
不错哦, 支持。
24 楼 llfzy 2010-05-15  
这功能不错。。。。我正需要
23 楼 rocheers 2010-04-07  
我把<%=debug(@photo) %>加进表单里,不过打印出来的都是空……
<% form_for :picture, @picture, :url => {:action => 'create'}, :html => {:multipart => true} do |f| %>
  <p>
    <%= f.file_field :uploaded_data %>
  </p>
  <p>
    <%= submit_tag 'Create' %>
  </p>
<% end %>

这是我上传图片的表单

def new
  @picture = Picture.new
  respond_to do |format|
    format.html # new.html.erb
    format.xml  { render :xml => @picture }
  end
end

def create
  @picture = Picture.new(params[:picture])
  pic = params[:picture]
  img = MiniMagick::Image.from_blob(pic.read)
  respond_to do |format|
    if @picture.save
      flash[:notice] = 'Picture was successfully created.'
      format.html { redirect_to(@picture) }
      format.xml  { render :xml => @picture, :status => :created, :location => @picture }
    else
      format.html { render :action => "new" }
      format.xml  { render :xml => @picture.errors, :status => :unprocessable_entity }
    end
  end
end

上面是我的controller里的跟上传图片有关的部分

之前看过你的回答后,我又修改了修改,但是无论怎么改都是不行,所以还是把原码给贴过来吧……
我把pic = params[:picture]换成pic = params[:picture][:uploaded_data]后pic的类型是Tempfile了,倒是可以用read了,但是还是报错,说pic里为空……不清楚是为什么……

我现在做的就是一个关于上传图片自动修改的项目,我的目的就是想让我上传的所有图片都按原比例变成一个分辨率,比如500x500,然后上下或左右加白边,加白边我看你之前给一个人的回答里有了,我试过了也可以。现在就是上传图片这块,实在是搞不懂……麻烦楼主帮忙解答一下~十分感谢~~!
22 楼 Hooopo 2010-04-07  
rocheers 写道
你好,我想请问一下,为什么我的程序总是在 img  = MiniMagick::Image.from_blob(photo.read) 这句报错呢?错误是undefined methods “read”,我查了一下photo的class,是个很奇怪的类——HashWithIndifferentAccess,貌似这个类里没有read的方法?不解……等待楼主的帮助~万分感激~

你的表单是什么样子的?photo的class是HashWithIndifferentAccess说明你得到的不是File对象,没有read方法....

你把photo对象详细的打印出来就知道了。

<%=debug(@photo) %>
21 楼 rocheers 2010-04-07  
你好,我想请问一下,为什么我的程序总是在 img  = MiniMagick::Image.from_blob(photo.read) 这句报错呢?错误是undefined methods “read”,我查了一下photo的class,是个很奇怪的类——HashWithIndifferentAccess,貌似这个类里没有read的方法?不解……等待楼主的帮助~万分感激~
20 楼 Hooopo 2010-01-14  
kamama 写道
请问有用mini_magick在图片上画中文字的么?
如在照片上,写上“你好”,“你好Hooopo”

我发现纯中文字是可以的,一旦字符串中夹杂数字或者字母就整个字符串打出来是乱码

加文字没试过,但是如果有乱码可以先用Photoshop制作一个小图片用imagMagick的composite命令贴上去
19 楼 kamama 2010-01-14  
请问有用mini_magick在图片上画中文字的么?
如在照片上,写上“你好”,“你好Hooopo”

我发现纯中文字是可以的,一旦字符串中夹杂数字或者字母就整个字符串打出来是乱码
18 楼 Hooopo 2010-01-14  
<div class="quote_title">ywencn 写道</div>
<div class="quote_div">
<pre name="code" class="js"> function initValue(){ 
       var o    = new Object();        
       var x    = $("#avatar").width(); 
      var y    = $("#avatar").height(); 
      var size = x &gt;= y ? y : x; 
      size     = size &gt;= 100 ? 100 : size; 
      o.x1 = (x - size) / 2; 
      o.y1 = (y - size) / 2; 
      o.x2 = o.x1 + size; 
       o.y2 = o.y1 + size; 
      return o;  </pre>
<p> </p>
<p>我发现如果图片加载比较慢的话就不能正确获取.width()和.height</p>
<p>因为jquery在DOM加载完毕后就开始执行,可能获取width的时候图片才加载了一点点,就导致了默认的选取框只有一个点。</p>
<p>这个有解决的办法么?</p>
</div>
<p>这是和浏览器有关,ie下可以获取。其他浏览器有问题。。</p>
<p>有两种解决方案:</p>
<p>1.服务器端传回一个图片长宽的值放在页面隐藏域,js读取隐藏域来获取图片宽高。</p>
<p>2.在服务器端把图片不足200x200的添加白边到200x200(回复里已经有做法),然后初始化选择框的时候就可以指定一个定值。</p>
17 楼 danielking 2010-01-14  
<div class="quote_title">ywencn 写道</div>
<div class="quote_div">
<pre name="code" class="js"> function initValue(){ 
       var o    = new Object();        
       var x    = $("#avatar").width(); 
      var y    = $("#avatar").height(); 
      var size = x &gt;= y ? y : x; 
      size     = size &gt;= 100 ? 100 : size; 
      o.x1 = (x - size) / 2; 
      o.y1 = (y - size) / 2; 
      o.x2 = o.x1 + size; 
       o.y2 = o.y1 + size; 
      return o;  </pre>
<p> </p>
<p>我发现如果图片加载比较慢的话就不能正确获取.width()和.height</p>
<p>因为jquery在DOM加载完毕后就开始执行,可能获取width的时候图片才加载了一点点,就导致了默认的选取框只有一个点。</p>
<p>这个有解决的办法么?</p>
</div>
<p> </p>
<p>图片load完之后再执行不就行了?</p>
16 楼 ywencn 2010-01-13  
<pre name="code" class="js"> function initValue(){ 
       var o    = new Object();        
       var x    = $("#avatar").width(); 
      var y    = $("#avatar").height(); 
      var size = x &gt;= y ? y : x; 
      size     = size &gt;= 100 ? 100 : size; 
      o.x1 = (x - size) / 2; 
      o.y1 = (y - size) / 2; 
      o.x2 = o.x1 + size; 
       o.y2 = o.y1 + size; 
      return o;  </pre>
<p> </p>
<p>我发现如果图片加载比较慢的话就不能正确获取.width()和.height</p>
<p>因为jquery在DOM加载完毕后就开始执行,可能获取width的时候图片才加载了一点点,就导致了默认的选取框只有一个点。</p>
<p>这个有解决的办法么?</p>
15 楼 寄生虫 2009-12-15  
不错啊,要是能在前台用JS剪裁就好了,YY一下
14 楼 zhonggeneral 2009-12-15  
服务端技术,没什么看头。
13 楼 changyuxin 2009-12-11  
挺不错的,收藏夹了!
12 楼 wujiazhao88 2009-12-10  
写得不错啊,顶一个
11 楼 fl1429 2009-12-09  
以前 我用 jquery imageselectarea.js + rmagick 同样实现了该功能。。原理一样
10 楼 freedomstyle 2009-12-09  
   听不错的哦,谢谢楼主分享
9 楼 kukuwuwu 2009-12-09  
我一直以为楼主头像是一只手拿着一个发光物体呢,今天看到真相了哈哈
8 楼 gokure 2009-12-07  
太帅了,就是这个效果.
7 楼 swen00 2009-12-07  
能做成个组件么?像那个上传多个文件一样。

收藏下先..

相关推荐

Global site tag (gtag.js) - Google Analytics