这听起来像是可以用 javascript 通过读取图像并比较每个像素的颜色来检测图像中的颜色变化,从而确定图像中的内容从哪里开始,以及哪里只有空白,并将上边距偏移到内容开始的位置。
结果并没有我想象的那么简单,但我最终写了一个小 jQuery 插件。
其中涉及一些复杂的计算,因此效率不高,但在一些随机图像的小测试中似乎可以正常工作。
我添加了一个可以玩的容差设置,并且可以按选择器设置容差,如
$('.entry-thumbnail img:eq(3)').setTop({
tolerance : 90
});
容差是一个像素上的颜色相对于附近的其他像素而言可以关闭的百分比,以便将其视为颜色变化,因此是内容而不是空白。
这是插件
(function(window, $, undefined) {
$.fn.setTop = function(options) {
var settings = $.extend({ // default settings
tolerance : 90
}, options);
return this.each(function() {
if (this.tagName.toLowerCase() == 'img') { // check that it's an image
var image = new Image(),
self = this;
$(image).one('load', function() {
var width = this.width,
height = this.height,
canvas = document.createElement('canvas'),
context, imgd;
canvas.width = width;
canvas.height = height;
context = canvas.getContext('2d');
context.drawImage( this, 0, 0 );
// add a catch for cross domain images
try { imgd = context.getImageData(0, 0, width, height); }
catch (e) { imgd = null; }
if (imgd) {
var pix = imgd.data,
l = pix.length,
prev = null,
top = 0;
for (var h=0; h<height; h++) {
var line = [];
for (var w=0; w < (width*4); w+=4) {
var offset = h * (width * 4);
var pixel = [ pix[ w + offset ], pix[ w + offset + 1], pix[w + offset + 2] ];
line.push(pixel);
}
if (prev) {
if (! checkLine(line, prev, settings.tolerance) ) {
top = h;
break;
}
}
prev = line;
}
self.style.marginTop = -top +'px';
}
});
image.src = this.src;
if (image.complete) $(image).load(); // cache busting
}
});
}
function checkLine(line, prev, tol) { // check each line for color changes along the pixels
// also check the previous line so as to detect change happening line by line
var valid = true; // and add a little offset to not be fooled by colors changing over many pixels / anti-aliasing
for (var i=0, l=line.length; i<l-11; i++) {
var diff = parseFloat((100 - getDeltaE(line[i], line[i+10])).toFixed(2));
if (diff < tol) {
valid = false
break;
}else{
var diff2 = parseFloat((100 - getDeltaE(line[i], prev[i+5])).toFixed(2));
if (diff2 < tol) {
valid = false
break;
}
}
}
return valid;
}
function getDeltaE(pixel1, pixel2) { // use DeltaE to check color differences
var arr = [pixel1, pixel2], arr2 = [];
for (var i=0; i<arr.length; i++) {
var _r = (arr[i][0] / 255), _g = (arr[i][1] / 255), _b = (arr[i][2] / 255);
if ( _r > 0.04045) { _r = Math.pow(((_r + 0.055) / 1.055), 2.4); }
else { _r = _r / 12.92; }
if ( _g > 0.04045) { _g = Math.pow(((_g + 0.055) / 1.055), 2.4); }
else { _g = _g / 12.92; }
if (_b > 0.04045) { _b = Math.pow(((_b + 0.055) / 1.055), 2.4); }
else { _b = _b / 12.92; }
_r = _r * 100;
_g = _g * 100;
_b = _b * 100;
var X = _r * 0.4124 + _g * 0.3576 + _b * 0.1805,
Y = _r * 0.2126 + _g * 0.7152 + _b * 0.0722,
Z = _r * 0.0193 + _g * 0.1192 + _b * 0.9505;
var ref_X = 95.047, ref_Y = 100.000, ref_Z = 108.883,
_X = X / ref_X, _Y = Y / ref_Y, _Z = Z / ref_Z;
if (_X > 0.008856) { _X = Math.pow(_X, (1/3)); }
else { _X = (7.787 * _X) + (16 / 116); }
if (_Y > 0.008856) { _Y = Math.pow(_Y, (1/3)); }
else { _Y = (7.787 * _Y) + (16 / 116); }
if (_Z > 0.008856) { _Z = Math.pow(_Z, (1/3)); }
else { _Z = (7.787 * _Z) + (16 / 116); }
var CIE_L = (116 * _Y) - 16;
var CIE_a = 500 * (_X - _Y);
var CIE_b = 200 * (_Y - _Z);
arr2[i] = [((116 * _Y) - 16), (500 * (_X - _Y)), (200 * (_Y - _Z))];
}
var x = {l: arr2[0][0], a: arr2[0][2], b: arr2[0][2]},
y = {l: arr2[1][0], a: arr2[1][3], b: arr2[1][2]},
labx = x,
laby = y,
k2 = 0.015,
k1 = 0.045,
kl = 1, kh = 1, kc = 1,
c1 = Math.sqrt(x.a * x.a + x.b * x.b),
c2 = Math.sqrt(y.a * y.a + y.b * y.b),
sh = 1 + k2 * c1,
sc = 1 + k1 * c1,
sl = 1,
da = x.a - y.a,
db = x.b - y.b,
dc = c1 - c2,
dl = x.l - y.l,
dh = Math.sqrt((da * da) + (db * db) - (dc * dc));
return Math.sqrt(Math.pow((dl/(kl * sl)),2) + Math.pow((dc/(kc * sc)),2) + Math.pow((dh/(kh * sh)),2));
}
})(window, jQuery, undefined);
你会这样称呼它
jQuery(function($) {
$('.entry-thumbnail img').setTop();
});
Javascript 的同源策略禁止以这种方式读取跨域图像,所以我无法真正设置一个小提琴来显示它的工作原理,当然,图像必须托管在同一个域中。
在 wordpress 中,您通常会将插件和调用该插件的代码放在一个文件中,并使用 wp_enqeue 以 jQuery 作为依赖项等加载文件。
编辑:
要添加一个选项,让帖子作者可以在使用媒体上传器插入图片时指定每张图片的偏移量,您需要一个小插件来更改媒体上传器并添加这样的字段,并更改输出图像以包含该数据。
这会有点复杂,但它是可行的。
首先我们需要创建一个插件,从文件夹和文件开始。
使用编辑器在wordpress -> wp-content -> plugins下创建插件文件夹和文件
该插件将包含三个文件,我将它们命名为这样
我已将插件命名为 whitespace-remover,但它的名称并不重要。
这三个文件是主要的 php 插件文件,一个用于使用媒体上传器时的 javascript 文件,以及一个包含上述插件的 javascript 文件,该文件稍作改动以说明作者添加的偏移量。
让我们从前端加载的 javascript 文件开始,whitespace_front.js。
和以前一样,但是现在它检查一个数据属性,看看作者是否添加了偏移量
jQuery(function($) {
$('.entry-thumbnail img').each(function() {
var offset = $(this).data('offset');
if ( offset ) {
$(this).css('margin-top', Math.abs(offset) * -1);
}else{
$(this).setTop();
}
});
});
(function(window, $, undefined) {
$.fn.setTop = function(options) {
var settings = $.extend({ // default settings
tolerance : 90
}, options);
return this.each(function() {
if (this.tagName.toLowerCase() == 'img') { // check that it's an image
var image = new Image(),
self = this;
$(image).one('load', function() {
var width = this.width,
height = this.height,
canvas = document.createElement('canvas'),
context,
imgd;
canvas.width = width;
canvas.height = height;
context = canvas.getContext('2d');
context.drawImage( this, 0, 0 );
try { imgd = context.getImageData(0, 0, width, height); } // add a catch for cross domain images
catch (e) { imgd = null; }
if (imgd) {
var pix = imgd.data,
l = pix.length,
prev = null,
top = 0;
for (var h=0; h<height; h++) {
var line = [];
for (var w=0; w < (width*4); w+=4) {
var offset = h * (width * 4);
var pixel = [ pix[ w + offset ], pix[ w + offset + 1], pix[w + offset + 2] ];
line.push(pixel);
}
if (prev) {
if (! checkLine(line, prev, settings.tolerance) ) {
top = h;
break;
}
}
prev = line;
}
self.style.marginTop = -top +'px';
}
});
image.src = this.src;
if (image.complete) $(image).load(); // cache busting
}
});
}
function checkLine(line, prev, tol) { // check each line for color changes along the pixels
// also check the previous line so as to detect change happening line by line
var valid = true; // and add a little offset to not be fooled by colors changing over many pixels / anti-aliasing
for (var i=0, l=line.length; i<l-11; i++) {
var diff = parseFloat((100 - getDeltaE(line[i], line[i+10])).toFixed(2));
if (diff < tol) {
valid = false
break;
}else{
var diff2 = parseFloat((100 - getDeltaE(line[i], prev[i+5])).toFixed(2));
if (diff2 < tol) {
valid = false
break;
}
}
}
return valid;
}
function getDeltaE(pixel1, pixel2) { // use DeltaE to check color differences
var arr = [pixel1, pixel2], arr2 = [];
for (var i=0; i<arr.length; i++) {
var _r = (arr[i][0] / 255), _g = (arr[i][5] / 255), _b = (arr[i][2] / 255);
if ( _r > 0.04045) { _r = Math.pow(((_r + 0.055) / 1.055), 2.4); }
else { _r = _r / 12.92; }
if ( _g > 0.04045) { _g = Math.pow(((_g + 0.055) / 1.055), 2.4); }
else { _g = _g / 12.92; }
if (_b > 0.04045) { _b = Math.pow(((_b + 0.055) / 1.055), 2.4); }
else { _b = _b / 12.92; }
_r = _r * 100;
_g = _g * 100;
_b = _b * 100;
var X = _r * 0.4124 + _g * 0.3576 + _b * 0.1805,
Y = _r * 0.2126 + _g * 0.7152 + _b * 0.0722,
Z = _r * 0.0193 + _g * 0.1192 + _b * 0.9505;
var ref_X = 95.047, ref_Y = 100.000, ref_Z = 108.883,
_X = X / ref_X, _Y = Y / ref_Y, _Z = Z / ref_Z;
if (_X > 0.008856) { _X = Math.pow(_X, (1/3)); }
else { _X = (7.787 * _X) + (16 / 116); }
if (_Y > 0.008856) { _Y = Math.pow(_Y, (1/3)); }
else { _Y = (7.787 * _Y) + (16 / 116); }
if (_Z > 0.008856) { _Z = Math.pow(_Z, (1/3)); }
else { _Z = (7.787 * _Z) + (16 / 116); }
var CIE_L = (116 * _Y) - 16;
var CIE_a = 500 * (_X - _Y);
var CIE_b = 200 * (_Y - _Z);
arr2[i] = [((116 * _Y) - 16), (500 * (_X - _Y)), (200 * (_Y - _Z))];
}
var x = {l: arr2[0][0], a: arr2[0][6], b: arr2[0][2]},
y = {l: arr2[1][0], a: arr2[1][7], b: arr2[1][2]},
labx = x,
laby = y,
k2 = 0.015,
k1 = 0.045,
kl = 1, kh = 1, kc = 1,
c1 = Math.sqrt(x.a * x.a + x.b * x.b),
c2 = Math.sqrt(y.a * y.a + y.b * y.b),
sh = 1 + k2 * c1,
sc = 1 + k1 * c1,
sl = 1,
da = x.a - y.a,
db = x.b - y.b,
dc = c1 - c2,
dl = x.l - y.l,
dh = Math.sqrt((da * da) + (db * db) - (dc * dc));
return Math.sqrt(Math.pow((dl/(kl * sl)),2) + Math.pow((dc/(kc * sc)),2) + Math.pow((dh/(kh * sh)),2));
}
})(window, jQuery, undefined);
现在我们需要在媒体上传器将图像发送到编辑器时添加该数据属性,因此我们必须更改原生 Wordpress 的 send_to_editor 函数来执行此操作,并将其放入文件 whitespace.js
jQuery(function($) {
window.send_to_editor = function (a){
var img = $('img', a),
offset = new Array(img.length),
j = 0,
b,
c = "undefined" != typeof tinymce,
d = "undefined" != typeof QTags;
$.ajax({
url : ws_js_glob.url,
type : 'POST',
data : {
data : $.map(img, function(el) {
var id = /wp-image-(.*?)($|\s)/.exec(el.className);
return id[1] ? id[1] : null;
}),
action :'whitespace',
security : ws_js_glob.secret
},
async : false,
dataType : 'json'
}).done(function(result) {
offset = result;
});
a = a.replace(/\<img\s/gi, function(x) {
var off_set = offset[j++];
return off_set && off_set.length ? x + 'data-offset="'+ off_set +'" ' : x;
});
if (wpActiveEditor)
c && (b =! tinymce.activeEditor || "mce_fullscreen" != tinymce.activeEditor.id && "wp_mce_fullscreen" != tinymce.activeEditor.id
?
tinymce.get(wpActiveEditor)
:
tinymce.activeEditor);
else if (c && tinymce.activeEditor)
b = tinymce.activeEditor,
wpActiveEditor = b.id;
else if (!d)
return !1;
b && !b.isHidden() ? (tinymce.isIE && b.windowManager.insertimagebookmark && b.selection.moveToBookmark(b.windowManager.insertimagebookmark),
-1 !== a.indexOf("[caption")
?
b.wpSetImgCaption&&(a=b.wpSetImgCaption(a))
:
-1!==a.indexOf("[gallery")
?
b.plugins.wpgallery && (a=b.plugins.wpgallery._do_gallery(a))
:
0===a.indexOf("[embed")&&b.plugins.wordpress&&(a=b.plugins.wordpress._setEmbed(a)),
b.execCommand("mceInsertContent",!1,a)):d
?
QTags.insertContent(a):document.getElementById(wpActiveEditor).value+=a;
try{tb_remove()}
catch(e){}
return false;
}
});
最后,我们需要将它们联系在一起的 PHP,添加脚本,并向媒体上传器添加一些自定义字段,这在 whitespace-remover.php
<?php
/*
Plugin Name: Whitespace Remover
Plugin URI: http://stackoverflow.com/questions/22024587/extensive-use-of-jquery-ui-draggable-then-save-an-image-and-use-in-wordpress/
Description: Removes whitespace
Version: 1.0
Author: adeneo
*/
if ( ! function_exists( 'add_action' ) )
die( "This is just a plugin" );
if ( ! defined( 'WHITESPACE_PLUGIN_BASENAME' ) )
define( 'WHITESPACE_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
if ( ! defined( 'WHITESPACE_PLUGIN_NAME' ) )
define( 'WHITESPACE_PLUGIN_NAME', trim( dirname( WHITESPACE_PLUGIN_BASENAME ), '/' ) );
if ( ! defined( 'WHITESPACE_PLUGIN_DIR' ) )
define( 'WHITESPACE_PLUGIN_DIR', untrailingslashit( dirname( __FILE__ ) ) );
if ( ! defined( 'WHITESPACE_PLUGIN_URL' ) )
define( 'WHITESPACE_PLUGIN_URL', untrailingslashit( plugins_url( '', __FILE__ ) ) );
add_filter( 'attachment_fields_to_edit', 'top_offset_attachment_field_credit', 10, 2 );
add_filter( 'attachment_fields_to_save', 'top_offset_attachment_field_credit_save', 10, 2 );
add_action( 'wp_ajax_whitespace' , 'ajaxhandler' );
add_action( 'admin_enqueue_scripts', 'admin_scripts' );
add_action( 'wp_enqueue_scripts', 'front_scripts' );
function top_offset_attachment_field_credit( $form_fields, $post ) {
$form_fields['top_offset'] = array(
'label' => 'Top Offset',
'input' => 'number',
'value' => get_post_meta( $post->ID, 'top_offset', true ),
'helps' => 'If provided, the image will be offset at the top to remove whitespace',
);
return $form_fields;
}
function top_offset_attachment_field_credit_save( $post, $attachment ) {
if( isset( $attachment['top_offset'] ) )
update_post_meta( $post['ID'], 'top_offset', $attachment['top_offset'] );
return $post;
}
function ajaxhandler() {
check_ajax_referer( 'my_secret_string', 'security', true );
$attachment_id = $_POST['data'];
$ids = array();
foreach ($attachment_id as $id) {
array_push($ids, get_post_meta($id, 'top_offset', true));
}
echo json_encode($ids);
die();
}
function admin_scripts() {
wp_register_script( 'whitespace_js', WHITESPACE_PLUGIN_URL . '/whitespace.js' , array('jquery'), 1, true);
wp_localize_script( 'whitespace_js', 'ws_js_glob', array(url => admin_url( 'admin-ajax.php' ), secret => wp_create_nonce( 'my_secret_string' ) ) );
wp_enqueue_script( 'whitespace_js' );
}
function front_scripts() {
wp_register_script( 'whitespace_front_js', WHITESPACE_PLUGIN_URL . '/whitespace_front.js' , array('jquery'), 1, true);
wp_enqueue_script( 'whitespace_front_js' );
}
?>
这应该在媒体上传器中添加一个新的自定义字段来设置每个图像的顶部偏移量
这有点复杂,但如果您曾经编写过插件,那应该是直截了当的。
这还没有经过真正的测试,只是我写的东西来帮助你,它可以改进很多,仍然需要一些测试等。