You are here

README.txt in ImageCache Actions 7

README
------
README for the Image effect text module.

Author Erwin Derksen (fietserwin: https://drupal.org/user/750928)


Dependencies
------------
Hard dependencies:
- Imagecache actions.
- Image (Drupal core).

Soft dependencies/recommended modules:
- Imagemagick (preferred toolkit, https://drupal.org/project/imagemagick).
- PHP filter (Drupal core, if yuo want to use PHP to create the text to render).
- System stream wrapper (https://drupal.org/project/system_stream_wrapper)
- Remote stream wrapper (https://drupal.org/project/remote_stream_wrapper)
The latter 2 provide additional stream wrappers. Especially the system stream
wrapper is very handy as it provides, among others, a module:// and theme://
wrapper.


Toolkit
-------
Personally, I prefer the imagemagick toolkit:
- It is better in anti-aliasing, try to rotate an image using both toolkits and
  you will see what I mean.
- It does not execute in the PHP memory space, so is not restricted by the
  memory_limit PHP setting.
- The GD toolkit will, at least on my Windows configuration, keep the font file
  open after a text operation, so you cannot delete, move or rename it anymore.
- This module does a better job with Imagemagick (see below).


Installing
----------
As usual. After enabling the module you can add texts to images. This image
effect works with both the GD and imagemagick toolkit, though results differ
depending on the toolkit you use.


More information about the effect data options
----------------------------------------------

Font
----
This module comes with some free fonts so you can easily test this effect.
Please read their respective licences.

For real use, you normally want to use your own font as dictated by the website
design. The font types supported depend on the toolkit in use, but at least ttf
files will always work. This option accepts either:
- 1 of the (enabled) scheme's:
  * public://
  * private:// Preferred for site specific masks, overlays, etc, that do not
    need to be shared publicly.
  * temporary:// Unlikely to be useful, but supported anyway as all schemes are
    supported.
  * module:// Introduced by the system stream wrapper module and preferred for
    module provided resources.
  * theme:// idem.
  * profile:// idem.
  * library:// idem.
- A relative path (relative to the current directory, probably Drupal root).
- An absolute path.
- A system or toolkit font specification. E.g. on my Windows system 'arial.ttf'
  worked with both GD and Imagemagick. A warning will be issued but that may be
  ignored when it works as expected.


Text position
-------------
The text position defines the point in the image where you want to place (align)
your text. It starts at the top left corner of the image with position 0,0 and
the positive directions are to the right and down.

The definition of the vertical position differs per toolkit. For GD it is the
position of the font baseline, while for Imagemagick it is the bottom of the
bounding box, i.e the descender or beard line in typography terminology.


Text alignment
--------------
You can align your text with regard to the text position. Possible horizontal
alignments are left (default), center and right. Vertical alignments are top,
center and bottom (default).

Note: Given
- the way that GD uses the vertical text position (as baseline),
- and the way this module implements (vertical) alignment (translating the
  (vertical) position using the calculated bounding box),
vertical alignment with the GD toolkit is a bit off. You will have to compensate
for this yourself.


Rotation
--------
The text can be rotated before being overlaid on the image. The value is in
degrees. Positive values are rotated clockwise, So 90 degrees is straight down.
negative values counter clockwise.

In Imagemagick the text is rotated around the text position. Thus centered text
is rotated around its own center. GD, on the other hand, always rotates around
the left bottom (baseline) position, regardless the text alignment. So using
rotation with a non default alignment (left bottom) will give surprising
results.


Text source
-----------
The text to place on the image may come from different sources:
- Text (with token replacement): the text to place on the image has to be
  entered on the image effect form. Use this e.g. for a copyright notice.
  notes:
  * Token replacement: you can use all global tokens, the file tokens, and
    tokens from entities referring to the image via an image field. Example: if
    you know that the image style is only used for article nodes, you can use
    [node:field-image:alt] to get the alt text of the image. Note: this specific
    example requires the entity_token module.
  * New lines: you can add a new line by adding \n to your text. To get a
    literal \n, use \\n.
- PHP: the text to place on the image comes from a piece of PHP code that should
  return the text to place on the image. Only users with the 'use PHP for
  settings' permission are allowed to use this source. This permission and the
  evaluation of the PHP code come from the PHP filter module which is part of
  Drupal core and thus needs to be enabled, also during image generation.
  To add new lines to your text add them literally to the string you return,
  normally by using "\n" in your PHP code.
- Image Alt or Title: to alleviate the need to enable the PHP filter module, 2
  commonly used sources for dynamic texts are directly available without any
  coding: the alt and title properties of an image field linked to the image at
  hand.

Notes:
- When using token replacement or the image alt or title, multiple image fields,
  possibly in different languages, may be referring to the image that is being
  processed. This module will take the first image field it finds to extract the
  alt and title. If the field in itself is multi-lingual, thus not a synced
  field, the current language will be taken, which is the language of the user
  that happens to request this image derivative first.
- This module will not automatically break text based on available space.
- Due to the way that GD text box positioning works it is quite difficult to
  correctly position multiple lines of text with GD. If you have a working
  solution please post a patch. (Probably involves exploding the text in
  separate lines and then positioning each line separately.)


PHP snippets to determine the text
----------------------------------
Given the correct permission, you can write your own PHP snippet to compute the
text to display. To ease this task, this module makes some information regarding
the image being processed available in a number of variables: $image,
$image_context, $image_style, and $image_effect_id. These variables are readily
available in your snippet.

$image is an object containing the following properties:
- source: string, the source of the image, e.g. public://photo.jpg
- info: array, example data:
   - width (int) 180
   - height  (int) 180
   - extension (string) png
   - mime_type (string) image/png
   - file_size (int) 4417
- toolkit: string, imagemagick or GD

$image_context is an associative array containing:
- effect_data: array, the data of this image effect, example data for the text
  effect:
   - size  (string) 12
   - xpos  (string) center
   - ypos  (string) center
   - halign  (string) left
   - valign  (string) bottom
   - RGB Array [1]
      - HEX (string) 000000
      - alpha (string) 100
   - angle (string) 0
   - fontfile  (string:46) module://image_effects_text/Komika_display.ttf
   - text_source   (string) text
   - text  (string) Hello World!
   - php  (string) return 'Hello World!'
- managed_file: object|null. A managed file object containing these properties:
   - fid (string) 2
   - uid (string) 1
   - filename  (string) photo.jpg
   - uri (string) public://photo.jpg
   - filemime  (string) image/jpeg
   - filesize  (string) 445751
   - status  (string) 1
   - timestamp (string) 1327525851
   - metatags  Array [0]
   - rdf_mapping Array [0]
- referring_entities: array|null. A nested array with (fully loaded) entities
  referring to the current image. The 1st level of entries is keyed by the field
  name, the 2nd by entity type, and the 3rd by entity id. Example data:
   - field_photo Array [1]
      - node  Array [1]
         - 12  Object of: stdClass
            - nid (string) 12
            - vid (string) 12
            - type  (string) page
            - author ...
            - timestamp ...
            - ...
- entity: object|null, the 1st entity in referring_entities. This is for easy
  access to the referring entity if it may be assumed that only 1 entity is
  referring to the current image.
- image_field: array|null, the 1st image field in entity that is referring to
  the current image. This is for easy access to the image field data if it may
  be assumed that only 1 image field is referring to the current image. Example
  data:
   - fid (int) 2
   - alt (string) ...
   - title (string) ...
   - ...

$image_style is an associative array containing the current image style being
processed. It ocntians a.o.:
- isid: the unique image style id
- name: machine name.
- label: Human readable name.
- effects: An array with the effects of this image style, ordered in the way
  they should be applied.

$image_effect_id is an int containng the unique id of the current image effect
being applied. This can be used to look the current image effect up in the
$image_style array.

Of course there are many other possible useful globals. Think of:
- base_url
- base_path
- base_root
- is_https
- user
- language
and of course $_SERVER and $_GET.

Using these information you can access entity data as follows:

Specific case (1 entity, of known entity_type, referring to the image):
<?php
if (!$image_context['entity']) {
  return 'No referring entity';
}
$entity_type = 'node';
$field_name = 'my_field';
$entity = $image_context['entity'];
$field = field_get_items($entity_type, $entity, $field_name);
if ($field) {
  return isset($field[0]['value']) ? $field[0]['value'] : 'No field value';
}
?>

Or the more general case (not knowing the referring type, or multiple entities
that may be referring to the image):
<?php
if (!$image_context['referring_entities']) {
  return 'No referring entities';
}
$referring_entities = $image_context['referring_entities'];
foreach ($referring_entities as $field_name => $field_referring_entities) {
  foreach ($field_referring_entities as $entity_type => $entities) {
    foreach ($entities as $entity_id => $entity) {
      $field = field_get_items($entity_type, $entity, $field_name);
      // ...
    }
  }
}
?>

TODO
----
- Vertical alignment: add baseline as vertical alignment and make both toolkits
  behave the same for any given vertical alignment.
- Rotation and alignment. Imagemagick seems to be more correct. Can GD made to
  do the same?
- Language and alt/title: what if the first user to pass by and that generates
  the image is in a language that has no alt/title?
- Check for existence of imagettftext() and fail properly.

To quote http://www.imagemagick.org/Usage/text/#draw:
As of IM version 6.2.4, the "-draw text" operation no longer understands the use
of '\n' as meaning newline, or the use of percent '%' image information escapes.
(See Drawing a Percent Bug). These abilities, and problems, however remain
available in the new IM v6 operator "-annotate". See the Annotate Text Drawing
Operator below.

File

image_effects_text/README.txt
View source
  1. README
  2. ------
  3. README for the Image effect text module.
  4. Author Erwin Derksen (fietserwin: https://drupal.org/user/750928)
  5. Dependencies
  6. ------------
  7. Hard dependencies:
  8. - Imagecache actions.
  9. - Image (Drupal core).
  10. Soft dependencies/recommended modules:
  11. - Imagemagick (preferred toolkit, https://drupal.org/project/imagemagick).
  12. - PHP filter (Drupal core, if yuo want to use PHP to create the text to render).
  13. - System stream wrapper (https://drupal.org/project/system_stream_wrapper)
  14. - Remote stream wrapper (https://drupal.org/project/remote_stream_wrapper)
  15. The latter 2 provide additional stream wrappers. Especially the system stream
  16. wrapper is very handy as it provides, among others, a module:// and theme://
  17. wrapper.
  18. Toolkit
  19. -------
  20. Personally, I prefer the imagemagick toolkit:
  21. - It is better in anti-aliasing, try to rotate an image using both toolkits and
  22. you will see what I mean.
  23. - It does not execute in the PHP memory space, so is not restricted by the
  24. memory_limit PHP setting.
  25. - The GD toolkit will, at least on my Windows configuration, keep the font file
  26. open after a text operation, so you cannot delete, move or rename it anymore.
  27. - This module does a better job with Imagemagick (see below).
  28. Installing
  29. ----------
  30. As usual. After enabling the module you can add texts to images. This image
  31. effect works with both the GD and imagemagick toolkit, though results differ
  32. depending on the toolkit you use.
  33. More information about the effect data options
  34. ----------------------------------------------
  35. Font
  36. ----
  37. This module comes with some free fonts so you can easily test this effect.
  38. Please read their respective licences.
  39. For real use, you normally want to use your own font as dictated by the website
  40. design. The font types supported depend on the toolkit in use, but at least ttf
  41. files will always work. This option accepts either:
  42. - 1 of the (enabled) scheme's:
  43. * public://
  44. * private:// Preferred for site specific masks, overlays, etc, that do not
  45. need to be shared publicly.
  46. * temporary:// Unlikely to be useful, but supported anyway as all schemes are
  47. supported.
  48. * module:// Introduced by the system stream wrapper module and preferred for
  49. module provided resources.
  50. * theme:// idem.
  51. * profile:// idem.
  52. * library:// idem.
  53. - A relative path (relative to the current directory, probably Drupal root).
  54. - An absolute path.
  55. - A system or toolkit font specification. E.g. on my Windows system 'arial.ttf'
  56. worked with both GD and Imagemagick. A warning will be issued but that may be
  57. ignored when it works as expected.
  58. Text position
  59. -------------
  60. The text position defines the point in the image where you want to place (align)
  61. your text. It starts at the top left corner of the image with position 0,0 and
  62. the positive directions are to the right and down.
  63. The definition of the vertical position differs per toolkit. For GD it is the
  64. position of the font baseline, while for Imagemagick it is the bottom of the
  65. bounding box, i.e the descender or beard line in typography terminology.
  66. Text alignment
  67. --------------
  68. You can align your text with regard to the text position. Possible horizontal
  69. alignments are left (default), center and right. Vertical alignments are top,
  70. center and bottom (default).
  71. Note: Given
  72. - the way that GD uses the vertical text position (as baseline),
  73. - and the way this module implements (vertical) alignment (translating the
  74. (vertical) position using the calculated bounding box),
  75. vertical alignment with the GD toolkit is a bit off. You will have to compensate
  76. for this yourself.
  77. Rotation
  78. --------
  79. The text can be rotated before being overlaid on the image. The value is in
  80. degrees. Positive values are rotated clockwise, So 90 degrees is straight down.
  81. negative values counter clockwise.
  82. In Imagemagick the text is rotated around the text position. Thus centered text
  83. is rotated around its own center. GD, on the other hand, always rotates around
  84. the left bottom (baseline) position, regardless the text alignment. So using
  85. rotation with a non default alignment (left bottom) will give surprising
  86. results.
  87. Text source
  88. -----------
  89. The text to place on the image may come from different sources:
  90. - Text (with token replacement): the text to place on the image has to be
  91. entered on the image effect form. Use this e.g. for a copyright notice.
  92. notes:
  93. * Token replacement: you can use all global tokens, the file tokens, and
  94. tokens from entities referring to the image via an image field. Example: if
  95. you know that the image style is only used for article nodes, you can use
  96. [node:field-image:alt] to get the alt text of the image. Note: this specific
  97. example requires the entity_token module.
  98. * New lines: you can add a new line by adding \n to your text. To get a
  99. literal \n, use \\n.
  100. - PHP: the text to place on the image comes from a piece of PHP code that should
  101. return the text to place on the image. Only users with the 'use PHP for
  102. settings' permission are allowed to use this source. This permission and the
  103. evaluation of the PHP code come from the PHP filter module which is part of
  104. Drupal core and thus needs to be enabled, also during image generation.
  105. To add new lines to your text add them literally to the string you return,
  106. normally by using "\n" in your PHP code.
  107. - Image Alt or Title: to alleviate the need to enable the PHP filter module, 2
  108. commonly used sources for dynamic texts are directly available without any
  109. coding: the alt and title properties of an image field linked to the image at
  110. hand.
  111. Notes:
  112. - When using token replacement or the image alt or title, multiple image fields,
  113. possibly in different languages, may be referring to the image that is being
  114. processed. This module will take the first image field it finds to extract the
  115. alt and title. If the field in itself is multi-lingual, thus not a synced
  116. field, the current language will be taken, which is the language of the user
  117. that happens to request this image derivative first.
  118. - This module will not automatically break text based on available space.
  119. - Due to the way that GD text box positioning works it is quite difficult to
  120. correctly position multiple lines of text with GD. If you have a working
  121. solution please post a patch. (Probably involves exploding the text in
  122. separate lines and then positioning each line separately.)
  123. PHP snippets to determine the text
  124. ----------------------------------
  125. Given the correct permission, you can write your own PHP snippet to compute the
  126. text to display. To ease this task, this module makes some information regarding
  127. the image being processed available in a number of variables: $image,
  128. $image_context, $image_style, and $image_effect_id. These variables are readily
  129. available in your snippet.
  130. $image is an object containing the following properties:
  131. - source: string, the source of the image, e.g. public://photo.jpg
  132. - info: array, example data:
  133. - width (int) 180
  134. - height (int) 180
  135. - extension (string) png
  136. - mime_type (string) image/png
  137. - file_size (int) 4417
  138. - toolkit: string, imagemagick or GD
  139. $image_context is an associative array containing:
  140. - effect_data: array, the data of this image effect, example data for the text
  141. effect:
  142. - size (string) 12
  143. - xpos (string) center
  144. - ypos (string) center
  145. - halign (string) left
  146. - valign (string) bottom
  147. - RGB Array [1]
  148. - HEX (string) 000000
  149. - alpha (string) 100
  150. - angle (string) 0
  151. - fontfile (string:46) module://image_effects_text/Komika_display.ttf
  152. - text_source (string) text
  153. - text (string) Hello World!
  154. - php (string) return 'Hello World!'
  155. - managed_file: object|null. A managed file object containing these properties:
  156. - fid (string) 2
  157. - uid (string) 1
  158. - filename (string) photo.jpg
  159. - uri (string) public://photo.jpg
  160. - filemime (string) image/jpeg
  161. - filesize (string) 445751
  162. - status (string) 1
  163. - timestamp (string) 1327525851
  164. - metatags Array [0]
  165. - rdf_mapping Array [0]
  166. - referring_entities: array|null. A nested array with (fully loaded) entities
  167. referring to the current image. The 1st level of entries is keyed by the field
  168. name, the 2nd by entity type, and the 3rd by entity id. Example data:
  169. - field_photo Array [1]
  170. - node Array [1]
  171. - 12 Object of: stdClass
  172. - nid (string) 12
  173. - vid (string) 12
  174. - type (string) page
  175. - author ...
  176. - timestamp ...
  177. - ...
  178. - entity: object|null, the 1st entity in referring_entities. This is for easy
  179. access to the referring entity if it may be assumed that only 1 entity is
  180. referring to the current image.
  181. - image_field: array|null, the 1st image field in entity that is referring to
  182. the current image. This is for easy access to the image field data if it may
  183. be assumed that only 1 image field is referring to the current image. Example
  184. data:
  185. - fid (int) 2
  186. - alt (string) ...
  187. - title (string) ...
  188. - ...
  189. $image_style is an associative array containing the current image style being
  190. processed. It ocntians a.o.:
  191. - isid: the unique image style id
  192. - name: machine name.
  193. - label: Human readable name.
  194. - effects: An array with the effects of this image style, ordered in the way
  195. they should be applied.
  196. $image_effect_id is an int containng the unique id of the current image effect
  197. being applied. This can be used to look the current image effect up in the
  198. $image_style array.
  199. Of course there are many other possible useful globals. Think of:
  200. - base_url
  201. - base_path
  202. - base_root
  203. - is_https
  204. - user
  205. - language
  206. and of course $_SERVER and $_GET.
  207. Using these information you can access entity data as follows:
  208. Specific case (1 entity, of known entity_type, referring to the image):
  209. if (!$image_context['entity']) {
  210. return 'No referring entity';
  211. }
  212. $entity_type = 'node';
  213. $field_name = 'my_field';
  214. $entity = $image_context['entity'];
  215. $field = field_get_items($entity_type, $entity, $field_name);
  216. if ($field) {
  217. return isset($field[0]['value']) ? $field[0]['value'] : 'No field value';
  218. }
  219. ?>
  220. Or the more general case (not knowing the referring type, or multiple entities
  221. that may be referring to the image):
  222. if (!$image_context['referring_entities']) {
  223. return 'No referring entities';
  224. }
  225. $referring_entities = $image_context['referring_entities'];
  226. foreach ($referring_entities as $field_name => $field_referring_entities) {
  227. foreach ($field_referring_entities as $entity_type => $entities) {
  228. foreach ($entities as $entity_id => $entity) {
  229. $field = field_get_items($entity_type, $entity, $field_name);
  230. // ...
  231. }
  232. }
  233. }
  234. ?>
  235. TODO
  236. ----
  237. - Vertical alignment: add baseline as vertical alignment and make both toolkits
  238. behave the same for any given vertical alignment.
  239. - Rotation and alignment. Imagemagick seems to be more correct. Can GD made to
  240. do the same?
  241. - Language and alt/title: what if the first user to pass by and that generates
  242. the image is in a language that has no alt/title?
  243. - Check for existence of imagettftext() and fail properly.
  244. To quote http://www.imagemagick.org/Usage/text/#draw:
  245. As of IM version 6.2.4, the "-draw text" operation no longer understands the use
  246. of '\n' as meaning newline, or the use of percent '%' image information escapes.
  247. (See Drawing a Percent Bug). These abilities, and problems, however remain
  248. available in the new IM v6 operator "-annotate". See the Annotate Text Drawing
  249. Operator below.