Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Графика > удалить фон изображения


Автор: z-END 16.4.2013, 16:49
столкнулся с казалось бы простой, но уже второй день не решаемой проблемой...
в общем есть изображения  (jpg)  на белом или почти белом фоне и есть банальная задача - сделать из них PNG с прозрачностью (т.е. просто удалив фон) 
а как оказалось задать "прозрачный цвет" можно только один, т.е. так: 
Код

            imagecolortransparent ($out_img, imagecolorat ($out_img, 0, 0));

результат во вложении... собственно вопрос, как задать диапазон "прозрачных цветов"?   или какой-то другой способ более плавного решения задачи?

да, под рукой только GD2, imagemagik на сервере отсутствует..

Автор: krundetz 17.4.2013, 17:50
z-END, а нельзя проделать несколько шагов? То есть поэтапно сделать прозрачными нужные цвета.

Автор: Чучмек 17.4.2013, 22:09
можно поиграть с палитрой
Код

$transparentColor = array('R'=>255,'G'=>255,'B'=>255); //Прозрачный цвет
$dtclr = 30; //"Близость" к transparentColor 
$clrcnt = 256; //Цветов в палтре

header('Content-type:image/png');
$img = imagecreatefromjpeg('1.jpg');
imagetruecolortopalette($img,true,$clrcnt);
$cc=imagecolorstotal($img);
for ($i=0;$i<$cc;$i++)
 {
 $clr = imagecolorsforindex($img,$i);
 $dr=$transparentColor['R']-$clr['red'];
 $dg=$transparentColor['G']-$clr['green'];
 $db=$transparentColor['B']-$clr['blue'];
 if (sqrt($dr*$dr+$dg*$dg+$db*$db)<=$dtclr)
   imagecolorset($img,$i,$clr['red'],$clr['green'],$clr['blue'],127);
 };
imagepng($img);


Добавлено через 6 минут и 35 секунд
В imagecolorset смущает описание 6-го параметра
Цитата

alpha - Value of alpha component. 
This change exists in the development version of PHP, and will probably exist after 5.3. 

Автор: z-END 18.4.2013, 14:29
Цитата(Чучмек @  17.4.2013,  23:09 Найти цитируемый пост)
можно поиграть с палитрой

PNG24 насколько я понимаю truecolor, так что палитра для него не подойдет..

мыслей было две:
А:
1. берем цвет угловой точки запоминаем его
2.  попиксельно проходим все изображение и заменяем цвет из п.1. на цвет которого нет в изображении (-вопрос как его узнать)
3. находим imagecolorclosestalpha ближайшего к цвету из п.1. 
4.  выполняем пункты 3 и 2 Н-ное кол-во раз, и получаем диапазон цветов залитый "хромокеем", который потом используем в качестве прозрачного..

но, при стандартной фотке 2х3 тыщи пикселей, получаем 6 миллионов операций за 1 проход..  если делаем 20 проходов - 120 миллионов операций... мне кажется или это очень много?! ))

Автор: Чучмек 18.4.2013, 20:50
Цитата(z-END @  18.4.2013,  14:29 Найти цитируемый пост)
PNG24 насколько я понимаю truecolor, так что палитра для него не подойдет..

это на выходе, а на промежуточном этапе - очень даже.
Попробуй с разными dtclr (10-50) и clrcnt (до 2^16)

Автор: z-END 19.4.2013, 17:34
Чучмек,  действительно палитра работает.. только вот проблема все равно остается, хотя, конечно смотрится уже значительно лучше)
чуть подправил: 
Код

<?php
$dtclr = 428; 
$clrcnt = 16777216;  //TrueColor

header('Content-type:image/png');
$img = imagecreatefromjpeg('1.jpg');

imagetruecolortopalette ($img, true, $clrcnt);
$transparentColor  = imagecolorsforindex ($img, imagecolorat ($img, 1, 1));

for ($i=0; $i<imagecolorstotal ($img); $i++) {
     $clr = imagecolorsforindex ($img,$i);
     $dr=$transparentColor['red']-$clr['red'];
     $dg=$transparentColor['green']-$clr['green'];
     $db=$transparentColor['blue']-$clr['blue'];
        if (sqrt($dr*$dr+$dg*$dg+$db*$db)<=$dtclr) {
               imagecolorset ($img, $i ,$transparentColor['red'], $transparentColor['green'], $transparentColor['blue']);    
        }
    };
imagecolortransparent ($img, imagecolorat ($img, 1, 1));    
imagepng ($img);


с альфа каналом в  imagecolorset  работать отказался... ПХП чуть ниже версией...
результаты в атаче

Автор: Чучмек 19.4.2013, 21:36
Цитата(z-END @  19.4.2013,  17:34 Найти цитируемый пост)
чуть подправил: 

Да не, так не годится.
Я пробовал изменять цвета в палитре на transparentColor, но  imagecolortransparent изменяет на прозрачный только один цвет.
Еще попробую вызвать imagecolortransparent для каждого цвета, который должен стать прозрачным.
Цитата(z-END @  19.4.2013,  17:34 Найти цитируемый пост)
$dtclr = 428; 

Разница между черным и белым ((255-0)^2 + (255-0)^2 +(255-0)^2)^0,5 всего 442
Цитата(z-END @  19.4.2013,  17:34 Найти цитируемый пост)
$clrcnt = 16777216;  //TrueColor

Перебирать палитру хорошо, когда в ней мало цветов. 
Быстрей будет попиксельно перебрать
Код

$dtclr = 60;

$img = imagecreatefromjpeg('1.jpg');
header('Content-type:image/png');

$w = imagesx($img);
$h = imagesy($img);
$transparentClrInd = imagecolorat($img,0,0);
$transparentColor  = imagecolorsforindex($img,$transparentClrInd);
for($y=0;$y<$h;$y++)
for($x=0;$x<$w;$x++)
  {
  $clrind=imagecolorat($img,$x,$y);
  $clr = imagecolorsforindex ($img,$clrind);
  $dr=$transparentColor['red']-$clr['red'];
  $dg=$transparentColor['green']-$clr['green'];
  $db=$transparentColor['blue']-$clr['blue'];
  if (sqrt($dr*$dr+$dg*$dg+$db*$db)<=$dtclr)
     imagesetpixel($img,$x,$y,$transparentClrInd);
  }
imagecolortransparent ($img, $transparentClrInd);

imagepng($img);

 


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)