StrangePlanet » Blog

php

[PHP] UTF-8 mon ami

23 mai 2012 by Mistic 3 Comments

Qui a déjà codé en PHP-MySQL a surement pu faire l’expérience des caractères spéciaux mal encodés, mal affichés, mal enregistrés, mal lus, bref : tout cassé ! J’en ai fait la douloureuse expérience lors du développement initial de Lexiglot. Mais grâce à quelques conseils épars sur le net j’ai pu enfin trouver le remède à toute épreuve : TOUT faire en charset UTF-8.

1. Tout d’abord la partie HTML, ne pas oublier la balise meta qui va bien :

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

2. Ensuite le PHP, avant toute chose il faut explicitement dire au navigateur que l’on est en UTF-8 :

header('Content-type: text/html; charset=utf-8');

C’est deux choses là c’était la partie facile qu’on peut trouver un peu partout sur le net, vient ensuite une requête SQL spéciale que l’on doit faire juste après avoir établit la connexion avec mysql_connect() :

mysql_query('SET names utf8;');

Cette petite requête permet de dire que les transactions entre le serveur MySQL et PHP se font en UTF-8, c’est en général à cet endroit que la caractères spéciaux rendent l’âme.

3. Dernière partie, la base de donnée, elle doit être en interclassement utf8_general_ci, tout comme chacune des tables, pour les champs de type TEXT, VARCHAR, etc. utilisez aussi utf8_general_ci ou utf8_bin si vous voulez que vos requêtes soient sensibles à la casse.

PS: cette méthode est importante si vous avez autre chose que des caractères latin accentués dans vos données, dans le cas contraire le charset Latin1 fait très bien l’affaire.

Posted in: Développement, Web Tagged: charset, encodage, php, utf-8, utf8

[PHP] une fonction pour rechercher dans un tableau

30 juillet 2011 by Mistic Leave a Comment

Aujourd’hui on va encore faire un peu de PHP avec une fonction que j’ai créé pour rechercher une chaine de caractère dans les valeurs d’un tableau. Mais à la différence de array_search elle est faite pour chercher une chaine incomplète, par exemple pour trouver toutes les lignes qui contiennent le mot « chat ».

Prototype :

mixed array_pos ( string $needle , array $haystack [, bool $match_all = false [, bool $preg_mode = false ]] )

Fonction :

/**
 * search a string in array values (not like 'array_search')
 * from http://www.strangeplanet.fr
 *
 * @param string needle
 * @param array haystack
 * @param bool return all instances
 * @param bool search in PCRE mode
 * @return mixed
 */
function array_pos($needle, $haystack, $match_all=false, $preg_mode=false)
{
  if ($match_all) $matches = array();
  
  foreach ($haystack as $i => $row)
  {
    if (!is_array($row))
    {
      if (!$preg_mode)
      {
        if (strpos($row, $needle) !== false)
        {
          if (!$match_all) return $i;
          else array_push($matches, $i);
        }
      }
      else
      {
        if (preg_match($needle, $row) === 1)
        {
          if (!$match_all) return $i;
          else array_push($matches, $i);
        }
      }
    }
  }
  
  if (!$match_all) return false;
  return $matches;
}

Liste des paramètres :

  • $needle : est bien sur la chaine à rechercher
  • $haystack : est le tableau dans lequel on effectue la recherche
  • $match_all : si vaut true le fonction renverra toutes les occurrences trouvées, sinon elle ne renverra que la première
  • $preg_mode : si vaut true $needle peut être une expression régulière

Valeur de retour :

Si $needle est trouvé, array_pos() retourne la clef correspondante (ou un tableau de clefs si $match_all = true). Si $needle n’est pas trouvé, elle renvoie false (ou un tableau vide).

Exemple :

$array = array(
    0 => "J'aime les chats et les chiens", 
    5 => "J'aime les chats", 
    'mine' => "Je préfère mon chat"
  );

// première ligne qui contient "chats"
$result = array_pos("chats", $array);
var_dump($result);

// toutes les lignes qui contiennent "chats"
$result = array_pos("chats", $array, true);
print_r($result);

// lignes qui ne se terminent pas par un "s"
$result = array_pos("#[^s]$#", $array, true, true);
print_r($result);

Ceci va afficher :

int(0)
Array 
(
  [0] => 0
  [1] => 5
)
Array
(
  [0] => mine
)

Note :

La fonction n’est pas compatible avec les tableaux imbriqués, si un élément de $haystack est un tableau il sera ignoré.

