iup_image.e 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. class IUP_IMAGE
  2. -- Creates an image to be shown on a label, button, toggle, or as a
  3. -- cursor.
  4. --
  5. -- Application icons are usually 32x32. Toolbar bitmaps are 24x24 or smaller.
  6. -- Menu bitmaps and small icons are 16x16 or smaller.
  7. --
  8. -- Images created with the procedure "image" can be reused in different
  9. -- elements.
  10. --
  11. -- The images should be destroyed when they are no longer necessary, by means
  12. -- of the "destroy" feature. To destroy an image, it cannot be in use, i.e the
  13. -- controls where it is used should be destroyed first. Images that were
  14. -- associated with controls by names are automatically destroyed in "close".
  15. --
  16. -- Please observe the rules for creating cursor images: CURSOR.
  17. --
  18. -- In all drivers, a path to a file name can also be used as the attribute
  19. -- value. But the available file formats supported are system dependent. The
  20. -- Windows driver supports BMP, ICO and CUR. The GTK driver supports the
  21. -- formats supported by the GDK-PixBuf library, such as BMP, GIF, JPEG, PCX,
  22. -- PNG, TIFF and many others. The Motif driver supports the X-Windows
  23. -- bitmap.
  24. --
  25. -- For the procedure creation "image", if a color is not set (with
  26. -- "set_color_at_index"), then it is used a default color for the 16 first
  27. -- colors. The default color table is the same for Windows, GTK and Motif:
  28. --
  29. -- 0 = 0, 0, 0 (black)
  30. -- 1 = 128, 0, 0 (dark red)
  31. -- 2 = 0,128, 0 (dark green)
  32. -- 3 = 128,128, 0 (dark yellow)
  33. -- 4 = 0, 0,128 (dark blue)
  34. -- 5 = 128, 0,128 (dark magenta)
  35. -- 6 = 0,128,128 (dark cian)
  36. -- 7 = 192,192,192 (gray)
  37. -- 8 = 128,128,128 (dark gray)
  38. -- 9 = 255, 0, 0 (red)
  39. -- 10 = 0,255, 0 (green)
  40. -- 11 = 255,255, 0 (yellow)
  41. -- 12 = 0, 0,255 (blue)
  42. -- 13 = 255, 0,255 (magenta)
  43. -- 14 = 0,255,255 (cian)
  44. -- 15 = 255,255,255 (white)
  45. --
  46. -- For images with more than 16 colors, and up to 256 colors, all the color
  47. -- indices must be defined up to the maximum number of colors. For example, if
  48. -- the biggest image index is 100, then all the colors from i=16 up to i=100
  49. -- must be defined even if some indices are not used.
  50. inherit
  51. IUP_WIDGET
  52. IUP_WIDGET_INTERNALS
  53. IUP_WIDGET_BGCOLOR
  54. create {ANY}
  55. image,
  56. image_rgb,
  57. image_rgba,
  58. load
  59. create {CD_CLIENT_IMAGES}
  60. with_internal
  61. feature {ANY}
  62. image (a_width, a_height: INTEGER; a_pixels: ARRAY[INTEGER])
  63. -- pixels: Array containing the value of each pixel, 1 value per pixel.
  64. -- Origin is at the top-left corner and data is oriented top to bottom,
  65. -- and left to right.
  66. require
  67. a_width_not_negative: a_width >= 0
  68. a_height_not_negative: a_height >= 0
  69. a_values_not_void: a_pixels /= Void
  70. consistent_size: a_width * a_height = a_pixels.count
  71. local
  72. a_image: POINTER
  73. do
  74. a_image := int_image(a_width, a_height, convert_array(a_pixels))
  75. if a_image /= default_pointer then
  76. set_widget(a_image)
  77. end
  78. end
  79. image_rgb (a_width, a_height: INTEGER; a_pixels: ARRAY[TUPLE[INTEGER, INTEGER, INTEGER]])
  80. -- pixels: Array containing the value of each pixel, 3 values per pixel.
  81. -- Origin is at the top-left corner and data is oriented top to bottom,
  82. -- and left to right.
  83. require
  84. a_width_not_negative: a_width >= 0
  85. a_height_not_negative: a_height >= 0
  86. a_values_not_void: a_pixels /= Void
  87. consistent_size: a_width * a_height = a_pixels.count
  88. local
  89. a_image: POINTER
  90. do
  91. a_image := int_image_rgb(a_width, a_height,
  92. convert_rgb_array(a_pixels))
  93. if a_image /= default_pointer then
  94. set_widget(a_image)
  95. end
  96. end
  97. image_rgba (a_width, a_height: INTEGER; a_pixels: ARRAY[TUPLE[INTEGER, INTEGER, INTEGER, INTEGER]])
  98. -- pixels: Array containing the value of each pixel, 4 values per pixel.
  99. -- Origin is at the top-left corner and data is oriented top to bottom,
  100. -- and left to right.
  101. require
  102. a_width_not_negative: a_width >= 0
  103. a_height_not_negative: a_height >= 0
  104. a_values_not_void: a_pixels /= Void
  105. consistent_size: a_width * a_height = a_pixels.count
  106. local
  107. a_image: POINTER
  108. do
  109. a_image := int_image_rgba(a_width, a_height,
  110. convert_rgba_array(a_pixels))
  111. if a_image /= default_pointer then
  112. set_widget(a_image)
  113. end
  114. end
  115. load (file_name: STRING)
  116. -- An image loaded from a file. Supported formats: BMP, JPEG, GIF, TIFF,
  117. -- PNG, PNM, PCX, ICO and others.
  118. local
  119. a_image: POINTER
  120. do
  121. a_image := int_load(get_pointer(file_name.to_c))
  122. if a_image /= default_pointer then
  123. set_widget(a_image)
  124. end
  125. end
  126. was_created: BOOLEAN
  127. -- Return "True" if no error when create the image. Useful to
  128. -- be used when an image is created with "load".
  129. do
  130. if widget /= default_pointer then
  131. Result := True
  132. else
  133. Result := False
  134. end
  135. end
  136. get_error: STRING
  137. -- Return: NO_ERROR if success, otherwise return the error reported
  138. -- by the system. Useful to get the error if there is one
  139. -- when create an image with "load".
  140. do
  141. if widget /= default_pointer then
  142. Result := "NO_ERROR"
  143. else
  144. Result := iup_open.get_global_attribute("IUPIM_LASTERROR")
  145. end
  146. end
  147. -- Operations
  148. save (file_name, format: STRING): STRING
  149. -- Save the image.
  150. -- file_name: Name of the file to be saved.
  151. -- format: format descriptor for IM (the library IM used internally). For
  152. -- ex: "BMP", "JPEG", "GIF", "TIFF", "PNG", "PNM", "PCX", "ICO", etc.
  153. -- Return: NO_ERROR if success, otherwise return the error reported
  154. -- by the system.
  155. local
  156. i: INTEGER
  157. do
  158. i := int_save(widget, get_pointer(file_name.to_c), get_pointer(format.to_c))
  159. if not i.is_equal(0) then
  160. Result := "NO_ERROR"
  161. else
  162. Result := iup_open.get_global_attribute("IUPIM_LASTERROR")
  163. end
  164. end
  165. -- Attributes
  166. set_color_at_index (rgb: STRING; index: INTEGER)
  167. -- The indices can range from 0 to 255. The total number of colors is
  168. -- limited to 256 colors. Be careful when setting colors, since they are
  169. -- attributes they follow the same storage rules for standard attributes.
  170. --
  171. -- The values are integer numbers from 0 to 255, one for each color in
  172. -- the RGB triple (For ex: "64 190 255"). If the value of a given index
  173. -- is "BGCOLOR", the color used will be the background color of the
  174. -- element on which the image will be inserted. The "BGCOLOR" value must
  175. -- be defined within an index less than 16.
  176. --
  177. -- Used only for images created "image".
  178. require
  179. index >= 0
  180. index <= 255
  181. is_valid_rgb_string(rgb)
  182. do
  183. iup_open.set_attribute(Current, index.out, rgb)
  184. end
  185. set_auto_scale (value: REAL_32)
  186. -- Automatically scale the image by a given real factor. If not defined
  187. -- the global attribute IMAGEAUTOSCALE will be used. Values are the same
  188. -- of the global attribute.
  189. do
  190. iup_open.set_attribute(Current, "AUTOSCALE", value.out)
  191. end
  192. get_bpp: INTEGER
  193. -- Returns the number of bits per pixel in the image. Images created
  194. -- with "image" returns 8, with "image_rgb" returns 24 and with
  195. -- "image_rgba" returns 32.
  196. local
  197. str: STRING
  198. do
  199. str := iup_open.get_attribute(Current, "BPP")
  200. if str.is_integer then
  201. Result := str.to_integer
  202. end
  203. end
  204. -- Skip CLEARCACHE
  205. get_channels: INTEGER
  206. -- Returns the number of channels in the image. Images created with
  207. -- "image" returns 1, with "image_rgb" returns 3 and with
  208. -- "image_rgba" returns 4.
  209. local
  210. str: STRING
  211. do
  212. str := iup_open.get_attribute(Current, "CHANNELS")
  213. if str.is_integer then
  214. Result := str.to_integer
  215. end
  216. end
  217. get_height: INTEGER
  218. -- Image height in pixels.
  219. local
  220. str: STRING
  221. do
  222. str := iup_open.get_attribute(Current, "HEIGHT")
  223. if str.is_integer then
  224. Result := str.to_integer
  225. end
  226. end
  227. set_hot_spot (x, y: INTEGER)
  228. -- Hotspot is the position inside a cursor image indicating the
  229. -- mouse-click spot. Its value is given by the x and y coordinates inside
  230. -- a cursor image. Default: "0:0".
  231. require
  232. x >= 0
  233. y >= 0
  234. local
  235. v: STRING
  236. do
  237. v := x.out
  238. v.append_string(":")
  239. v.append_string(y.out)
  240. iup_open.set_attribute(Current, "HOTSPOT", v)
  241. end
  242. get_rastersize: TUPLE[INTEGER, INTEGER]
  243. -- Returns the Current size, in pixels.
  244. local
  245. size: STRING
  246. do
  247. size := iup_open.get_attribute(Current, "RASTERSIZE")
  248. Result := components_of_size(size)
  249. end
  250. -- Skip RESHAPE
  251. resize_to (width, height: INTEGER)
  252. -- Given a new size changes WIDTH and HEIGHT attributes, and resizes the
  253. -- image contents using bilinear interpolation. Works only for RGB and
  254. -- RGBA images.
  255. require
  256. width > 0
  257. height > 0
  258. local
  259. v: STRING
  260. do
  261. v := width.out
  262. v.append_string("x")
  263. v.append_string(height.out)
  264. iup_open.set_attribute(Current, "RESIZE", v)
  265. end
  266. get_width: INTEGER
  267. -- Image width in pixels.
  268. local
  269. str: STRING
  270. do
  271. str := iup_open.get_attribute(Current, "WIDTH")
  272. if str.is_integer then
  273. Result := str.to_integer
  274. end
  275. end
  276. feature {CD_CLIENT_IMAGES}
  277. with_internal (a_image: POINTER)
  278. do
  279. set_widget(a_image)
  280. end
  281. get_wid: POINTER
  282. -- Returns the internal pixels data pointer.
  283. do
  284. Result := int_get_attribute(widget, get_pointer(("WID").to_c))
  285. end
  286. feature {NONE}
  287. -- Internals
  288. int_image (width, height: INTEGER; pixels: POINTER): POINTER
  289. external
  290. "C inline use %"eiffel-iup.h%""
  291. alias
  292. "return IupImage ($width, $height, $pixels);"
  293. end
  294. int_image_rgb (width, height: INTEGER; pixels: POINTER): POINTER
  295. external
  296. "C inline use %"eiffel-iup.h%""
  297. alias
  298. "return IupImageRGB ($width, $height, $pixels);"
  299. end
  300. int_image_rgba (width, height: INTEGER; pixels: POINTER): POINTER
  301. external
  302. "C inline use %"eiffel-iup.h%""
  303. alias
  304. "return IupImageRGBA ($width, $height, $pixels);"
  305. end
  306. int_load(file_name: POINTER): POINTER
  307. external
  308. "C inline use %"eiffel-iup.h%""
  309. alias
  310. "return IupLoadImage ($file_name);"
  311. end
  312. int_save(wgt, file_name, format: POINTER): INTEGER
  313. external
  314. "C inline use %"eiffel-iup.h%""
  315. alias
  316. "return IupSaveImage ($wgt, $file_name, $format);"
  317. end
  318. int_get_attribute (wgt, name: POINTER): POINTER
  319. external
  320. "C inline use %"eiffel-iup.h%""
  321. alias
  322. "return IupGetAttribute ($wgt, $name);"
  323. end
  324. -- Conversion
  325. convert_array (matrix: ARRAY[INTEGER]): POINTER
  326. local
  327. i, v: INTEGER;
  328. arg: ARRAY[CHARACTER_8]
  329. do
  330. create arg.make_filled(' ', 1, matrix.count + 1)
  331. i := 0
  332. across
  333. matrix as ic
  334. loop
  335. i := i + 1
  336. v := ic.item
  337. arg.put(v.to_character_8, i)
  338. end
  339. Result := get_pointer(arg.to_c)
  340. end
  341. convert_rgb_array (matrix: ARRAY[TUPLE[INTEGER, INTEGER, INTEGER]]): POINTER
  342. local
  343. i: INTEGER;
  344. arg: ARRAY[CHARACTER_8]
  345. v: TUPLE[INTEGER, INTEGER, INTEGER]
  346. do
  347. create arg.make_filled(' ', 1, matrix.count + 1)
  348. i := 0
  349. across
  350. matrix as ic
  351. loop
  352. i := i + 1
  353. v := ic.item
  354. arg.put(v.integer_32_item(1).to_character_8, i)
  355. i := i + 1
  356. arg.put(v.integer_32_item(2).to_character_8, i)
  357. i := i + 1
  358. arg.put(v.integer_32_item(3).to_character_8, i)
  359. end
  360. Result := get_pointer(arg.to_c)
  361. end
  362. convert_rgba_array (matrix: ARRAY[TUPLE[INTEGER, INTEGER, INTEGER, INTEGER]]): POINTER
  363. local
  364. i: INTEGER;
  365. arg: ARRAY[CHARACTER_8]
  366. v: TUPLE[INTEGER, INTEGER, INTEGER, INTEGER]
  367. do
  368. create arg.make_filled(' ', 1, matrix.count + 1)
  369. i := 0
  370. across
  371. matrix as ic
  372. loop
  373. i := i + 1
  374. v := ic.item
  375. arg.put(v.integer_32_item(1).to_character_8, i)
  376. i := i + 1
  377. arg.put(v.integer_32_item(2).to_character_8, i)
  378. i := i + 1
  379. arg.put(v.integer_32_item(3).to_character_8, i)
  380. i := i + 1
  381. arg.put(v.integer_32_item(4).to_character_8, i)
  382. end
  383. Result := get_pointer(arg.to_c)
  384. end
  385. end
  386. -- The MIT License (MIT)
  387. -- Copyright (c) 2016, 2018, 2019, 2020 by German A. Arias
  388. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  389. -- of this software and associated documentation files (the "Software"), to deal
  390. -- in the Software without restriction, including without limitation the rights
  391. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  392. -- copies of the Software, and to permit persons to whom the Software is
  393. -- furnished to do so, subject to the following conditions:
  394. --
  395. -- The above copyright notice and this permission notice shall be included in
  396. -- all copies or substantial portions of the Software.
  397. --
  398. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  399. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  400. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  401. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  402. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  403. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  404. -- SOFTWARE.