swfPic.ml 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. (*
  2. * This file is part of SwfLib
  3. * Copyright (c)2005 Nicolas Cannasse
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  18. *)
  19. open Png
  20. open Swf
  21. open ExtList
  22. type error_msg =
  23. | PngError of Png.error_msg
  24. | Interlaced
  25. | UnsupportedColorModel
  26. | UnsupportedExtension
  27. | UnzipFailed
  28. exception Error of error_msg
  29. exception File_not_found of string
  30. type picture = {
  31. pwidth : int;
  32. pheight : int;
  33. pid : int;
  34. pdata : tag_data;
  35. pframe : string option;
  36. }
  37. let error_msg = function
  38. | PngError m -> Png.error_msg m
  39. | Interlaced -> "Interlaced mode is not supported"
  40. | UnsupportedColorModel -> "Unsupported color model"
  41. | UnsupportedExtension -> "Unsupported file extension"
  42. | UnzipFailed -> "Decompression failed"
  43. let error msg = raise (Error msg)
  44. let unsigned v n =
  45. if v < 0 then
  46. (- ( v + 1 )) lxor (1 lsl n - 1)
  47. else
  48. v
  49. let load_picture file id =
  50. let ch = IO.input_channel (try open_in_bin file with _ -> raise (File_not_found file)) in
  51. let len = String.length file in
  52. let p = (try String.rindex file '.' with Not_found -> len) in
  53. let ext = String.sub file (p + 1) (len - (p + 1)) in
  54. match String.uppercase ext with
  55. | "PNG" ->
  56. let png , header, data = (try
  57. let p = Png.parse ch in
  58. p , Png.header p, Png.data p
  59. with Png.Error msg ->
  60. IO.close_in ch; error (PngError msg)
  61. ) in
  62. IO.close_in ch;
  63. if header.png_interlace then error Interlaced;
  64. let data = (try Extc.unzip data with _ -> error UnzipFailed) in
  65. let w = header.png_width in
  66. let h = header.png_height in
  67. let data = (try Png.filter png data with Png.Error msg -> error (PngError msg)) in
  68. let data = Bytes.unsafe_of_string data in
  69. {
  70. pwidth = w;
  71. pheight = h;
  72. pid = id;
  73. pframe = None;
  74. pdata = (match header.png_color with
  75. | ClTrueColor (TBits8,NoAlpha) ->
  76. (* set alpha to 0 *)
  77. for p = 0 to w * h - 1 do
  78. Bytes.unsafe_set data (p * 4) '\000';
  79. done;
  80. TBitsLossless {
  81. bll_id = id;
  82. bll_format = 5;
  83. bll_width = w;
  84. bll_height = h;
  85. bll_data = Extc.zip (Bytes.unsafe_to_string data);
  86. }
  87. | ClTrueColor (TBits8,HaveAlpha) ->
  88. (* premultiply rgb by alpha *)
  89. for p = 0 to w * h - 1 do
  90. let k = p * 4 in
  91. let a = int_of_char (Bytes.unsafe_get data k) in
  92. Bytes.unsafe_set data (k + 1) (Char.unsafe_chr ((int_of_char (Bytes.unsafe_get data (k + 1)) * a) / 0xFF));
  93. Bytes.unsafe_set data (k + 2) (Char.unsafe_chr ((int_of_char (Bytes.unsafe_get data (k + 2)) * a) / 0xFF));
  94. Bytes.unsafe_set data (k + 3) (Char.unsafe_chr ((int_of_char (Bytes.unsafe_get data (k + 3)) * a) / 0xFF));
  95. done;
  96. TBitsLossless2 {
  97. bll_id = id;
  98. bll_format = 5;
  99. bll_width = w;
  100. bll_height = h;
  101. bll_data = Extc.zip (Bytes.unsafe_to_string data);
  102. }
  103. | _ -> error UnsupportedColorModel);
  104. }
  105. | _ ->
  106. IO.close_in ch;
  107. error UnsupportedExtension
  108. let make_clip name pics baseid =
  109. let npics = List.length pics in
  110. let ids = Array.of_list (List.map (fun p -> p.pid) pics) in
  111. let rec loop i p =
  112. let w = p.pwidth in
  113. let h = p.pheight in
  114. let rb = if 20 * max w h >= 1 lsl 14 then 15 else 14 in
  115. let nbits = rb in
  116. TShape {
  117. sh_id = baseid + i;
  118. sh_bounds = {
  119. rect_nbits = rb;
  120. left = 0;
  121. top = 0;
  122. right = w * 20;
  123. bottom = h * 20;
  124. };
  125. sh_bounds2 = None;
  126. sh_style = {
  127. sws_fill_styles = [
  128. SFSBitmap {
  129. sfb_repeat = true;
  130. sfb_smooth = true;
  131. sfb_cid = ids.(i);
  132. sfb_mpos = {
  133. scale = Some {
  134. m_nbits = 22;
  135. mx = 20 lsl 16;
  136. my = 20 lsl 16;
  137. };
  138. rotate = None;
  139. trans = {
  140. m_nbits = 0;
  141. mx = 0;
  142. my = 0;
  143. };
  144. };
  145. };
  146. ];
  147. sws_line_styles = [];
  148. sws_records = {
  149. srs_nlbits = 0;
  150. srs_nfbits = 1;
  151. srs_records = [
  152. SRStyleChange {
  153. scsr_move = None;
  154. scsr_fs0 = None;
  155. scsr_fs1 = Some 1;
  156. scsr_ls = None;
  157. scsr_new_styles = None;
  158. };
  159. SRStraightEdge {
  160. sser_nbits = nbits;
  161. sser_line = Some (w * 20) , None;
  162. };
  163. SRStraightEdge {
  164. sser_nbits = nbits;
  165. sser_line = None , Some (h * 20);
  166. };
  167. SRStraightEdge {
  168. sser_nbits = nbits;
  169. sser_line = Some (unsigned (-w * 20) nbits), None;
  170. };
  171. SRStraightEdge {
  172. sser_nbits = nbits;
  173. sser_line = None , Some (unsigned (-h * 20) nbits);
  174. };
  175. ];
  176. };
  177. };
  178. }
  179. in
  180. let shapes = List.mapi loop pics in
  181. let rec loop i =
  182. if i = npics then
  183. []
  184. else
  185. TPlaceObject2 {
  186. po_depth = 0;
  187. po_move = (i > 0);
  188. po_cid = Some (baseid+i);
  189. po_color = None;
  190. po_matrix = None;
  191. po_ratio = None;
  192. po_inst_name = None;
  193. po_clip_depth = None;
  194. po_events = None;
  195. po_filters = None;
  196. po_blend = None;
  197. po_bcache = None;
  198. } :: TShowFrame :: loop (i+1)
  199. in
  200. let tid = ref 0 in
  201. let make_tag t =
  202. incr tid;
  203. {
  204. tid = - !tid;
  205. textended = false;
  206. tdata = t;
  207. }
  208. in
  209. let pics = List.map (fun p -> make_tag p.pdata) pics in
  210. let shapes = List.map make_tag shapes in
  211. pics @ shapes @ List.map make_tag [
  212. TClip {
  213. c_id = baseid + npics;
  214. c_frame_count = npics;
  215. c_tags = List.map make_tag (loop 0);
  216. };
  217. TExport [{
  218. exp_id = baseid + npics;
  219. exp_name = name;
  220. }];
  221. ]