Сценарий Гнуда избыточно вызывает imagesx и imagesy. Он также выполняет итерацию каждого пикселя со всех сторон, даже когда углы перекрываются. Эта улучшенная версия исключает избыточные вызовы функций и проверяет каждый пиксель только один раз, обеспечивая значительное увеличение скорости. Функция возвращает статус ($ result ['#']), равный 2, если каждый пиксель обрезается.
example();
function example(){
$img = imagecreatefromjpeg("http://ecx.images-amazon.com/images/I/413XvF0yukL._SL500_AA280_.jpg");
// find the trimmed image border
$box = imageTrimBox($img);
// copy cropped portion
$img2 = imagecreate($box['w'], $box['h']);
imagecopy($img2, $img, 0, 0, $box['l'], $box['t'], $box['w'], $box['h']);
// output cropped image to the browser
header('Content-Type: image/png');
imagepng($img2);
imagedestroy($img);
imagedestroy($img2);
}
function imageTrimBox($img, $hex=null){
if (!ctype_xdigit($hex)) $hex = imagecolorat($img, 0,0);
$b_top = $b_lft = 0;
$b_rt = $w1 = $w2 = imagesx($img);
$b_btm = $h1 = $h2 = imagesy($img);
do {
//top
for(; $b_top < $h1; ++$b_top) {
for($x = 0; $x < $w1; ++$x) {
if(imagecolorat($img, $x, $b_top) != $hex) {
break 2;
}
}
}
// stop if all pixels are trimmed
if ($b_top == $b_btm) {
$b_top = 0;
$code = 2;
break 1;
}
// bottom
for(; $b_btm >= 0; --$b_btm) {
for($x = 0; $x < $w1; ++$x) {
if(imagecolorat($img, $x, $b_btm-1) != $hex) {
break 2;
}
}
}
// left
for(; $b_lft < $w1; ++$b_lft) {
for($y = $b_top; $y <= $b_btm; ++$y) {
if(imagecolorat($img, $b_lft, $y) != $hex) {
break 2;
}
}
}
// right
for(; $b_rt >= 0; --$b_rt) {
for($y = $b_top; $y <= $b_btm; ++$y) {
if(imagecolorat($img, $b_rt-1, $y) != $hex) {
break 2;
}
}
}
$w2 = $b_rt - $b_lft;
$h2 = $b_btm - $b_top;
$code = ($w2 < $w1 || $h2 < $h1) ? 1 : 0;
} while (0);
// result codes:
// 0 = Trim Zero Pixels
// 1 = Trim Some Pixels
// 2 = Trim All Pixels
return array(
'#' => $code, // result code
'l' => $b_lft, // left
't' => $b_top, // top
'r' => $b_rt, // right
'b' => $b_btm, // bottom
'w' => $w2, // new width
'h' => $h2, // new height
'w1' => $w1, // original width
'h1' => $h1, // original height
);
}
Рассмотрите возможность инкапсуляции:
public class TwoTypesConsumer {
private TomatoConsumer tomatoConsumer = new TomatoConsumer();
private AppleConsumer appleConsumer = new AppleConsumer();
public void consume(Tomato t) {
tomatoConsumer.consume(t);
}
public void consume(Apple a) {
appleConsumer.consume(a);
}
public static class TomatoConsumer implements Consumer<Tomato> {
public void consume(Tomato t) { ..... }
}
public static class AppleConsumer implements Consumer<Apple> {
public void consume(Apple a) { ..... }
}
}
Если вас беспокоит создание этих статических внутренних классов, вы можете использовать анонимные классы:
public class TwoTypesConsumer {
private Consumer<Tomato> tomatoConsumer = new Consumer<Tomato>() {
public void consume(Tomato t) {
}
};
private Consumer<Apple> appleConsumer = new Consumer<Apple>() {
public void consume(Apple a) {
}
};
public void consume(Tomato t) {
tomatoConsumer.consume(t);
}
public void consume(Apple a) {
appleConsumer.consume(a);
}
}
Вы можете вернуться к C и использовать sprintf
printf(stderr,"The Error(%d) happened(%s)\n",error,errmsg(error));
Boost также имеет формат.
Вот возможное решение, основанное на решении Стива МакЛеода :
public class TwoTypesConsumer {
public void consumeTomato(Tomato t) {...}
public void consumeApple(Apple a) {...}
public Consumer<Tomato> getTomatoConsumer() {
return new Consumer<Tomato>() {
public void consume(Tomato t) {
consumeTomato(t);
}
}
}
public Consumer<Apple> getAppleConsumer() {
return new Consumer<Apple>() {
public void consume(Apple a) {
consumeApple(t);
}
}
}
}
Неявное требование вопроса было Потребитель <Помидор>
и Потребитель
объекты с общим состоянием. Потребность в объектах Consumer
возникает из-за других методов, которые ожидают их в качестве параметров. Мне нужен один класс, чтобы реализовать их оба, чтобы поделиться состоянием.
Идея Стива состояла в том, чтобы использовать два внутренних класса, каждый из которых реализует свой общий тип.
Эта версия добавляет геттеры для объектов, реализующих интерфейс потребителя, которые затем могут быть переданы другим ожидающим их методам.
По крайней мере, вы можете немного улучшить свою реализацию диспетчеризации, выполнив что-то вроде следующего:
public class TwoTypesConsumer implements Consumer<Fruit> {
Fruit - предок Tomato и Apple.