Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP] "zaokrąglanie kolorów"
Forum PHP.pl > Forum > Przedszkole
kleszczoscisk
Witam

Czy ktoś może zna sposób na to aby niejako zaokrąglić dowolny kolor zapisany w systemie szesnastkowym, do najbardziej zbliżonego mu koloru ze zdefiniowanej wczesniej palety, np. "web safe"? Chodzi o to żeby np. 5 rodzajów czerwieni (#CC0001,#CC0002,#CC0003,#FF0003,#990005) wynikowo "zaokrąglić" np. do #CC0000.
Są klasy i funkcje wyciągające paletę z obrazka, ale te które widziałem wypluwają najróżniejsze kolory, marzy mi się żeby te kolory uprościć żeby były w jakimś z góry zdefiniowanym zbiorze, np. web safe.
Może ktoś podpowie jak to ugryźć, albo zna jakieś gotowe rozwiązanie?

trueblue
Przygotuj tabelę bezpiecznych kolorów.
Potem w pętli musisz sprawdzić dystans między badanym kolorem, a kolorem z tablicy.
Dystans liczysz tak:
pierw((r2-r1)^2 + (g2-g1)^2 + (b2-b1)^2)
Oczywiście najmniejszy dystans to najbliższy kolor.
kleszczoscisk
Dzięki Trueblue. Nie działa mi to według tego jak zrobiłem do testów... Help.


  1. <?php
  2. $conn = mysql_connect(SQL_HOST, SQL_USER, SQL_PASS) or die ("Nie udało sie połączyć z bazą danych MySQL " . mysql_error());
  3. mysql_select_db(SQL_DB, $conn);
  4. mysql_query("SET NAMES utf8");
  5. mysql_query("SET CHARACTER SET utf8");
  6. mysql_query("SET collation_connection = utf8_general_ci");
  7. ?>
  8. <!DOCTYPE HTML>
  9. <html>
  10. <head>
  11. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  12. <title>test</title>
  13. </head>
  14. <body>
  15. <?php
  16. function hex2rgb($hex) {
  17. $hex = str_replace("#", "", $hex);
  18. if(strlen($hex) == 3) {
  19. $r = hexdec(substr($hex,0,1).substr($hex,0,1));
  20. $g = hexdec(substr($hex,1,1).substr($hex,1,1));
  21. $b = hexdec(substr($hex,2,1).substr($hex,2,1));
  22. } else {
  23. $r = hexdec(substr($hex,0,2));
  24. $g = hexdec(substr($hex,2,2));
  25. $b = hexdec(substr($hex,4,2));
  26. }
  27. $rgb = array($r, $g, $b);
  28. //return implode(",", $rgb); // returns the rgb values separated by commas
  29. return $rgb; // returns an array with the rgb values
  30. }
  31.  
  32. //losowe kolory
  33. for($x = 0; $x <= 10; $x++ ){
  34. $losowy = dechex(rand(0,255)).''.dechex(rand(0,255)).''.dechex(rand(0,255));
  35. echo '<div style="padding:1em;float:left;width:5%;background:#'.$losowy.';"><a href="'.$_SERVER['PHP_SELF'].'?kolor='.$losowy.'">#'.$losowy.'</a></div>';
  36. }
  37.  
  38. //losowy kolor w get
  39. if(isset($_GET['kolor'])){$color_hex = '#'.$_GET['kolor'];}
  40. else $color_hex = '#000000';
  41.  
  42. //na rgb
  43. $color_rgb = hex2rgb($color_hex);
  44.  
  45. //wyświetlenie
  46. echo '<br /><div style="float:none;clear:both;background:'.$color_hex.';"><strong>kolor zadany: '.$color_hex.'<br />rgb('.$color_rgb[0].','.$color_rgb[0].','.$color_rgb[0].')</strong></div>';
  47.  
  48.  
  49. $query = "SELECT * FROM colors ORDER BY id";
  50. $result = mysql_query($query) or die (mysql_error());
  51.  
  52. while($row = mysql_fetch_row($result)){
  53. //echo $color_rgb[0].'+'.$color_rgb[1].'+'.$color_rgb[2].'<br />';
  54. //print_r($color_rgb);
  55. $roznica = (($row[2]-$color_rgb[0])^2 + ($row[3]-$color_rgb[1])^2 + ($row[4]-$color_rgb[2])^2);
  56. $dystanse[] = (($row[2]-$color_rgb[0])^2 + ($row[3]-$color_rgb[1])^2 + ($row[4]-$color_rgb[2])^2);
  57. array_push($row, $roznica);
  58. $tablica[] = $row;
  59.  
  60. $c = array_combine($dystanse, $tablica);
  61. }
  62.  
  63. ksort($c);
  64. $kolor = array_shift($c);
  65.  
  66. echo '<div style="background:'.$kolor[1].';"><strong>kolor zbliżony: '.$kolor[1].'<br />rgb('.$kolor[2].','.$kolor[3].','.$kolor[4].')</strong><br />dystans: '.$kolor[5].'</div>';
  67.  
  68.  
  69. //echo 'tablica: '.count($tablica);
  70. //echo ' dystanse: '.count($dystanse);
  71. echo '<pre>';
  72. print_r($kolor);
  73. echo '</pre>';
  74.  
  75. ?>
  76. </body>
  77. </html>
  78.  



  1. --
  2. -- Struktura tabeli dla tabeli `colors`
  3. --
  4.  
  5. CREATE TABLE IF NOT EXISTS `colors` (
  6. `id` int(11) NOT NULL AUTO_INCREMENT,
  7. `hex` char(7) NOT NULL,
  8. `r` tinyint(3) UNSIGNED NOT NULL,
  9. `g` tinyint(3) UNSIGNED NOT NULL,
  10. `b` tinyint(3) UNSIGNED NOT NULL,
  11. PRIMARY KEY (`id`)
  12. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=217 ;
  13.  
  14. --
  15. -- Zrzut danych tabeli `colors`
  16. --
  17.  
  18. INSERT INTO `colors` (`id`, `hex`, `r`, `g`, `b`) VALUES
  19. (1, '#FF00FF', 255, 0, 255),
  20. (2, '#FF33FF', 255, 51, 255),
  21. (3, '#CC00CC', 204, 0, 204),
  22. (4, '#FF66FF', 255, 102, 255),
  23. (5, '#CC33CC', 204, 51, 204),
  24. (6, '#990099', 153, 0, 153),
  25. (7, '#FF99FF', 255, 153, 255),
  26. (...)
  27. (214, '#666666', 102, 102, 102),
  28. (215, '#333333', 51, 51, 51),
  29. (216, '#000000', 0, 0, 0);


Cytat
pierw((r2-r1)^2 + (g2-g1)^2 + (b2-b1)^2)


ten sposób raz trafia, raz nie:
Cytat
sqrt((r2-r1)^2 + (g2-g1)^2 + (b2-b1)^2)

trueblue
Na pewno błąd jest w liczeniu różnicy, "^" ma inne znaczenie w PHP.
  1. $roznica = sqrt(pow($row[2]-$color_rgb[0],2) + pow($row[3]-$color_rgb[1],2) + pow($row[4]-$color_rgb[2],2));
  2. $dystanse[] = $roznica; // policzyłeś to wcześniej, więc nie ma sensu drugi raz


Popatrz również na wartości hex losowych kolorów, niektóre są pięcioznakowe.
kleszczoscisk
Uff... problem był w sposobie liczenia dystansu, w zależnoci od tego która wartosc RGB (zadana czy szukana) była większa od tej należało odjąć:
  1. //red
  2. if($row[2]>$color_r) $roznica_r = $row[2]-$color_r;
  3. elseif($row[2]<$color_r) $roznica_r = $color_r-$row[2];
  4. else $roznica_r = 0;
  5. //green
  6. if($row[3]>$color_g) $roznica_g = $row[3]-$color_g;
  7. elseif($row[3]<$color_g) $roznica_g = $color_g-$row[3];
  8. else $roznica_g = 0;
  9. //blue
  10. if($row[4]>$color_b) $roznica_b = $row[4]-$color_b;
  11. elseif($row[4]<$color_b) $roznica_b = $color_b-$row[4];
  12. else $roznica_b = 0;
  13.  
  14. $roznica = ($roznica_r+ $roznica_g + $roznica_b);

$row[2], $row[3], $row[4] - wartosci rgb szukane
$color_r,$color_b,$color_b - rgb zadane

Dzięki za pomoc.
trueblue
Nie, źle liczysz.
Nie ma znaczenia, która jest większa, bo różnicę podnosisz do kwadratu.
Różnicę każdej składowej podnosisz do kwadratu, dodajesz składowe i z sumy wyciągasz pierwiastek.
kleszczoscisk
  1. $roznica = sqrt( pow(($row[2]-$color_r),2)+ pow(($row[3]-$color_g),2) + pow(($row[4]-$color_b),2) );


Mam wrażenie, że działa tak samo smile.gif
Dzięki jeszcze raz.
trueblue
To równanie to nic innego jak dystans euklidesowy: http://pl.wikipedia.org/wiki/Odleg%C5%82o%C5%9B%C4%87
Wyobraź sobie, że działasz w przestrzeni 2D (a nie 3D jak w Twoim przypadku).
Nie możesz obliczyć odległości między dwoma punktami na zasadzie różnic ich współrzędnych (według Twojego algorytmu odległość między punktem (2,2) a (4,4) jest taka sama jak między (2,2) a (2,6)).
kleszczoscisk
Świat jest piękny, jeszcze tyle można się nauczyć smile.gif W życiu bym nie pomyślał, że trafię na zagadnienie z geometrii przy okazji dłubania w kolorach.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.