2015-09-14 2 views
3

Я должен масштабировать изображения и превращать их в jpegs в браузере. Для этого я использовал функцию изменения размера javascript под названием Hermite-resizeУменьшение изображения с помощью Hermite-resize создает тонкую черную линию из ниоткуда

Это прекрасно работает. После повторной калибровки нескольких сотен изображений я заметил, что что-то странное случается каждый раз. С некоторыми изображениями в нижней части уменьшенного JPEG-изображения появляется тонкая черная линия.

Normal image and one with unwanted black line

Я думал, что это может быть из-за прозрачной линии визуализируется в уменьшенной версии. После преобразования в jpeg линия становится черной, так как jpegs не превращают фон в черный фон.

Однако, если я поставил белый фон за изображение перед его отображением как jpeg, проблема остается.

Если у кого-то есть идея о том, что создает это, или как его исправить, я был бы очень признателен.

jsfiddle пояснить, что я имею в виду:

canvas.getContext("2d").fillStyle = '#FFF'; 
canvas.getContext("2d").fillRect(0, 0, W2, H2); 
canvas.getContext("2d").putImageData(img2, 0, 0); 
document.getElementById("imageid").src = canvas.toDataURL("image/jpeg"); 

http://jsfiddle.net/gt4r54zr/1/

Я не уверен, если это связано, но если я установить прозрачность до полного (255) в скрипте Эрмита, то та же черная линия появляется, а также:

data2[x2 + 3] = 255;// Original value: gx_a/weights_alpha; 

http://jsfiddle.net/3osq1s1w/3/

+1

Это происходит только при точном значении пикселей? – invot

+1

Отличный вопрос invot. Это на самом деле. Для изображения в примере я помещаю все значения пикселей в пастебин (http://pastebin.com/C43FM9k8). Однако я не вижу в ней ничего общего. Хотя я действительно не понимаю, как ответ rphv, похоже, решает мою проблему, поэтому я счастлив :). – Kasper

ответ

2

Функция resample_hermite() вычисляет эти соотношения:

var ratio_w_half = Math.ceil(ratio_w/2); 
var ratio_h_half = Math.ceil(ratio_h/2); 

, которые в конечном итоге используются для определения размеров повторного размера изображения. Обратите внимание на Math.ceil, который округляет (ratio_h/2) до следующего наибольшего целого числа. Похоже, черная линия отображается в тех случаях, когда мантисса (т. Е. Все вправо десятичная точка) (ratio_h/2) составляет менее 0.5. В этих случаях расчетная высота изображения слишком велика, а данных для заполнения этих пикселей нет.

Изменение

var ratio_h_half = Math.ceil(ratio_h/2); 

в

var ratio_h_half = Math.round(ratio_h/2); 

, кажется, решить эту проблему в вашем примере.

+1

Спасибо, rphv !! Хотя у меня проблемы с пониманием, ваш ответ, похоже, решает мою проблему. Я попробовал это для всех тревожных высот пикселей этого примера изображения, и ни один из них не вызвал проблемы. Я попытался взглянуть на мантиссу, но я не видел описанного вами шаблона. Возможно, я сделал это неправильно. (Если вам нравится, вы можете найти значения по адресу http://pastebin.com/C43FM9k8) – Kasper

+2

Рад помочь. Ваши данные показывают образец, который я идентифицировал - позвольте мне уточнить.Рассмотрим '(Исходная высота/новая высота)/2': во всех случаях [мантисса] (http://mathworld.wolfram.com/Mantissa.html) (также * значение + * или« часть номера в справа от десятичной точки ") меньше, чем' 0,5'. Это означает, что 'Math.round()' и 'Math.ceil()' будут возвращать разные значения - например, 'Math.round (4.1666666667) = 4', но' Math.ceil (4.1666666667) = 5'. В этих случаях расчетный размер измененного изображения немного велик, а дополнительное пространство заполняется черной линией. – rphv

+0

Спасибо, rphv за дальнейшую разработку этого. Я понимаю разницу в округлении и то, как это может вызвать этот эффект. Это не происходит для всех значений с мантиссой, которая меньше 0,5. Я думаю, есть еще один фактор. Однако весь расчет в коде немного над моей головой. Я пытался понять, что происходит, но это само по себе могло быть ошибкой;). На данный момент я просто очень рад, что мои снимки отображаются правильно: D. Спасибо вам за это! – Kasper

Смежные вопросы