2012-06-19 11 views
7

Muszę opatrzyć komentarzem obrazek z chińskim tekstem i używam biblioteki Imagick już teraz.Jak korzystać z adnotowanego obrazka dla chińskiego tekstu?

Przykładem chiński tekst jest

这 是 中文

Chiński plik czcionki używany jest this

Plik oryginalnie nazywa 华文 黑体 .ttf

może być również znalezione w Mac OSX pod/Library/Font

Zmieniono nazwę na angielską STHeiTi.ttf, aby ułatwić wywołanie th e plik w kodzie php.

W szczególności the Imagick::annotateImage function

Ja również jestem using the answer from "How can I draw wrapped text using Imagick in PHP?".

Powodem, dla którego go używam jest powód, dla którego angielski tekst i aplikacje muszą zawierać adnotacje zarówno w języku angielskim, jak i chińskim, ale nie w tym samym czasie.

Problem polega na tym, że gdy uruchamiam annotateImage użyciu chiński tekst, mam adnotację, że wygląda jak 罍

Kod zawarte here

+1

Tekst w języku chińskim? A co z pierwszym tworzeniem grafiki chińskich symboli, a następnie scaleniem jej z obrazem? – hakre

+0

Jak mam to zrobić? –

+1

Cóż, dla każdej chińskiej postaci utwórz jeden obraz, który ją wyświetli. Następnie umieść te obrazy razem na przykład. Może nie być najlepszą metodą, ale może zaoszczędzić ci problemu, aby rzeczywiście użyć chińskiej czcionki. – hakre

Odpowiedz

2

Pełne rozwiązanie tutaj:

https://gist.github.com/2971092/232adc3ebfc4b45f0e6e8bb5934308d9051450a4

Główne idee:

musi ustawić charset HTML i kodowanie wewnętrzne na formularzu i na stronie przetwarzania

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

These linie muszą znajdować się w najwyższych liniach plików php.

Funkcja ta służy do określenia, czy tekst jest chiński i użyć prawego plik czcionki

function isThisChineseText($text) { 
    return preg_match("/\p{Han}+/u", $text); 
} 

Aby uzyskać więcej informacji sprawdź https://stackoverflow.com/a/11219301/80353

zestaw TextEncoding właściwie w obiekcie ImagickDraw

$draw = new ImagickDraw(); 

// set utf 8 format 
$draw->setTextEncoding('UTF-8'); 

Uwaga na literę U TF. Było to usłużnie wskazał mi przez Walter Tross w jego odpowiedź tutaj: https://stackoverflow.com/a/11207521/80353

Używaj preg_match_all eksplodować angielskich słów, chińskich słów i przestrzenie

// separate the text by chinese characters or words or spaces 
preg_match_all('/([\w]+)|(.)/u', $text, $matches); 
$words = $matches[0]; 

Zainspirowany tą odpowiedź https://stackoverflow.com/a/4113903/80353

działa podobnie a także tekst w języku angielskim:

+1

Ostatnie wyrażenie rozdzieli ciąg "UTF-8" na 3 oddzielne "słowa". Twoja poprawka w wordWrapAnnotation jest niepoprawna, ponieważ może teraz zwrócić spację lub interpunkcję na początku drugiej linii. 'explode ('', ...)' było poprawne, chyba że jest jakieś dziwactwo chińskiego pisma, którego nie znam. Sądzę również, że zaakceptowałeś moje rozwiązanie, ponieważ użyłeś dwóch zawartych w nim poprawek kodu. To prawda, że ​​dodałeś informacje, ale mogło to nastąpić w komentarzach (i mogłem też edytować moje rozwiązanie). –

+0

OK, teraz widzę, co jest "dziwactwem" chińskiego pisania: ogólnie nie ma spacji między słowami. Jednym ze sposobów podziału na "słowa", dla twoich celów, może być coś takiego: 'preg_split ("/((? <=) | (? = \ P {Han}) (? = \ PL))/u ", $ str, -1, PREG_SPLIT_NO_EMPTY) ', które" odcina "ciąg po spacji lub przed" literami "Han (w rzeczywistości słowa), ale końcowe spacje powinny być traktowane osobno (usunięte i dodane tylko wtedy, gdy nie ma podziału linii występuje). Uwaga: po "? <=' Istnieje spacja. –

+1