Posted in: Développement Tagged: array_search, php, recherche, regex, tableau

[PHP] Bloquer l’embed d’images mais pas le hotlink

26 juin 2011 by Mistic Leave a Comment

Voici un besoin que j’ai eu pour TM-ScreenMania : empêcher les sites et forums d’embarquer les images haute-définition à l’aide des balises HTML < img > mais les autoriser tout de même à faire des liens directs vers ces images.

Toutes les solutions que j’ai pu trouver empêchent le hotlink c’est-à-dire les embeds ET les liens, et se basant sur le référant (HTTP Referrer).

J’ai donc cherché une façon de faire la différence entre les deux côté server. J’ai trouvé la solution dans la variable globale PHP $_SERVER[‘HTTP_ACCEPTED’]. Dans la cas d’un embed ça commence par image/jpeg mais dans le cas de l’image directement affichée (via un lien) ça commence par text/html.

Il n’y a plus qu’a faire un petit script (tms-image.php dans mon cas) qui teste cette valeur :

<?php
$accept = explode(',', $_SERVER['HTTP_ACCEPT']);

if ($accept[0] == 'text/html') 
{
  $pict = file_get_contents($_GET['file']);
} 
else 
{
  $pict = file_get_contents('hotlink.jpg');
}

header("Content-Type:image/jpeg");
echo $pict;
?>

et rediriger les images vers le script avec une redirection .htaccess (dans la galerie les images HD sont stockées dans un sous-dossier pwg_high) :

RewriteEngine on
RewriteRule ^(.*)/pwg_high/(.*)\.jpg$ tms-image.php?file=$1/pwg_high/$2.jpg [L]

Ce code très simple doit être un peu étoffé si on veut qu’il fonctionne avec différents types d’images.
Notez aussi que tel quel il empêche de faire un embed sur son propre site, pour y remédier on peut tester le referrer avant de faire la redirection pour ne pas la faire si on est sur son propre site :

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^http://(www\.)?tm-screenmania.com/.*$ [NC]
RewriteRule ^(.*)/pwg_high/(.*)\.jpg$ tms-image.php?file=$1/pwg_high/$2.jpg [L]
Posted in: Développement, Web Tagged: embed, hotlink, image, php, picture

[PHP] Calcul de la couleur dominante d’une image

22 mai 2011 by Mistic 12 Comments

Jusqu’à maintenant j’utilisais Picasa pour trouver la couleur dominante des images. Le soft utilise le même algorithme que Google Image (logique) et donne de bons résultats à mon sens. Seulement j’avais besoin d’un truc standalone, soit un soft qui s’exécute en ligne de commande, soit directement une fonction (PHP dans mon cas).
Après avoir trouvé diverses fonctions, aucune ne me satisfaisant pleinement, j’ai faut une compilation de tout ça.

Le but est donc de calculer de quelle couleur de référence l’image s’approche le plus. Dans mon cas ma référence est (en RGB) :

$colors = array(
  'red' => array(255,0,0),
  'orange' => array(255,127,0),
  'yellow' => array(255,255,0),
  'green' => array(0,255,0),
  'blue' => array(0,0,255),
  'purple' => array(127,0,255),
  'pink' => array(255,0,255),
  );

…car ce sont les couleurs que donne Picasa, on peut bien sur ajouter n’importe quelle couleur.

Déjà je travaille dans l’espace HSV (Hue-Saturation-Value), ça donne de meilleurs résultats que dans l’espace RGB (Red-Green-Blue).
Ensuite le fonctionnement est somme toute assez simple : il y à un compteur par couleur de base, qu’on incrémente pour chaque pixel de l’inverse de la différence entre la couleur du pixel et la base, différence calculée en norme euclidienne.
Ainsi le compteur le plus haut correspond à la couleur dominante.

Voici donc ma fonction :

<?php
/**
 * Copyright (C) 2011 Damien SOREL (Mistic)
 * http://www.strangeplanet.fr
 * 
 * This function is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 */

