Есть ли способ использовать JavaScript для преобразования белого фона PNG в прозрачный фон?

У меня есть куча .png, в которых нет ничего, кроме черного текста на белом фоне. До сих пор все они отображались на белом фоне экрана, так что проблем не было; но теперь я меняю цвет фона. Проблема в том, что текст выглядит немного не так, когда он установлен на не совсем белом фоне, поэтому мне интересно узнать, способен ли JavaScript (jQuery в порядке) преобразовывать белый фон .png в прозрачный фон на лету. Меня не интересует решение этой проблемы на стороне сервера (например, сценарий для просмотра всех изображений и выполнения этого программно с библиотекой изображений), -ручной подход нецелесообразен.

Кто-нибудь знает способ сделать это? Поиск ничего не дал. Обратите внимание, что я не ищу исправление .png для IE!

Если есть способ, каковы будут накладные расходы, связанные с таким процессом?

Спасибо за любую помощь!


person Josh Leitzel    schedule 13.01.2011    source источник
comment
Хотя возможно, что есть способ сделать это, вероятно, с помощью функций, специфичных для браузера, оно того не стоит. Просто найдите приложение, которое будет выполнять конвертацию в пакетном режиме. Утилиты командной строки ImageMagick, вероятно, помогут вам в работе.   -  person Brian Donovan    schedule 13.01.2011
comment
Спасибо, Брайан. Я полагаю, что это, вероятно, сведется к этому, но я хотел сначала изучить свои варианты.   -  person Josh Leitzel    schedule 13.01.2011


Ответы (2)


Самое близкое, что я могу думать, это специфично для IE, есть фильтр цветности, который может делать то, что вы хотите (вроде синего экрана, где все синее будет прозрачным, в вашем случае все белое будет прозрачным). , см.: http://www.ssi-developer.net/css/visual-filters.shtml. Не нашел эквивалента для этого ни в других браузерах, ни в CSS3.

Можно создать сценарий, который ищет все изображения в документе, заменяет его элементом холста, рисует изображение на холсте, просматривает данные изображения попиксельно и, если пиксель имеет определенный цвет, изменяет его альфа до 0 (прозрачный).

Вот краткий POC по этой концепции ... Вам нужно запустить это на веб-сервере, чтобы оно работало в Chrome и FF, оно может работать локально в бета-версии IE9.

Просто измените изображение на что-нибудь с чистым белым цветом RGB (255, 255, 255). Он сделает любой белый пиксель изображения прозрачным, установив для его альфа-канала значение 0.

<!DOCTYPE html>
<html>
  <head>
    <title>Test</title>
    <style type="text/css">
      body { background-color: #00f; margin: 0px; padding: 0px; }
    </style>
    <script type="text/javascript" src="jquery-1.4.4.min.js"></script>
  </head>
  <body>
    <img src="test.png">
    <img src="test.png">
  </body>
  <script type="text/javascript">
    $(function() {
      $("img").each(function() {
        var $this = $(this);
        var tim = $this.get(0);
        var idx = $this.index();

        var canvas = null;
        var ctx = null;

        var img = new Image();
        img.onload = function() {
          copyImageToCanvas(img);
        };
        img.setAttribute("src", tim.src);

        function copyImageToCanvas(aImg) {
          canvas = document.createElement("canvas");

          var w = typeof aImg.naturalWidth == "undefined" ? aImg.width : aImg.naturalWidth;
          var h = typeof aImg.naturalHeight == "undefined" ? aImg.height : aImg.naturalHeight;

          canvas.id = "img" + idx;
          canvas.width = w;
          canvas.height = h;

          $this.replaceWith(canvas);

          ctx = canvas.getContext("2d");
          ctx.clearRect(0, 0, w, h);      
          ctx.drawImage(aImg, 0, 0);

          makeTransparent(aImg);
        }

        function makeTransparent(aImg) {

          var w = typeof aImg.naturalWidth == "undefined" ? aImg.width : aImg.naturalWidth;
          var h = typeof aImg.naturalHeight == "undefined" ? aImg.height : aImg.naturalHeight;
          var imageData = ctx.getImageData(0, 0, w, h);

          for (var x = 0; x < imageData.width; x++)
            for (var y = 0; y < imageData.height; y++) {
              var offset = (y * imageData.width + x) * 4;
              var r = imageData.data[offset];
              var g = imageData.data[offset + 1];
              var b = imageData.data[offset + 2];

              //if it is pure white, change its alpha to 0              
              if (r == 255 && g == 255 && b == 255)
                imageData.data[offset + 3] = 0;
            };

          ctx.putImageData(imageData, 0, 0);
        }
      });
    });
  </script>
</html>
person Jimmy Chandra    schedule 13.01.2011
comment
Спасибо за ответ, Джимми! Хотя это не решило мою проблему (которая, вероятно, неразрешима с ее текущим определением), ваш ответ был очень полезным. - person Josh Leitzel; 09.02.2011
comment
Сначала я пробовал на jsfiddle, но междоменная проблема затрудняет тестирование. На моем сервере я подтвердил, что этот код работает для меня. Это работает для меня. Спасибо. - person Kabkee; 06.03.2016

Единственный известный мне вариант обработки изображений js — это Pixastic, и у него нет нужной вам функции. Вы должны сделать это на стороне сервера, насколько я знаю

person nunopolonia    schedule 13.01.2011
comment
И если вы сделаете это на стороне сервера, вы можете просто AJAX вернуть новые изображения, чтобы вы не возвращали полную публикацию страницы. - person The Muffin Man; 14.01.2011