Jcrop & Canvas:裁剪区域的大小很奇怪 & 500 内部服务器错误
Jcrop & Canvas: Size of cropped area is weird & 500 Internal Server Error
简介
流程
所以,我正在制作一个 Web 应用程序,用户应该可以在其中上传图像并进行裁剪:
- 用户选择本地图片
- 从图像
创建了一个对象url
- 对象 url 是
<img>
的来源
- Jcrop应用于此
<img>
- 选中的裁剪区域被绘制成canvas
- 从这个canvas
创建了一个数据url
- 此数据url被写入存储在服务器上的文件
问题
- 存储在canvas中的裁剪区域的大小是原始图像
的数倍
- 当我最终尝试将解码数据 url 写入文件时,出现 500 内部服务器错误
代码
注:代码已简化
event_handlers.js
jQuery('#my_upload_input').change(function(my_event)
{
my_load_image(my_event.currentTarget.files);
});
jQuery(document).keyup(function(my_event)
{
if (my_event.which == 13)
{
my_crop_image();
}
});
image_handling.js
var my_file_glob;
var my_image_glob;
var my_jcrop_api_glob;
function my_load_image(my_files)
{
var my_file_glob = my_files[0];
var my_image_glob = new Image();
my_image_glob.onload = function()
{
my_show_image();
};
my_image_glob.src = URL.createObjectURL(my_file_glob);
}
function my_show_image()
{
jQuery('#my_container').html('<img id="my_img" src="' + my_image_glob.src + '" />');
jQuery('#my_img').Jcrop(
{
boxWidth: 1280,
boxHeight: 720,
trueSize: [my_image_glob.width, my_image_glob.height],
setSelect: [0, 0, 1920, 1080],
aspectRatio: 1920 / 1080,
minSize: [1920, 1080],
bgColor: '',
allowSelect: false
}, function()
{
my_jcrop_api_glob = this;
});
}
function my_crop_image()
{
if (typeof my_jcrop_api_glob !== 'undefined')
{
var my_selection = my_jcrop_api_glob.tellSelect();
var my_canvas = document.createElement('canvas');
var my_canvas_context = my_canvas.getContext('2d');
my_canvas.width = my_selection.w;
my_canvas.height = my_selection.h;
my_canvas_context.drawImage(my_image_glob, my_selection.x, my_selection.y, my_selection.w, my_selection.h, 0, 0, my_selection.w, my_selection.h);
my_upload_canvas(my_canvas);
}
}
function my_upload_canvas(my_canvas)
{
var my_canvas_url = my_canvas.toDataURL('image/png');
jQuery.ajax(
{
type: 'POST',
url: 'ajax_calls.php',
data:
{
my_canvas_url: my_canvas_url
},
success: function(my_response)
{
alert(my_response);
window.location.reload(true);
}
});
}
ajax_calls.js
if(isset($_POST['my_canvas_url']))
{
$my_canvas_url = $_POST['my_canvas_url'];
my_upload_canvas($my_canvas_url);
}
function my_upload_canvas($my_canvas_url)
{
$my_canvas_data_enc = explode(',', $my_canvas_url)[1];
$my_canvas_data_enc = str_replace(' ', '+', $my_canvas_data_enc);
$my_canvas_data_dec = base64_decode($my_canvas_data_enc);
file_put_contents(dirname(__FILE__) . '/menu.png', $my_canvas_data_dec);
if($my_png_created !== false)
{
echo 'success';
}
else
{
echo 'failure';
}
}
额外
在函数my_upload_canvas(my_canvas)
中,我写了这几行来比较原始图像和裁剪区域的大小:
var head = 'data:image/png;base64,';
var imgfilesize = Math.round((my_canvas_url.length - head.length) * 3 / 4);
console.log('size orig: ' + Math.round(my_file_glob.size));
console.log('size crop: ' + Math.round(imgfilesize));
console.log('cropped area is ' + Math.round(imgfilesize / my_file_glob.size) + ' times bigger than the original image');
三个不同图像的输出如下:
JPEG (807 KB)
size orig: 826730
size crop: 2445081
cropped area is 3 times bigger than the original image
JPG (141 KB)
size orig: 144837
size crop: 1201146
cropped area is 8 times bigger than the original image
PNG (334 KB)
size orig: 342617
size crop: 53799
cropped area is 0 times bigger than the original image
请注意,图像 #1 和 #2 的裁剪区域尺寸大于原始图像本身的尺寸,但图像 #3 不是。
更新 #1
500 内部服务器错误 是由函数 plugins_url()
前面的 $
引起的...愚蠢的我。但是,不幸的是,保存 .png 仍然不起作用(我什至无法创建文件)。介绍和代码已更新。
更新#2
现在可以上传图片了!我替换了
file_put_contents(plugins_url('/menu.png', __FILE__), $my_canvas_data_dec)
与
file_put_contents(dirname(__FILE__) . '/menu.png', $my_canvas_data_dec)
显然 URL 行不通,但完整路径行得通。介绍和代码已更新。
更新#3
谜底揭晓!如您所见 here,canvas 只包含图像像素的信息。因此,数据的大小 url 取决于浏览器如何对这些像素进行编码,并可能导致比图像更大。此外,在大多数情况下,PNG 比相同 canvas.
的 JPEG 大得多
我自己想出来了。如果您对答案感兴趣,请查看我的 post 的更新。
简介
流程
所以,我正在制作一个 Web 应用程序,用户应该可以在其中上传图像并进行裁剪:
- 用户选择本地图片
- 从图像 创建了一个对象url
- 对象 url 是
<img>
的来源
- Jcrop应用于此
<img>
- 选中的裁剪区域被绘制成canvas
- 从这个canvas 创建了一个数据url
- 此数据url被写入存储在服务器上的文件
问题
- 存储在canvas中的裁剪区域的大小是原始图像 的数倍
- 当我最终尝试将解码数据 url 写入文件时,出现 500 内部服务器错误
代码
注:代码已简化
event_handlers.js
jQuery('#my_upload_input').change(function(my_event)
{
my_load_image(my_event.currentTarget.files);
});
jQuery(document).keyup(function(my_event)
{
if (my_event.which == 13)
{
my_crop_image();
}
});
image_handling.js
var my_file_glob;
var my_image_glob;
var my_jcrop_api_glob;
function my_load_image(my_files)
{
var my_file_glob = my_files[0];
var my_image_glob = new Image();
my_image_glob.onload = function()
{
my_show_image();
};
my_image_glob.src = URL.createObjectURL(my_file_glob);
}
function my_show_image()
{
jQuery('#my_container').html('<img id="my_img" src="' + my_image_glob.src + '" />');
jQuery('#my_img').Jcrop(
{
boxWidth: 1280,
boxHeight: 720,
trueSize: [my_image_glob.width, my_image_glob.height],
setSelect: [0, 0, 1920, 1080],
aspectRatio: 1920 / 1080,
minSize: [1920, 1080],
bgColor: '',
allowSelect: false
}, function()
{
my_jcrop_api_glob = this;
});
}
function my_crop_image()
{
if (typeof my_jcrop_api_glob !== 'undefined')
{
var my_selection = my_jcrop_api_glob.tellSelect();
var my_canvas = document.createElement('canvas');
var my_canvas_context = my_canvas.getContext('2d');
my_canvas.width = my_selection.w;
my_canvas.height = my_selection.h;
my_canvas_context.drawImage(my_image_glob, my_selection.x, my_selection.y, my_selection.w, my_selection.h, 0, 0, my_selection.w, my_selection.h);
my_upload_canvas(my_canvas);
}
}
function my_upload_canvas(my_canvas)
{
var my_canvas_url = my_canvas.toDataURL('image/png');
jQuery.ajax(
{
type: 'POST',
url: 'ajax_calls.php',
data:
{
my_canvas_url: my_canvas_url
},
success: function(my_response)
{
alert(my_response);
window.location.reload(true);
}
});
}
ajax_calls.js
if(isset($_POST['my_canvas_url']))
{
$my_canvas_url = $_POST['my_canvas_url'];
my_upload_canvas($my_canvas_url);
}
function my_upload_canvas($my_canvas_url)
{
$my_canvas_data_enc = explode(',', $my_canvas_url)[1];
$my_canvas_data_enc = str_replace(' ', '+', $my_canvas_data_enc);
$my_canvas_data_dec = base64_decode($my_canvas_data_enc);
file_put_contents(dirname(__FILE__) . '/menu.png', $my_canvas_data_dec);
if($my_png_created !== false)
{
echo 'success';
}
else
{
echo 'failure';
}
}
额外
在函数my_upload_canvas(my_canvas)
中,我写了这几行来比较原始图像和裁剪区域的大小:
var head = 'data:image/png;base64,';
var imgfilesize = Math.round((my_canvas_url.length - head.length) * 3 / 4);
console.log('size orig: ' + Math.round(my_file_glob.size));
console.log('size crop: ' + Math.round(imgfilesize));
console.log('cropped area is ' + Math.round(imgfilesize / my_file_glob.size) + ' times bigger than the original image');
三个不同图像的输出如下:
JPEG (807 KB)
size orig: 826730
size crop: 2445081
cropped area is 3 times bigger than the original image
JPG (141 KB)
size orig: 144837
size crop: 1201146
cropped area is 8 times bigger than the original image
PNG (334 KB)
size orig: 342617
size crop: 53799
cropped area is 0 times bigger than the original image
请注意,图像 #1 和 #2 的裁剪区域尺寸大于原始图像本身的尺寸,但图像 #3 不是。
更新 #1
500 内部服务器错误 是由函数 plugins_url()
前面的 $
引起的...愚蠢的我。但是,不幸的是,保存 .png 仍然不起作用(我什至无法创建文件)。介绍和代码已更新。
更新#2
现在可以上传图片了!我替换了
file_put_contents(plugins_url('/menu.png', __FILE__), $my_canvas_data_dec)
与
file_put_contents(dirname(__FILE__) . '/menu.png', $my_canvas_data_dec)
显然 URL 行不通,但完整路径行得通。介绍和代码已更新。
更新#3
谜底揭晓!如您所见 here,canvas 只包含图像像素的信息。因此,数据的大小 url 取决于浏览器如何对这些像素进行编码,并可能导致比图像更大。此外,在大多数情况下,PNG 比相同 canvas.
的 JPEG 大得多我自己想出来了。如果您对答案感兴趣,请查看我的 post 的更新。