happypeter / onestep

haoqicat.com 代码
http://haoqicat.com
171 stars 90 forks source link

头像上传png格式的透明背景处理 #485

Closed luckyyang closed 10 years ago

luckyyang commented 10 years ago

目前会处理成黑色,应该是白色才对

luckyyang commented 10 years ago

让我再梳理一下这个步骤:

  1. 上传一个带透明背景的png图片
  2. 显示预览和裁剪modal,这个时候img的src被转化成了data url: twitter的完美方案:
    image 我的方案: image 这里的区别是img后面的 MIME type 不同,twitter给改成了jpeg(为什么啊),我的是和原始图片一致的png。但我认为这个不是关键,后面的实际的数据才关键,两者的数据是一样的。
  3. 确认裁剪,图片的透明背景显示为白色(而我的方案是黑色) 这个步骤是经过后端来做的,我应该在这里再看看
luckyyang commented 10 years ago

http://pastebin.com/ZQJRr3Bc https://github.com/carrierwaveuploader/carrierwave/wiki/How-to%3A-Upload-from-a-string-in-Rails-3

billie66 commented 10 years ago

恭喜,问题解决了。期待做成课程,讲解一下

luckyyang commented 10 years ago

没有,这个问题间歇性的不行,一会又行。该死的,我再看看

luckyyang commented 10 years ago

今天我先饶了它

luckyyang commented 10 years ago

http://www.script-tutorials.com/html5-image-uploader-with-jcrop/

从他的Live Demo上得到的结果也是不理想,png的透明背景也变成了黑色

algo31031 commented 10 years ago

@luckyyang 在carrierwave的rdoc里找到了个resize_and_pad, 里面可以传background的参数 用这个替换掉了之前uploader里的resize_to_fit 另外稍微转变了下思路, 把crop()里的manipulate!一行加了format: "png"参数,变成manipulate! format: "png" do |img| 如此一来要是低分辨率的图的话直接裁, 就保留png透明底色的特性 这么改完之后, 目前在本地跑看起来是ok的

luckyyang commented 10 years ago

哇 太酷了! @algo31031

format: "png" 是强制把图片格式变成png的么?如果原始图片是jpg也会被转换成png么?

luckyyang commented 10 years ago

还有,我在 https://github.com/happypeter/onestep/blob/master/config/initializers/stringiohax.rb#L11 制定的png格式没起作用么?

对carrivewave有些东西还是不理解

algo31031 commented 10 years ago

@luckyyang 非常之不幸...刚才又试了下resize_and_pad()如果传的图片非正方形, 截出来的图外面会有白边 上午用的2个png都是方的所以没发现这问题 感觉还是要从输出图片的格式下手, 找找看怎么能把图保留为png 从现在结果看似乎resize_to_fit这一步时候已经格式变了

algo31031 commented 10 years ago

在uploader里重写了resize_to_fit()方法加format可以奏效, 但是总觉得有点不舒服 /config/initializers/stringiohax.rb没作用会不会跟original_filename()用了jpeg有关

algo31031 commented 10 years ago

看来是了, 把CarrierStringIO#original_filename返回值改成了"photo.png" 截完之后输出的图片扩展名和mimetype也能对上了, 透明底的依然保留透明

luckyyang commented 10 years ago

我也试一下,按理说original_filename()用了jpeg 应该对图片格式没影响啊

algo31031 commented 10 years ago

我推测是用了jpeg之后, 输出的图片就被存做JPEG格式了, 但是存完之后加了个错误的png的mimetype 具体如何恐怕要看源码了

luckyyang commented 10 years ago

看来真是和这个original_filename() 有关,这么简单,浪费了我不少时间。迷惑的地方还有一点就是,每次改完original_filename() ,都要重启一下apache或者touch tmp/restart.txt,才能保证修改后完全生效。不然都不知道问题在哪里。

luckyyang commented 10 years ago

非常之不幸...刚才又试了下resize_and_pad()如果传的图片非正方形, 截出来的图外面会有白边

之前的这个方法有白边?我怎么没发现呢,我用一大一小两个图片都试了,没问题啊。而且我的裁剪选择框默认就是正方形,和上传的图片是不是正方形没关系吧

luckyyang commented 10 years ago

resize_and_pad()和original_filename()这两种方法都是把图片转换成png格式,能不能不转换也可以呢?original_filename()里用正则表达式是不是就可以,可以试试

algo31031 commented 10 years ago

之前代码里用的resize_to_fit()应该是没白边的, 后来我改成了resize_and_pad(), 不是方形的图就会有问题, 刚才的提交已经改回原先的resize_to_fit()

luckyyang commented 10 years ago

我用resize_and_pad()试了下,没有白边啊。因为我裁剪的选择框是无法选择图片以外的区域的啊。

你能截个图么?是不是我理解的有偏差。

resize_and_pad(width, height, background=:transparent, gravity=::Magick::CenterGravity) Resize the image to fit within the specified dimensions while retaining the original aspect ratio. If necessary, will pad the remaining area with the given color, which defaults to transparent (for gif and png, white for jpeg).

你说的白边就是这个文档里说的填充(pad)颜色?

algo31031 commented 10 years ago

选择了一张非正方形图, 截成正方形 0 使用resize_and_pad(), 产生白边 1 改回resize_to_fit(), OK 2

luckyyang commented 10 years ago

png也会有,我开始没注意到,是因为一直用带透明背景的png测试的。。。 蛮帅的嘛!

algo31031 commented 10 years ago

婚纱照里的一张, 这辈子就指着靠这一张照片混了...

luckyyang commented 10 years ago

哈哈。

白边的原因肯定是因为crop之前获得的图片的长度和宽度值不对。这可能也是我当初为什么选择resize_to_fit了,因为文件的原始尺寸信息没变化?

是不是resize_and_pad() 把图片给处理了所以尺寸信息变了,最后crop出来的效果就不对了?

luckyyang commented 10 years ago

哦哦,明白了,resize_and_pad() 也没有改变文件的尺寸信息,只是把其余的部分给填充了,用白色,所以裁剪出来才是那个样子。如果你用宽度大于高度的去测,那就是上边会有白边。

我真是个天才!