Как определить, использует ли изображение прозрачность в Javascript?

Я хотел бы иметь возможность определить, имеет ли изображение типа логотипа прозрачный фон или нет, давайте представим, что два похожих изображения представляют собой файлы .png, но у одного есть белый фон, а у другого прозрачный фон, как бы я мог определить тот, с прозрачностью?

Я пытался использовать colorthief, но он не учитывает прозрачность, поэтому я решил сделать это самостоятельно на canvas. Первым решением было бы преобразовать файл png в jpg, и если цвет фона jpg после преобразования кажется черным, то это прозрачный логотип, но это может быть проблемой для пользователей с черным фоном и белыми логотипами. Есть ли лучшее решение, чем это?

http://jsfiddle.net/9s5qf5cu/

из png в jpg

var imageLoader = document.getElementById('imageLoader');
imageLoader.addEventListener('change', handleImage, false);

var canvas = document.getElementById('imageCanvas');
var ctx = canvas.getContext('2d');


function handleImage(e){
    var reader = new FileReader();
    reader.onload = function(event){
        var img = new Image();
        img.onload = function(){
            canvas.width = 100;
            canvas.height = 100;
            ctx.drawImage(img,0,0, 100, 100);
            document.getElementById("image").src = canvas.toDataURL("image/jpeg");
        }
        img.src = event.target.result;

    }
    reader.readAsDataURL(e.target.files[0]);     
}

person Hiroyuki Nuri    schedule 15.07.2017    source источник
comment
Первым решением было бы преобразовать файл png в jpg ‹-- К вашему сведению: JPEG не имеет альфа-канала.   -  person Zomry    schedule 15.07.2017
comment
@Zomry Я знаю это, но при преобразовании файла png в jpg вы получаете черный фон, если изображение прозрачно.   -  person Hiroyuki Nuri    schedule 15.07.2017
comment
Вероятно, для этого есть много способов, один из них - сделать то, что вы предлагаете, возможно, проверив все пиксели и определив, имеют ли определенное количество пикселей тот же цвет, что и фон. Использование другого изображения в качестве фона сделало бы маловероятным совпадение большого количества пикселей и т. д. Однако правильно было бы отправить изображение на сервер и использовать ImageMagick для проверки альфа-канала.   -  person adeneo    schedule 15.07.2017
comment
@Lindow Вы не получаете черный фон при преобразовании. Это программное обеспечение или алгоритм, который вы собираетесь использовать, решает установить черный фон. Но он может быть розовым!   -  person lilezek    schedule 15.07.2017
comment
@lilezek Да, я это понимаю, но я говорю, что в моем случае на jsfiddle он черный, и я мог бы использовать это, чтобы определить, был ли фон прозрачным   -  person Hiroyuki Nuri    schedule 15.07.2017
comment
но при преобразовании файла png в jpg вы получаете черный фон, если изображение прозрачно - и как это поможет вам определить, был ли у вас PNG с прозрачным фоном или тот, который был черным в начале с участием? Я полагаю, что копирование PNG на холст и использование getImageData и проверка альфа-уровня каждого отдельного пикселя (при условии, что копирование изображения, содержащего такие прозрачные части, на пустой холст сохраняет эти значения нетронутыми.)   -  person CBroe    schedule 15.07.2017
comment
@CBroe Интересно, я не знал, что вы можете проверить альфа-уровень каждого пикселя на холсте.   -  person Hiroyuki Nuri    schedule 15.07.2017
comment
getImageData возвращает ImageData со свойством data, содержащим одномерный массив целых чисел, R , G, B и A для каждого пикселя, только одно за другим.   -  person CBroe    schedule 15.07.2017
comment
но я говорю, что в моем случае на jsfiddle он черный - ну, это, вероятно, потому, что программа, которая создала ваш PNG, просто поместила туда черные пиксели с альфа-значением, равным нулю... но это могло быть любого другого цвета, например, если пользователь графической программы выбрал область с помощью инструмента «волшебная палочка» по цвету, а затем сделал свой выбор прозрачным.   -  person CBroe    schedule 15.07.2017
comment
Я предполагаю, что это немного проблематично, любое изображение, вставленное в холст, которое не из того же источника, будет испорчено, поэтому любое изображение, используемое в JSFiddle, должно происходить из этого источника.   -  person adeneo    schedule 15.07.2017
comment
На MDN есть демонстрация. , немного вниз по странице   -  person adeneo    schedule 15.07.2017
comment
Это должно быть достаточно просто для достижения, если у вас уже есть код для загрузки PNG на холст (создание холста правильных размеров)... Вы получаете данные изображения, а затем вы можете проверить простой цикл for, начиная с 0 , увеличивая счетчик цикла на 4 каждый раз, независимо от того, указывает ли альфа-значение на отсутствие прозрачности для этого пикселя. Если вы столкнетесь с таким, установите флажок и выйдите из цикла...   -  person CBroe    schedule 15.07.2017


Ответы (1)


Используйте эту функцию, передав свой контекст и свой холст. Затем он будет перебирать альфа-канал, пока не найдет запись, которая не является полностью непрозрачной.

function hasAlpha (context, canvas) {
    var data = context.getImageData(0, 0, canvas.width, canvas.height).data,
        hasAlphaPixels = false;
    for (var i = 3, n = data.length; i < n; i+=4) {
        if (data[i] < 255) {
            hasAlphaPixels = true;
            break;
        }
   }
   return hasAlphaPixels;
}

Примечание: это не сработает, если ваш холст испорчен.

person Zomry    schedule 15.07.2017
comment
Спасибо, у меня возникли проблемы с его работой: jsfiddle.net/9s5qf5cu/2 что я должен ввести к контексту? - person Hiroyuki Nuri; 15.07.2017
comment
В этой функции это будет ctx. - person Zomry; 15.07.2017
comment
Каждое изображение, которое я пробую, кажется прозрачным, даже если это не так. - person adeneo; 15.07.2017
comment
Я вижу, я начал с i с 0, а должен был начинаться с 3. Попробуйте эту версию: jsfiddle.net /Zomry/g0mt5obw - person Zomry; 15.07.2017