Należy rozszerzyć powyższe wyrażenie, aby nie dopuścić do tego, by określone znaki kończyły linię (znaki te są odpowiednikiem zachodnich znaków, które są zwykle poprzedzane spacją, np. Otwierają nawiasy lub otwierają cudzysłów - np. Zobacz [tutaj] (http: //msdn.microsoft.com/en-us/goglobal/bb688158.aspx)) –

3

Obawiam się, trzeba będzie wybrać TTF, które mogą wspierać Chińczyków punkty kodowe. Istnieje wiele źródeł na to, tu są dwa:

http://www.wazu.jp/gallery/Fonts_ChineseTraditional.html

http://wildboar.net/multilingual/asian/chinese/language/fonts/unicode/non-microsoft/non-microsoft.html

+0

Co masz na myśli przez punkty kodowe? –

+0

@kimsia http://inamidst.com/stuff/unidata/ –

+0

@kimsia: or [Unicode] (http://en.wikipedia.org/wiki/Unicode#Architecture_and_terminology) w Wikipedii –

5

Problem karmisz ImageMagick wyjście "rozgałęźnika linii" (wordWrapAnnotation), do którego jesteś utf8_decode ing wprowadzenie tekstu. Na pewno jest to złe, jeśli masz do czynienia z chińskim tekstem. utf8_decode może przetwarzać tylko tekst UTF-8, który MOŻE być przekonwertowany na ISO-8859-1 (najpopularniejsze 8-bitowe rozszerzenie ASCII).

Mam nadzieję, że tekst jest kodowany UTF-8. Jeśli tak nie jest, może być w stanie przekształcić go tak:

$text = mb_convert_encoding($text, 'UTF-8', 'BIG-5'); 

lub jak to

$text = mb_convert_encoding($text, 'UTF-8', 'GB18030'); // only PHP >= 5.4.0 

(w kodzie $text jest raczej $text1 i $text2).

Następnie istnieją (co najmniej) dwie rzeczy do poprawienia w kodzie:

  1. przekazać tekst „tak jak jest” (bez utf8_decode) do wordWrapAnnotation,
  2. zmiana argument setTextEncoding z "utf-8" do "UTF-8" zgodnie specs

mam nadzieję, że wszystkie zmienne w kodzie są inicjowane w jakiejś brakującej części. Przy dwóch powyższych zmianach (drugi może nie być konieczny, ale nigdy nie wiadomo ...), a przy brakujących częściach w miejscu, nie widzę powodu, dla którego twój kod nie powinien działać, chyba że plik TTF jest uszkodzony lub Biblioteka Imagick jest zepsuta (imagemagick, na której bazuje Imagick, jest świetną biblioteką, więc uważam tę ostatnią możliwość raczej za mało prawdopodobną).

EDIT:

obserwuję Państwa życzenie mogę zaktualizować moją odpowiedź z

a) fakt, że ustawienie mb_internal_encoding('utf-8') jest bardzo ważne dla rozwiązania, jak mówisz w swojej answer i

b) moja propozycja lepszego podziału linii, która działa akceptowalnie dla języków zachodnich i chińskiego, i to jest prawdopodobnie dobry punkt wyjścia dla innych języków używających logogramów Han (japońskie kanji i koreańska hanja):

function wordWrapAnnotation(&$image, &$draw, $text, $maxWidth) 
{ 
    $regex = '/(|(?=\p{Han})(?<!\p{Pi})(?<!\p{Ps})|(?=\p{Pi})|(?=\p{Ps}))/u'; 
    $cleanText = trim(preg_replace('/[\s\v]+/', ' ', $text)); 
    $strArr = preg_split($regex, $cleanText, -1, PREG_SPLIT_DELIM_CAPTURE | 
               PREG_SPLIT_NO_EMPTY); 
    $linesArr = array(); 
    $lineHeight = 0; 
    $goodLine = ''; 
    $spacePending = false; 
    foreach ($strArr as $str) { 
     if ($str == ' ') { 
     $spacePending = true; 
     } else { 
     if ($spacePending) { 
      $spacePending = false; 
      $line = $goodLine.' '.$str; 
     } else { 
      $line = $goodLine.$str; 
     } 
     $metrics = $image->queryFontMetrics($draw, $line); 
     if ($metrics['textWidth'] > $maxWidth) { 
      if ($goodLine != '') { 
       $linesArr[] = $goodLine; 
      } 
      $goodLine = $str; 
     } else { 
      $goodLine = $line; 
     } 
     if ($metrics['textHeight'] > $lineHeight) { 
      $lineHeight = $metrics['textHeight']; 
     } 
     } 
    } 
    if ($goodLine != '') { 
     $linesArr[] = $goodLine; 
    } 
    return array($linesArr, $lineHeight); 
} 

W słowach: dane wejściowe są najpierw oczyszczane przez zastąpienie wszystkich przebiegów białych znaków, w tym znaków nowej linii, pojedynczym odstępem, z wyjątkiem początkowych i końcowych białych znaków, które są usuwane. Następnie jest dzielona w spacjach lub tuż przed znakami Han nie poprzedzonymi znakami "wiodącymi" (takimi jak otwarcie nawiasów lub otwarcie cudzysłowów) lub bezpośrednio przed znakami "wiodącymi". Linie są montowane, aby nie były renderowane poziomo ponad 12,pikseli, z wyjątkiem sytuacji, gdy nie jest to możliwe dzięki regułom podziału (w takim przypadku ostateczne renderowanie prawdopodobnie przepełni się). Modyfikacja w celu wymuszenia podziału w skrzynkach przelewowych nie jest trudna. Zwróć uwagę, że np. Chińska interpunkcja nie jest sklasyfikowana jako Han w Unicode, więc poza "wiodącą" interpunkcją przed algorytmem nie można wstawić przed nim linii.

+0

Jest to najbardziej prawdopodobny powód zepsutego kodowania. –

+0

Witam Walter, twoja odpowiedź pomogła mi dojść do ostatecznego rozwiązania. Chciałbyś podziękować za pomoc. –

+0

Nie skorzystałem z rozwiązania mb_convert_encoding. –