// conversion RGB -> HSV
function rgb2hsv ($RGB)
{
  $var_R = $RGB[0]/255;
  $var_G = $RGB[1]/255;
  $var_B = $RGB[2]/255;
  $var_Min = min($var_R, $var_G, $var_B);
  $var_Max = max($var_R, $var_G, $var_B);
  $del_Max = $var_Max - $var_Min;
  
  $V = $var_Max;

  if ($del_Max == 0)
  {
    $H = 0;
    $S = 0;  
  }
  else
  {
    $S = $del_Max / $var_Max;
    $del_R = ((($var_Max - $var_R)/6) + ($del_Max/2)) / $del_Max;
    $del_G = ((($var_Max - $var_G)/6) + ($del_Max/2)) / $del_Max;
    $del_B = ((($var_Max - $var_B)/6) + ($del_Max/2)) / $del_Max;
    
    if      ($var_R == $var_Max) $H = $del_B - $del_G;
    else if ($var_G == $var_Max) $H = (1/3) + $del_R - $del_B;
    else if ($var_B == $var_Max) $H = (2/3) + $del_G - $del_R;
    
    if      ($H<0) $H++;
    else if ($H>1) $H--;
  }
  
  return array($H*255, $S*255, $V*255);
}

// norme euclidienne
function distance($col1, $col2)
{
  $distance = 0;
  for($i=0 ; $i<3 ; $i++)
  {
    $diff[$i] = $col1[$i]/255-$col2[$i]/255;
    $distance += $diff[$i]*$diff[$i];
  }
  if ($distance == 0) $distance = 0.01; // pour ne pas avoir l'inverse de 0
  return sqrt($distance);
}

// fonctionne mère
function get_main_color($img, $points, $colors)
{
  $width = imagesx($img);
  $height = imagesy($img);
  $scale = intval(max($width,$height)/$points);
  
  // Pour chaque base on convertir en HSV et on initialise le compteur
  foreach ($colors as $name => $base)
  {
    $results[$name] = 0;
    $colors[$name] = rgb2hsv($base);
  }
  
  $colors_grey = 0; // Compteur pour les pixels gris (R=G=B)
  $pixel_count = 0; // Compteur du nombre total de pixels analysés
      
  for ($j=0; $j<$height; $j+=$scale)
  {
    for ($i=0; $i<$width; $i+=$scale)
    {
      // Couleur du pixel
      $color = imagecolorat($img, $i, $j);
      $r = ($color >> 16) &0xFF;
      $g = ($color >> 8) &0xFF;
      $b = $color &0xFF;
      
      if ($r==$g and $g==$b)
      {
        $colors_grey++;
      }
      else
      {
        // On incrémente le compteur de chaque base 
        // de l'inverse de la distance à la couleur du pixel
        foreach ($colors as $name => $base)
        {
          $color = rgb2hsv(array($r, $g, $b));
          $results[$name] += 1 / distance($color, $base);
        }
      }
      
      $pixel_count++;
    }
  }

  if ($colors_grey == $pixel_count)
  {
    return 'grey';
  }
  else
  {
    asort($results);
    $results = array_keys($results);
    return $results[count($results)-1];
  }
}

?>

Pour l’utiliser il suffit d’appeler la fonction get_main_color et lui fournissant une image, le nombre de points de contrôle (50 donne de bons résultats tout en ne prenant pas trop de temps, ça fait quand même 2500 points pour une image carrée) et le tableau de base.

$img = imagecreatefromjpeg($url);
echo get_main_color($img, 50, $colors);

J’ai fait de nombreux tests bien sur, en voici quelque-uns avec les fonds d’écrans de Windows 7 : http://www.strangeplanet.fr/files/color/
On remarque que sur certaines images Picasa est plus pertinent, sur d’autres c’est ma fonction… on ne peut pas tout avoir !

Posted in: Développement Tagged: couleur, dominante, image, php
1 2 Suivant »

Catégories

  • Créations (9)
  • Développement (16)
  • Général (1)
  • Perso (3)
  • Récits (5)
  • Tutoriels (3)
  • Web (8)

Articles récents

  • Use Travis CI & Coveralls for a web frontend library
  • Comment j’ai transformé un téléphone en moniteur système
  • jQuery QueryBuilder
  • [Piwigo] Un carrousel des dernières photos ajoutées
  • [Musique] Tarja: Colours in the Dark

Étiquettes

bateau c++ calcaires carbon chevrolet cité corvette désespoir encodage escalade extension font forever forêt galerie graphique image javascript jquery mer montagne mort musical musique oblivion patch photoshop php piwigo provence qt ruine rêve sexy site web skins tomb raider trackmania ultramon united ville visual voiture windows étranger

Copyright © 2019 StrangePlanet » Blog.

Omega WordPress Theme by ThemeHall

  • Accueil
  • Blog
  • Galerie
  • Projets
  • À-propos