chunky_png 0.10.5 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (245) hide show
  1. data/Gemfile.lock +1 -1
  2. data/benchmarks/filesize_benchmark.rb +1 -1
  3. data/chunky_png.gemspec +4 -4
  4. data/lib/chunky_png.rb +4 -11
  5. data/lib/chunky_png/canvas.rb +7 -8
  6. data/lib/chunky_png/canvas/adam7_interlacing.rb +36 -18
  7. data/lib/chunky_png/canvas/png_decoding.rb +258 -36
  8. data/lib/chunky_png/canvas/png_encoding.rb +1 -1
  9. data/lib/chunky_png/color.rb +41 -5
  10. data/lib/chunky_png/compatibility.rb +15 -0
  11. data/lib/chunky_png/datastream.rb +6 -0
  12. data/spec/chunky_png/canvas/adam7_interlacing_spec.rb +7 -7
  13. data/spec/chunky_png/canvas/png_decoding_spec.rb +33 -20
  14. data/spec/chunky_png/canvas/png_encoding_spec.rb +2 -3
  15. data/spec/chunky_png/color_spec.rb +29 -0
  16. data/spec/chunky_png/datastream_spec.rb +0 -5
  17. data/spec/chunky_png/rmagick_spec.rb +3 -3
  18. data/spec/png_suite/background_chunks/bgai4a08.png +0 -0
  19. data/spec/png_suite/background_chunks/bgai4a16.png +0 -0
  20. data/spec/png_suite/background_chunks/bgan6a08.png +0 -0
  21. data/spec/png_suite/background_chunks/bgan6a16.png +0 -0
  22. data/spec/png_suite/background_chunks/bgbn4a08.png +0 -0
  23. data/spec/png_suite/background_chunks/bggn4a16.png +0 -0
  24. data/spec/png_suite/background_chunks/bgwn6a08.png +0 -0
  25. data/spec/png_suite/background_chunks/bgyn6a16.png +0 -0
  26. data/spec/png_suite/basic/basi0g01.png +0 -0
  27. data/spec/png_suite/basic/basi0g01.rgba +0 -0
  28. data/spec/png_suite/basic/basi0g02.png +0 -0
  29. data/spec/png_suite/basic/basi0g02.rgba +0 -0
  30. data/spec/png_suite/basic/basi0g04.png +0 -0
  31. data/spec/png_suite/basic/basi0g04.rgba +0 -0
  32. data/spec/png_suite/basic/basi0g08.png +0 -0
  33. data/spec/png_suite/basic/basi0g08.rgba +0 -0
  34. data/spec/png_suite/basic/basi0g16.png +0 -0
  35. data/spec/png_suite/basic/basi0g16.rgba +0 -0
  36. data/spec/png_suite/basic/basi2c08.png +0 -0
  37. data/spec/png_suite/basic/basi2c08.rgba +0 -0
  38. data/spec/png_suite/basic/basi2c16.png +0 -0
  39. data/spec/png_suite/basic/basi2c16.rgba +0 -0
  40. data/spec/png_suite/basic/basi3p01.png +0 -0
  41. data/spec/png_suite/basic/basi3p01.rgba +1 -0
  42. data/spec/png_suite/basic/basi3p02.png +0 -0
  43. data/spec/png_suite/basic/basi3p02.rgba +0 -0
  44. data/spec/png_suite/basic/basi3p04.png +0 -0
  45. data/spec/png_suite/basic/basi3p04.rgba +0 -0
  46. data/spec/png_suite/basic/basi3p08.png +0 -0
  47. data/spec/png_suite/basic/basi3p08.rgba +0 -0
  48. data/spec/png_suite/basic/basi4a08.png +0 -0
  49. data/spec/png_suite/basic/basi4a08.rgba +0 -0
  50. data/spec/png_suite/basic/basi4a16.png +0 -0
  51. data/spec/png_suite/basic/basi4a16.rgba +0 -0
  52. data/spec/png_suite/basic/basi6a08.png +0 -0
  53. data/spec/png_suite/basic/basi6a08.rgba +0 -0
  54. data/spec/png_suite/basic/basi6a16.png +0 -0
  55. data/spec/png_suite/basic/basi6a16.rgba +0 -0
  56. data/spec/png_suite/basic/basn0g01.png +0 -0
  57. data/spec/png_suite/basic/basn0g01.rgba +0 -0
  58. data/spec/png_suite/basic/basn0g02.png +0 -0
  59. data/spec/png_suite/basic/basn0g02.rgba +0 -0
  60. data/spec/png_suite/basic/basn0g04.png +0 -0
  61. data/spec/png_suite/basic/basn0g04.rgba +0 -0
  62. data/spec/png_suite/basic/basn0g08.png +0 -0
  63. data/spec/png_suite/basic/basn0g08.rgba +0 -0
  64. data/spec/png_suite/basic/basn0g16.png +0 -0
  65. data/spec/png_suite/basic/basn0g16.rgba +0 -0
  66. data/spec/png_suite/basic/basn2c08.png +0 -0
  67. data/spec/png_suite/basic/basn2c08.rgba +0 -0
  68. data/spec/png_suite/basic/basn2c16.png +0 -0
  69. data/spec/png_suite/basic/basn2c16.rgba +0 -0
  70. data/spec/png_suite/basic/basn3p01.png +0 -0
  71. data/spec/png_suite/basic/basn3p01.rgba +1 -0
  72. data/spec/png_suite/basic/basn3p02.png +0 -0
  73. data/spec/png_suite/basic/basn3p02.rgba +0 -0
  74. data/spec/{resources/indexed_4bit.png → png_suite/basic/basn3p04.png} +0 -0
  75. data/spec/png_suite/basic/basn3p04.rgba +0 -0
  76. data/spec/png_suite/basic/basn3p08.png +0 -0
  77. data/spec/png_suite/basic/basn3p08.rgba +0 -0
  78. data/spec/png_suite/basic/basn4a08.png +0 -0
  79. data/spec/png_suite/basic/basn4a08.rgba +0 -0
  80. data/spec/png_suite/basic/basn4a16.png +0 -0
  81. data/spec/png_suite/basic/basn4a16.rgba +0 -0
  82. data/spec/png_suite/basic/basn6a08.png +0 -0
  83. data/spec/png_suite/basic/basn6a08.rgba +0 -0
  84. data/spec/png_suite/basic/basn6a16.png +0 -0
  85. data/spec/png_suite/basic/basn6a16.rgba +0 -0
  86. data/spec/png_suite/broken/x00n0g01.png +0 -0
  87. data/spec/png_suite/broken/xcrn0g04.png +0 -0
  88. data/spec/png_suite/broken/xlfn0g04.png +13 -0
  89. data/spec/png_suite/chunk_ordering/oi1n0g16.png +0 -0
  90. data/spec/png_suite/chunk_ordering/oi1n2c16.png +0 -0
  91. data/spec/png_suite/chunk_ordering/oi2n0g16.png +0 -0
  92. data/spec/png_suite/chunk_ordering/oi2n2c16.png +0 -0
  93. data/spec/png_suite/chunk_ordering/oi4n0g16.png +0 -0
  94. data/spec/png_suite/chunk_ordering/oi4n2c16.png +0 -0
  95. data/spec/png_suite/chunk_ordering/oi9n0g16.png +0 -0
  96. data/spec/png_suite/chunk_ordering/oi9n2c16.png +0 -0
  97. data/spec/png_suite/compression_levels/z00n2c08.png +0 -0
  98. data/spec/png_suite/compression_levels/z03n2c08.png +0 -0
  99. data/spec/png_suite/compression_levels/z06n2c08.png +0 -0
  100. data/spec/png_suite/compression_levels/z09n2c08.png +0 -0
  101. data/spec/png_suite/filtering/f00n0g08.png +0 -0
  102. data/spec/png_suite/filtering/f00n0g08.rgba +0 -0
  103. data/spec/png_suite/filtering/f00n0g08_reference.png +0 -0
  104. data/spec/png_suite/filtering/f00n0g08_reference.rgba +0 -0
  105. data/spec/png_suite/filtering/f00n2c08.png +0 -0
  106. data/spec/png_suite/filtering/f00n2c08.rgba +0 -0
  107. data/spec/png_suite/filtering/f00n2c08_reference.png +0 -0
  108. data/spec/png_suite/filtering/f00n2c08_reference.rgba +0 -0
  109. data/spec/png_suite/filtering/f01n0g08.png +0 -0
  110. data/spec/png_suite/filtering/f01n0g08.rgba +0 -0
  111. data/spec/png_suite/filtering/f01n0g08_reference.png +0 -0
  112. data/spec/png_suite/filtering/f01n0g08_reference.rgba +0 -0
  113. data/spec/png_suite/filtering/f01n2c08.png +0 -0
  114. data/spec/png_suite/filtering/f01n2c08.rgba +0 -0
  115. data/spec/png_suite/filtering/f01n2c08_reference.png +0 -0
  116. data/spec/png_suite/filtering/f01n2c08_reference.rgba +0 -0
  117. data/spec/png_suite/filtering/f02n0g08.png +0 -0
  118. data/spec/png_suite/filtering/f02n0g08.rgba +0 -0
  119. data/spec/png_suite/filtering/f02n0g08_reference.png +0 -0
  120. data/spec/png_suite/filtering/f02n0g08_reference.rgba +0 -0
  121. data/spec/png_suite/filtering/f02n2c08.png +0 -0
  122. data/spec/png_suite/filtering/f02n2c08.rgba +0 -0
  123. data/spec/png_suite/filtering/f02n2c08_reference.png +0 -0
  124. data/spec/png_suite/filtering/f02n2c08_reference.rgba +0 -0
  125. data/spec/png_suite/filtering/f03n0g08.png +0 -0
  126. data/spec/png_suite/filtering/f03n0g08.rgba +0 -0
  127. data/spec/png_suite/filtering/f03n0g08_reference.png +0 -0
  128. data/spec/png_suite/filtering/f03n0g08_reference.rgba +0 -0
  129. data/spec/png_suite/filtering/f03n2c08.png +0 -0
  130. data/spec/png_suite/filtering/f03n2c08.rgba +0 -0
  131. data/spec/png_suite/filtering/f03n2c08_reference.png +0 -0
  132. data/spec/png_suite/filtering/f03n2c08_reference.rgba +0 -0
  133. data/spec/png_suite/filtering/f04n0g08.png +0 -0
  134. data/spec/png_suite/filtering/f04n0g08.rgba +0 -0
  135. data/spec/png_suite/filtering/f04n0g08_reference.png +0 -0
  136. data/spec/png_suite/filtering/f04n0g08_reference.rgba +0 -0
  137. data/spec/png_suite/filtering/f04n2c08.png +0 -0
  138. data/spec/png_suite/filtering/f04n2c08.rgba +0 -0
  139. data/spec/png_suite/filtering/f04n2c08_reference.png +0 -0
  140. data/spec/png_suite/filtering/f04n2c08_reference.rgba +0 -0
  141. data/spec/png_suite/gamma/g03n0g16.png +0 -0
  142. data/spec/png_suite/gamma/g03n2c08.png +0 -0
  143. data/spec/png_suite/gamma/g03n3p04.png +0 -0
  144. data/spec/png_suite/gamma/g04n0g16.png +0 -0
  145. data/spec/png_suite/gamma/g04n2c08.png +0 -0
  146. data/spec/png_suite/gamma/g04n3p04.png +0 -0
  147. data/spec/png_suite/gamma/g05n0g16.png +0 -0
  148. data/spec/png_suite/gamma/g05n2c08.png +0 -0
  149. data/spec/png_suite/gamma/g05n3p04.png +0 -0
  150. data/spec/png_suite/gamma/g07n0g16.png +0 -0
  151. data/spec/png_suite/gamma/g07n2c08.png +0 -0
  152. data/spec/png_suite/gamma/g07n3p04.png +0 -0
  153. data/spec/png_suite/gamma/g10n0g16.png +0 -0
  154. data/spec/png_suite/gamma/g10n2c08.png +0 -0
  155. data/spec/png_suite/gamma/g10n3p04.png +0 -0
  156. data/spec/png_suite/gamma/g25n0g16.png +0 -0
  157. data/spec/png_suite/gamma/g25n2c08.png +0 -0
  158. data/spec/png_suite/gamma/g25n3p04.png +0 -0
  159. data/spec/png_suite/metadata/cm0n0g04.png +0 -0
  160. data/spec/png_suite/metadata/cm7n0g04.png +0 -0
  161. data/spec/png_suite/metadata/cm9n0g04.png +0 -0
  162. data/spec/png_suite/other/ccwn2c08.png +0 -0
  163. data/spec/png_suite/other/ccwn3p08.png +0 -0
  164. data/spec/png_suite/other/cdfn2c08.png +0 -0
  165. data/spec/png_suite/other/cdhn2c08.png +0 -0
  166. data/spec/png_suite/other/cdsn2c08.png +0 -0
  167. data/spec/png_suite/other/cdun2c08.png +0 -0
  168. data/spec/png_suite/other/ch1n3p04.png +0 -0
  169. data/spec/png_suite/other/ch2n3p08.png +0 -0
  170. data/spec/png_suite/other/cs3n2c16.png +0 -0
  171. data/spec/png_suite/other/cs3n3p08.png +0 -0
  172. data/spec/png_suite/other/cs5n2c08.png +0 -0
  173. data/spec/png_suite/other/cs5n3p08.png +0 -0
  174. data/spec/png_suite/other/cs8n2c08.png +0 -0
  175. data/spec/png_suite/other/cs8n3p08.png +0 -0
  176. data/spec/png_suite/other/ct0n0g04.png +0 -0
  177. data/spec/png_suite/other/ct1n0g04.png +0 -0
  178. data/spec/png_suite/other/ctzn0g04.png +0 -0
  179. data/spec/png_suite/other/pp0n2c16.png +0 -0
  180. data/spec/png_suite/other/pp0n6a08.png +0 -0
  181. data/spec/png_suite/other/ps1n0g08.png +0 -0
  182. data/spec/png_suite/other/ps1n2c16.png +0 -0
  183. data/spec/png_suite/other/ps2n0g08.png +0 -0
  184. data/spec/png_suite/other/ps2n2c16.png +0 -0
  185. data/spec/png_suite/sizes/s01i3p01.png +0 -0
  186. data/spec/png_suite/sizes/s01n3p01.png +0 -0
  187. data/spec/png_suite/sizes/s02i3p01.png +0 -0
  188. data/spec/png_suite/sizes/s02n3p01.png +0 -0
  189. data/spec/png_suite/sizes/s03i3p01.png +0 -0
  190. data/spec/png_suite/sizes/s03n3p01.png +0 -0
  191. data/spec/png_suite/sizes/s04i3p01.png +0 -0
  192. data/spec/png_suite/sizes/s04n3p01.png +0 -0
  193. data/spec/png_suite/sizes/s05i3p02.png +0 -0
  194. data/spec/png_suite/sizes/s05n3p02.png +0 -0
  195. data/spec/png_suite/sizes/s06i3p02.png +0 -0
  196. data/spec/png_suite/sizes/s06n3p02.png +0 -0
  197. data/spec/png_suite/sizes/s07i3p02.png +0 -0
  198. data/spec/png_suite/sizes/s07n3p02.png +0 -0
  199. data/spec/png_suite/sizes/s08i3p02.png +0 -0
  200. data/spec/png_suite/sizes/s08n3p02.png +0 -0
  201. data/spec/png_suite/sizes/s09i3p02.png +0 -0
  202. data/spec/png_suite/sizes/s09n3p02.png +0 -0
  203. data/spec/png_suite/sizes/s32i3p04.png +0 -0
  204. data/spec/png_suite/sizes/s32n3p04.png +0 -0
  205. data/spec/png_suite/sizes/s33i3p04.png +0 -0
  206. data/spec/png_suite/sizes/s33n3p04.png +0 -0
  207. data/spec/png_suite/sizes/s34i3p04.png +0 -0
  208. data/spec/png_suite/sizes/s34n3p04.png +0 -0
  209. data/spec/png_suite/sizes/s35i3p04.png +0 -0
  210. data/spec/png_suite/sizes/s35n3p04.png +0 -0
  211. data/spec/png_suite/sizes/s36i3p04.png +0 -0
  212. data/spec/png_suite/sizes/s36n3p04.png +0 -0
  213. data/spec/png_suite/sizes/s37i3p04.png +0 -0
  214. data/spec/png_suite/sizes/s37n3p04.png +0 -0
  215. data/spec/png_suite/sizes/s38i3p04.png +0 -0
  216. data/spec/png_suite/sizes/s38n3p04.png +0 -0
  217. data/spec/png_suite/sizes/s39i3p04.png +0 -0
  218. data/spec/png_suite/sizes/s39n3p04.png +0 -0
  219. data/spec/png_suite/sizes/s40i3p04.png +0 -0
  220. data/spec/png_suite/sizes/s40n3p04.png +0 -0
  221. data/spec/png_suite/transparency/tbbn1g04.png +0 -0
  222. data/spec/png_suite/transparency/tbbn2c16.png +0 -0
  223. data/spec/png_suite/transparency/tbbn3p08.png +0 -0
  224. data/spec/png_suite/transparency/tbgn2c16.png +0 -0
  225. data/spec/png_suite/transparency/tbgn3p08.png +0 -0
  226. data/spec/png_suite/transparency/tbrn2c08.png +0 -0
  227. data/spec/png_suite/transparency/tbwn1g16.png +0 -0
  228. data/spec/png_suite/transparency/tbwn3p08.png +0 -0
  229. data/spec/png_suite/transparency/tbyn3p08.png +0 -0
  230. data/spec/png_suite/transparency/tp0n1g08.png +0 -0
  231. data/spec/png_suite/transparency/tp0n2c08.png +0 -0
  232. data/spec/png_suite/transparency/tp0n3p08.png +0 -0
  233. data/spec/png_suite/transparency/tp1n3p08.png +0 -0
  234. data/spec/png_suite_spec.rb +119 -0
  235. data/spec/spec_helper.rb +26 -16
  236. metadata +240 -25
  237. data/spec/resources/16x16_interlaced.png +0 -0
  238. data/spec/resources/16x16_non_interlaced.png +0 -0
  239. data/spec/resources/gray_10x10.png +0 -0
  240. data/spec/resources/gray_10x10_grayscale.png +0 -0
  241. data/spec/resources/gray_10x10_grayscale_alpha.png +0 -0
  242. data/spec/resources/gray_10x10_indexed.png +0 -0
  243. data/spec/resources/gray_10x10_truecolor.png +0 -0
  244. data/spec/resources/gray_10x10_truecolor_alpha.png +0 -0
  245. data/spec/resources/transparent_gray_10x10.png +0 -0
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- chunky_png (0.10.5)
4
+ chunky_png (0.11.0)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
@@ -6,7 +6,7 @@ Bundler.setup
6
6
  require 'benchmark'
7
7
  require 'chunky_png'
8
8
 
9
- files = ['pixelstream_reference.png', 'operations.png', 'gray_10x10.png', 'clock_stubbed.png']
9
+ files = ['pixelstream_reference.png', 'operations.png', 'clock_stubbed.png']
10
10
 
11
11
  def encode_png(image, constraints = {})
12
12
  filesize = nil
@@ -3,8 +3,8 @@ Gem::Specification.new do |s|
3
3
 
4
4
  # Do not change the version and date fields by hand. This will be done
5
5
  # automatically by the gem release script.
6
- s.version = "0.10.5"
7
- s.date = "2010-10-22"
6
+ s.version = "0.11.0"
7
+ s.date = "2010-11-01"
8
8
 
9
9
  s.summary = "Pure ruby library for read/write, chunk-level access to PNG files"
10
10
  s.description = <<-EOT
@@ -38,6 +38,6 @@ Gem::Specification.new do |s|
38
38
 
39
39
  # Do not change the files and test_files fields by hand. This will be done
40
40
  # automatically by the gem release script.
41
- s.files = %w(.gitignore BENCHMARKS.rdoc Gemfile Gemfile.lock LICENSE README.rdoc Rakefile benchmarks/decoding_benchmark.rb benchmarks/encoding_benchmark.rb benchmarks/filesize_benchmark.rb chunky_png.gemspec lib/chunky_png.rb lib/chunky_png/canvas.rb lib/chunky_png/canvas/adam7_interlacing.rb lib/chunky_png/canvas/drawing.rb lib/chunky_png/canvas/operations.rb lib/chunky_png/canvas/png_decoding.rb lib/chunky_png/canvas/png_encoding.rb lib/chunky_png/canvas/stream_exporting.rb lib/chunky_png/canvas/stream_importing.rb lib/chunky_png/chunk.rb lib/chunky_png/color.rb lib/chunky_png/datastream.rb lib/chunky_png/image.rb lib/chunky_png/palette.rb lib/chunky_png/rmagick.rb spec/chunky_png/canvas/adam7_interlacing_spec.rb spec/chunky_png/canvas/drawing_spec.rb spec/chunky_png/canvas/operations_spec.rb spec/chunky_png/canvas/png_decoding_spec.rb spec/chunky_png/canvas/png_encoding_spec.rb spec/chunky_png/canvas_spec.rb spec/chunky_png/color_spec.rb spec/chunky_png/datastream_spec.rb spec/chunky_png/image_spec.rb spec/chunky_png/rmagick_spec.rb spec/chunky_png_spec.rb spec/resources/16x16_interlaced.png spec/resources/16x16_non_interlaced.png spec/resources/adam7.png spec/resources/clock.png spec/resources/clock_base.png spec/resources/clock_flip_horizontally.png spec/resources/clock_flip_vertically.png spec/resources/clock_mask.png spec/resources/clock_mask_updated.png spec/resources/clock_rotate_180.png spec/resources/clock_rotate_left.png spec/resources/clock_rotate_right.png spec/resources/clock_stubbed.png spec/resources/clock_updated.png spec/resources/composited.png spec/resources/cropped.png spec/resources/damaged_chunk.png spec/resources/damaged_signature.png spec/resources/gray_10x10.png spec/resources/gray_10x10_grayscale.png spec/resources/gray_10x10_grayscale_alpha.png spec/resources/gray_10x10_indexed.png spec/resources/gray_10x10_truecolor.png spec/resources/gray_10x10_truecolor_alpha.png spec/resources/indexed_4bit.png spec/resources/lines.png spec/resources/operations.png spec/resources/pixelstream.rgb spec/resources/pixelstream.rgba spec/resources/pixelstream_best_compression.png spec/resources/pixelstream_fast_rgba.png spec/resources/pixelstream_reference.png spec/resources/rect.png spec/resources/replaced.png spec/resources/text_chunk.png spec/resources/transparent_gray_10x10.png spec/resources/ztxt_chunk.png spec/spec_helper.rb tasks/benchmarks.rake tasks/github-gem.rake)
42
- s.test_files = %w(spec/chunky_png/canvas/adam7_interlacing_spec.rb spec/chunky_png/canvas/drawing_spec.rb spec/chunky_png/canvas/operations_spec.rb spec/chunky_png/canvas/png_decoding_spec.rb spec/chunky_png/canvas/png_encoding_spec.rb spec/chunky_png/canvas_spec.rb spec/chunky_png/color_spec.rb spec/chunky_png/datastream_spec.rb spec/chunky_png/image_spec.rb spec/chunky_png/rmagick_spec.rb spec/chunky_png_spec.rb)
41
+ s.files = %w(.gitignore BENCHMARKS.rdoc Gemfile Gemfile.lock LICENSE README.rdoc Rakefile benchmarks/decoding_benchmark.rb benchmarks/encoding_benchmark.rb benchmarks/filesize_benchmark.rb chunky_png.gemspec lib/chunky_png.rb lib/chunky_png/canvas.rb lib/chunky_png/canvas/adam7_interlacing.rb lib/chunky_png/canvas/drawing.rb lib/chunky_png/canvas/operations.rb lib/chunky_png/canvas/png_decoding.rb lib/chunky_png/canvas/png_encoding.rb lib/chunky_png/canvas/stream_exporting.rb lib/chunky_png/canvas/stream_importing.rb lib/chunky_png/chunk.rb lib/chunky_png/color.rb lib/chunky_png/compatibility.rb lib/chunky_png/datastream.rb lib/chunky_png/image.rb lib/chunky_png/palette.rb lib/chunky_png/rmagick.rb spec/chunky_png/canvas/adam7_interlacing_spec.rb spec/chunky_png/canvas/drawing_spec.rb spec/chunky_png/canvas/operations_spec.rb spec/chunky_png/canvas/png_decoding_spec.rb spec/chunky_png/canvas/png_encoding_spec.rb spec/chunky_png/canvas_spec.rb spec/chunky_png/color_spec.rb spec/chunky_png/datastream_spec.rb spec/chunky_png/image_spec.rb spec/chunky_png/rmagick_spec.rb spec/chunky_png_spec.rb spec/png_suite/background_chunks/bgai4a08.png spec/png_suite/background_chunks/bgai4a16.png spec/png_suite/background_chunks/bgan6a08.png spec/png_suite/background_chunks/bgan6a16.png spec/png_suite/background_chunks/bgbn4a08.png spec/png_suite/background_chunks/bggn4a16.png spec/png_suite/background_chunks/bgwn6a08.png spec/png_suite/background_chunks/bgyn6a16.png spec/png_suite/basic/basi0g01.png spec/png_suite/basic/basi0g01.rgba spec/png_suite/basic/basi0g02.png spec/png_suite/basic/basi0g02.rgba spec/png_suite/basic/basi0g04.png spec/png_suite/basic/basi0g04.rgba spec/png_suite/basic/basi0g08.png spec/png_suite/basic/basi0g08.rgba spec/png_suite/basic/basi0g16.png spec/png_suite/basic/basi0g16.rgba spec/png_suite/basic/basi2c08.png spec/png_suite/basic/basi2c08.rgba spec/png_suite/basic/basi2c16.png spec/png_suite/basic/basi2c16.rgba spec/png_suite/basic/basi3p01.png spec/png_suite/basic/basi3p01.rgba spec/png_suite/basic/basi3p02.png spec/png_suite/basic/basi3p02.rgba spec/png_suite/basic/basi3p04.png spec/png_suite/basic/basi3p04.rgba spec/png_suite/basic/basi3p08.png spec/png_suite/basic/basi3p08.rgba spec/png_suite/basic/basi4a08.png spec/png_suite/basic/basi4a08.rgba spec/png_suite/basic/basi4a16.png spec/png_suite/basic/basi4a16.rgba spec/png_suite/basic/basi6a08.png spec/png_suite/basic/basi6a08.rgba spec/png_suite/basic/basi6a16.png spec/png_suite/basic/basi6a16.rgba spec/png_suite/basic/basn0g01.png spec/png_suite/basic/basn0g01.rgba spec/png_suite/basic/basn0g02.png spec/png_suite/basic/basn0g02.rgba spec/png_suite/basic/basn0g04.png spec/png_suite/basic/basn0g04.rgba spec/png_suite/basic/basn0g08.png spec/png_suite/basic/basn0g08.rgba spec/png_suite/basic/basn0g16.png spec/png_suite/basic/basn0g16.rgba spec/png_suite/basic/basn2c08.png spec/png_suite/basic/basn2c08.rgba spec/png_suite/basic/basn2c16.png spec/png_suite/basic/basn2c16.rgba spec/png_suite/basic/basn3p01.png spec/png_suite/basic/basn3p01.rgba spec/png_suite/basic/basn3p02.png spec/png_suite/basic/basn3p02.rgba spec/png_suite/basic/basn3p04.png spec/png_suite/basic/basn3p04.rgba spec/png_suite/basic/basn3p08.png spec/png_suite/basic/basn3p08.rgba spec/png_suite/basic/basn4a08.png spec/png_suite/basic/basn4a08.rgba spec/png_suite/basic/basn4a16.png spec/png_suite/basic/basn4a16.rgba spec/png_suite/basic/basn6a08.png spec/png_suite/basic/basn6a08.rgba spec/png_suite/basic/basn6a16.png spec/png_suite/basic/basn6a16.rgba spec/png_suite/broken/x00n0g01.png spec/png_suite/broken/xcrn0g04.png spec/png_suite/broken/xlfn0g04.png spec/png_suite/chunk_ordering/oi1n0g16.png spec/png_suite/chunk_ordering/oi1n2c16.png spec/png_suite/chunk_ordering/oi2n0g16.png spec/png_suite/chunk_ordering/oi2n2c16.png spec/png_suite/chunk_ordering/oi4n0g16.png spec/png_suite/chunk_ordering/oi4n2c16.png spec/png_suite/chunk_ordering/oi9n0g16.png spec/png_suite/chunk_ordering/oi9n2c16.png spec/png_suite/compression_levels/z00n2c08.png spec/png_suite/compression_levels/z03n2c08.png spec/png_suite/compression_levels/z06n2c08.png spec/png_suite/compression_levels/z09n2c08.png spec/png_suite/filtering/f00n0g08.png spec/png_suite/filtering/f00n0g08.rgba spec/png_suite/filtering/f00n0g08_reference.png spec/png_suite/filtering/f00n0g08_reference.rgba spec/png_suite/filtering/f00n2c08.png spec/png_suite/filtering/f00n2c08.rgba spec/png_suite/filtering/f00n2c08_reference.png spec/png_suite/filtering/f00n2c08_reference.rgba spec/png_suite/filtering/f01n0g08.png spec/png_suite/filtering/f01n0g08.rgba spec/png_suite/filtering/f01n0g08_reference.png spec/png_suite/filtering/f01n0g08_reference.rgba spec/png_suite/filtering/f01n2c08.png spec/png_suite/filtering/f01n2c08.rgba spec/png_suite/filtering/f01n2c08_reference.png spec/png_suite/filtering/f01n2c08_reference.rgba spec/png_suite/filtering/f02n0g08.png spec/png_suite/filtering/f02n0g08.rgba spec/png_suite/filtering/f02n0g08_reference.png spec/png_suite/filtering/f02n0g08_reference.rgba spec/png_suite/filtering/f02n2c08.png spec/png_suite/filtering/f02n2c08.rgba spec/png_suite/filtering/f02n2c08_reference.png spec/png_suite/filtering/f02n2c08_reference.rgba spec/png_suite/filtering/f03n0g08.png spec/png_suite/filtering/f03n0g08.rgba spec/png_suite/filtering/f03n0g08_reference.png spec/png_suite/filtering/f03n0g08_reference.rgba spec/png_suite/filtering/f03n2c08.png spec/png_suite/filtering/f03n2c08.rgba spec/png_suite/filtering/f03n2c08_reference.png spec/png_suite/filtering/f03n2c08_reference.rgba spec/png_suite/filtering/f04n0g08.png spec/png_suite/filtering/f04n0g08.rgba spec/png_suite/filtering/f04n0g08_reference.png spec/png_suite/filtering/f04n0g08_reference.rgba spec/png_suite/filtering/f04n2c08.png spec/png_suite/filtering/f04n2c08.rgba spec/png_suite/filtering/f04n2c08_reference.png spec/png_suite/filtering/f04n2c08_reference.rgba spec/png_suite/gamma/g03n0g16.png spec/png_suite/gamma/g03n2c08.png spec/png_suite/gamma/g03n3p04.png spec/png_suite/gamma/g04n0g16.png spec/png_suite/gamma/g04n2c08.png spec/png_suite/gamma/g04n3p04.png spec/png_suite/gamma/g05n0g16.png spec/png_suite/gamma/g05n2c08.png spec/png_suite/gamma/g05n3p04.png spec/png_suite/gamma/g07n0g16.png spec/png_suite/gamma/g07n2c08.png spec/png_suite/gamma/g07n3p04.png spec/png_suite/gamma/g10n0g16.png spec/png_suite/gamma/g10n2c08.png spec/png_suite/gamma/g10n3p04.png spec/png_suite/gamma/g25n0g16.png spec/png_suite/gamma/g25n2c08.png spec/png_suite/gamma/g25n3p04.png spec/png_suite/metadata/cm0n0g04.png spec/png_suite/metadata/cm7n0g04.png spec/png_suite/metadata/cm9n0g04.png spec/png_suite/other/ccwn2c08.png spec/png_suite/other/ccwn3p08.png spec/png_suite/other/cdfn2c08.png spec/png_suite/other/cdhn2c08.png spec/png_suite/other/cdsn2c08.png spec/png_suite/other/cdun2c08.png spec/png_suite/other/ch1n3p04.png spec/png_suite/other/ch2n3p08.png spec/png_suite/other/cs3n2c16.png spec/png_suite/other/cs3n3p08.png spec/png_suite/other/cs5n2c08.png spec/png_suite/other/cs5n3p08.png spec/png_suite/other/cs8n2c08.png spec/png_suite/other/cs8n3p08.png spec/png_suite/other/ct0n0g04.png spec/png_suite/other/ct1n0g04.png spec/png_suite/other/ctzn0g04.png spec/png_suite/other/pp0n2c16.png spec/png_suite/other/pp0n6a08.png spec/png_suite/other/ps1n0g08.png spec/png_suite/other/ps1n2c16.png spec/png_suite/other/ps2n0g08.png spec/png_suite/other/ps2n2c16.png spec/png_suite/sizes/s01i3p01.png spec/png_suite/sizes/s01n3p01.png spec/png_suite/sizes/s02i3p01.png spec/png_suite/sizes/s02n3p01.png spec/png_suite/sizes/s03i3p01.png spec/png_suite/sizes/s03n3p01.png spec/png_suite/sizes/s04i3p01.png spec/png_suite/sizes/s04n3p01.png spec/png_suite/sizes/s05i3p02.png spec/png_suite/sizes/s05n3p02.png spec/png_suite/sizes/s06i3p02.png spec/png_suite/sizes/s06n3p02.png spec/png_suite/sizes/s07i3p02.png spec/png_suite/sizes/s07n3p02.png spec/png_suite/sizes/s08i3p02.png spec/png_suite/sizes/s08n3p02.png spec/png_suite/sizes/s09i3p02.png spec/png_suite/sizes/s09n3p02.png spec/png_suite/sizes/s32i3p04.png spec/png_suite/sizes/s32n3p04.png spec/png_suite/sizes/s33i3p04.png spec/png_suite/sizes/s33n3p04.png spec/png_suite/sizes/s34i3p04.png spec/png_suite/sizes/s34n3p04.png spec/png_suite/sizes/s35i3p04.png spec/png_suite/sizes/s35n3p04.png spec/png_suite/sizes/s36i3p04.png spec/png_suite/sizes/s36n3p04.png spec/png_suite/sizes/s37i3p04.png spec/png_suite/sizes/s37n3p04.png spec/png_suite/sizes/s38i3p04.png spec/png_suite/sizes/s38n3p04.png spec/png_suite/sizes/s39i3p04.png spec/png_suite/sizes/s39n3p04.png spec/png_suite/sizes/s40i3p04.png spec/png_suite/sizes/s40n3p04.png spec/png_suite/transparency/tbbn1g04.png spec/png_suite/transparency/tbbn2c16.png spec/png_suite/transparency/tbbn3p08.png spec/png_suite/transparency/tbgn2c16.png spec/png_suite/transparency/tbgn3p08.png spec/png_suite/transparency/tbrn2c08.png spec/png_suite/transparency/tbwn1g16.png spec/png_suite/transparency/tbwn3p08.png spec/png_suite/transparency/tbyn3p08.png spec/png_suite/transparency/tp0n1g08.png spec/png_suite/transparency/tp0n2c08.png spec/png_suite/transparency/tp0n3p08.png spec/png_suite/transparency/tp1n3p08.png spec/png_suite_spec.rb spec/resources/adam7.png spec/resources/clock.png spec/resources/clock_base.png spec/resources/clock_flip_horizontally.png spec/resources/clock_flip_vertically.png spec/resources/clock_mask.png spec/resources/clock_mask_updated.png spec/resources/clock_rotate_180.png spec/resources/clock_rotate_left.png spec/resources/clock_rotate_right.png spec/resources/clock_stubbed.png spec/resources/clock_updated.png spec/resources/composited.png spec/resources/cropped.png spec/resources/damaged_chunk.png spec/resources/damaged_signature.png spec/resources/lines.png spec/resources/operations.png spec/resources/pixelstream.rgb spec/resources/pixelstream.rgba spec/resources/pixelstream_best_compression.png spec/resources/pixelstream_fast_rgba.png spec/resources/pixelstream_reference.png spec/resources/rect.png spec/resources/replaced.png spec/resources/text_chunk.png spec/resources/ztxt_chunk.png spec/spec_helper.rb tasks/benchmarks.rake tasks/github-gem.rake)
42
+ s.test_files = %w(spec/chunky_png/canvas/adam7_interlacing_spec.rb spec/chunky_png/canvas/drawing_spec.rb spec/chunky_png/canvas/operations_spec.rb spec/chunky_png/canvas/png_decoding_spec.rb spec/chunky_png/canvas/png_encoding_spec.rb spec/chunky_png/canvas_spec.rb spec/chunky_png/color_spec.rb spec/chunky_png/datastream_spec.rb spec/chunky_png/image_spec.rb spec/chunky_png/rmagick_spec.rb spec/chunky_png_spec.rb spec/png_suite_spec.rb)
43
43
  end
@@ -3,6 +3,7 @@ require 'zlib'
3
3
  require 'stringio'
4
4
  require 'enumerator'
5
5
 
6
+ require 'chunky_png/compatibility'
6
7
  require 'chunky_png/datastream'
7
8
  require 'chunky_png/chunk'
8
9
  require 'chunky_png/palette'
@@ -27,7 +28,7 @@ module ChunkyPNG
27
28
 
28
29
  # The current version of ChunkyPNG. This value will be updated automatically
29
30
  # by them gem:release rake task.
30
- VERSION = "0.10.5"
31
+ VERSION = "0.11.0"
31
32
 
32
33
  ###################################################
33
34
  # PNG international standard defined constants
@@ -81,14 +82,6 @@ module ChunkyPNG
81
82
  class OutOfBounds < ChunkyPNG::ExpectationFailed
82
83
  end
83
84
 
84
- EMPTY_BYTEARRAY = (RUBY_VERSION.to_f < 1.9) ? "".freeze : "".force_encoding('ASCII-8BIT').freeze
85
- EXTRA_BYTE = (RUBY_VERSION.to_f < 1.9) ? "\0" : "\0".force_encoding('ASCII-8BIT')
86
- end
87
-
88
- if RUBY_VERSION.to_f < 1.9
89
- class String
90
- alias_method :getbyte, :[]
91
- alias_method :setbyte, :[]=
92
- alias_method :bytesize, :size
93
- end
85
+ EMPTY_BYTEARRAY = String.method_defined?(:force_encoding) ? "".force_encoding('ASCII-8BIT').freeze : "".freeze
86
+ EXTRA_BYTE = String.method_defined?(:force_encoding) ? "\0".force_encoding('ASCII-8BIT') : "\0"
94
87
  end
@@ -215,15 +215,14 @@ module ChunkyPNG
215
215
  ChunkyPNG::Image.from_canvas(self)
216
216
  end
217
217
 
218
- #################################################################
219
- # RUBY 1.8.6 compatibility
220
- #################################################################
221
-
222
- unless respond_to?(:tap)
223
- def tap(&block)
224
- yield(self)
225
- self
218
+ # Alternative implementation of the inspect method.
219
+ # @return [String] A nicely formatted string representation of this canvas.
220
+ def inspect
221
+ inspected = "<#{self.class.name} #{width}x#{height} ["
222
+ for y in 0...height
223
+ inspected << "\n\t[" << row(y).map { |p| ChunkyPNG::Color.to_hex(p) }.join(' ') << ']'
226
224
  end
225
+ inspected << "\n]>"
227
226
  end
228
227
 
229
228
  protected
@@ -1,47 +1,65 @@
1
1
  module ChunkyPNG
2
2
  class Canvas
3
3
 
4
- # Methods for decoding and encoding adam7 interlacing
4
+ # Methods for decoding and encoding Adam7 interlacing.
5
5
  #
6
+ # Adam7 interlacing extractg 7 pass images out of a single image, that can be encoded to a
7
+ # stream separately so the image can be built up progressively. The module is included into
8
+ # ChunkyPNG canvas and is used to extract the pass images from the original image, or to
9
+ # reconstruct an original image from separate pass images.
6
10
  module Adam7Interlacing
7
11
 
12
+ # Returns an array with the x-shift, x-offset, y-shift and y-offset for the requested pass.
13
+ # @param [Integer] pass The pass number, should be in 0..6.
8
14
  def adam7_multiplier_offset(pass)
9
- {
10
- :x_shift => 3 - (pass >> 1),
11
- :x_offset => (pass & 1 == 0) ? 0 : 8 >> ((pass + 1) >> 1),
12
- :y_shift => pass == 0 ? 3 : 3 - ((pass - 1) >> 1),
13
- :y_offset => (pass == 0 || pass & 1 == 1) ? 0 : 8 >> (pass >> 1)
14
- }
15
+ [3 - (pass >> 1), (pass & 1 == 0) ? 0 : 8 >> ((pass + 1) >> 1),
16
+ pass == 0 ? 3 : 3 - ((pass - 1) >> 1), (pass == 0 || pass & 1 == 1) ? 0 : 8 >> (pass >> 1)]
15
17
  end
16
18
 
19
+ # Returns the pixel dimensions of the requested pass.
20
+ # @param [Integer] pass The pass number, should be in 0..6.
21
+ # @param [Integer] original_width The width of the original image.
22
+ # @param [Integer] original_height The height of the original image.
17
23
  def adam7_pass_size(pass, original_width, original_height)
18
- m_o = adam7_multiplier_offset(pass)
19
- [ (original_width - m_o[:x_offset] + (1 << m_o[:x_shift]) - 1) >> m_o[:x_shift],
20
- (original_height - m_o[:y_offset] + (1 << m_o[:y_shift]) - 1) >> m_o[:y_shift]]
24
+ x_shift, x_offset, y_shift, y_offset = adam7_multiplier_offset(pass)
25
+ [ (original_width - x_offset + (1 << x_shift) - 1) >> x_shift,
26
+ (original_height - y_offset + (1 << y_shift) - 1) >> y_shift]
21
27
  end
22
-
28
+
29
+ # Returns an array of the dimension of all the pass images.
30
+ # @param [Integer] original_width The width of the original image.
31
+ # @param [Integer] original_height The height of the original image.
32
+ # @return [Array<Array<Integer>>] Returns an array with 7 pairs of dimensions.
33
+ # @see #adam7_pass_size
23
34
  def adam7_pass_sizes(original_width, original_height)
24
35
  (0...7).map { |pass| adam7_pass_size(pass, original_width, original_height) }
25
36
  end
26
37
 
38
+ # Merges a pass image into a total image that is being constructed.
39
+ # @param [Integer] pass The pass number, should be in 0..6.
40
+ # @param [ChunkyPNG::Canvas] canvas The image that is being constructed.
41
+ # @param [ChunkyPNG::Canvas] subcanvas The pass image that should be merged
27
42
  def adam7_merge_pass(pass, canvas, subcanvas)
28
- m_o = adam7_multiplier_offset(pass)
43
+ x_shift, x_offset, y_shift, y_offset = adam7_multiplier_offset(pass)
29
44
  for y in 0...subcanvas.height do
30
45
  for x in 0...subcanvas.width do
31
- new_x = (x << m_o[:x_shift]) | m_o[:x_offset]
32
- new_y = (y << m_o[:y_shift]) | m_o[:y_offset]
46
+ new_x = (x << x_shift) | x_offset
47
+ new_y = (y << y_shift) | y_offset
33
48
  canvas[new_x, new_y] = subcanvas[x, y]
34
49
  end
35
50
  end
36
- canvas
37
51
  end
38
52
 
53
+ # Extracts a pass from a complete image
54
+ # @param [Integer] pass The pass number, should be in 0..6.
55
+ # @param [ChunkyPNG::Canvas] canvas The image that is being deconstructed.
56
+ # @return [ChunkyPNG::Canvas] The extracted pass image.
39
57
  def adam7_extract_pass(pass, canvas)
40
- m_o = adam7_multiplier_offset(pass)
58
+ x_shift, x_offset, y_shift, y_offset = adam7_multiplier_offset(pass)
41
59
  sm_pixels = []
42
60
 
43
- m_o[:y_offset].step(canvas.height - 1, 1 << m_o[:y_shift]) do |y|
44
- m_o[:x_offset].step(canvas.width - 1, 1 << m_o[:x_shift]) do |x|
61
+ y_offset.step(canvas.height - 1, 1 << y_shift) do |y|
62
+ x_offset.step(canvas.width - 1, 1 << x_shift) do |x|
45
63
  sm_pixels << canvas[x, y]
46
64
  end
47
65
  end
@@ -63,17 +63,16 @@ module ChunkyPNG
63
63
  # @param [ChunkyPNG::Datastream] ds The datastream to decode.
64
64
  # @return [ChunkyPNG::Canvas] The canvas decoded from the PNG datastream.
65
65
  def from_datastream(ds)
66
- raise ChunkyPNG::NotSupported, "Only 8-bit color depth is currently supported by ChunkyPNG!" unless ds.header_chunk.depth == 8
66
+ # raise ChunkyPNG::NotSupported, "Only 8-bit color depth is currently supported by ChunkyPNG!" unless ds.header_chunk.depth == 8
67
67
 
68
68
  width = ds.header_chunk.width
69
69
  height = ds.header_chunk.height
70
70
  color_mode = ds.header_chunk.color
71
71
  interlace = ds.header_chunk.interlace
72
+ depth = ds.header_chunk.depth
72
73
 
73
74
  self.decoding_palette = ChunkyPNG::Palette.from_chunks(ds.palette_chunk, ds.transparency_chunk)
74
- pixelstream = ChunkyPNG::Chunk::ImageData.combine_chunks(ds.data_chunks)
75
-
76
- decode_png_pixelstream(pixelstream, width, height, color_mode, interlace)
75
+ decode_png_pixelstream(ds.imagedata, width, height, color_mode, depth, interlace)
77
76
  end
78
77
 
79
78
  # Decodes a canvas from a PNG encoded pixelstream, using a given width, height,
@@ -82,14 +81,14 @@ module ChunkyPNG
82
81
  # @param [Integer] width The width of the image.
83
82
  # @param [Integer] width The height of the image.
84
83
  # @param [Integer] color_mode The color mode of the encoded pixelstream.
84
+ # @param [Integer] depth The bit depth of the pixel samples.
85
85
  # @param [Integer] interlace The interlace method of the encoded pixelstream.
86
86
  # @return [ChunkyPNG::Canvas] The decoded Canvas instance.
87
- def decode_png_pixelstream(stream, width, height, color_mode = ChunkyPNG::COLOR_TRUECOLOR, interlace = ChunkyPNG::INTERLACING_NONE)
87
+ def decode_png_pixelstream(stream, width, height, color_mode, depth, interlace)
88
88
  raise ChunkyPNG::ExpectationFailed, "This palette is not suitable for decoding!" if decoding_palette && !decoding_palette.can_decode?
89
-
90
- return case interlace
91
- when ChunkyPNG::INTERLACING_NONE; decode_png_without_interlacing(stream, width, height, color_mode)
92
- when ChunkyPNG::INTERLACING_ADAM7; decode_png_with_adam7_interlacing(stream, width, height, color_mode)
89
+ case interlace
90
+ when ChunkyPNG::INTERLACING_NONE; decode_png_without_interlacing(stream, width, height, color_mode, depth)
91
+ when ChunkyPNG::INTERLACING_ADAM7; decode_png_with_adam7_interlacing(stream, width, height, color_mode, depth)
93
92
  else raise ChunkyPNG::NotSupported, "Don't know how the handle interlacing method #{interlace}!"
94
93
  end
95
94
  end
@@ -102,9 +101,10 @@ module ChunkyPNG
102
101
  # @param width (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
103
102
  # @param height (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
104
103
  # @param color_mode (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
104
+ # @param depth (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
105
105
  # @return (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
106
- def decode_png_without_interlacing(stream, width, height, color_mode)
107
- decode_png_image_pass(stream, width, height, color_mode, 0)
106
+ def decode_png_without_interlacing(stream, width, height, color_mode, depth)
107
+ decode_png_image_pass(stream, width, height, color_mode, depth, 0)
108
108
  end
109
109
 
110
110
  # Decodes a canvas from a Adam 7 interlaced PNG encoded pixelstream, using a
@@ -113,19 +113,249 @@ module ChunkyPNG
113
113
  # @param width (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
114
114
  # @param height (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
115
115
  # @param color_mode (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
116
+ # @param depth (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
116
117
  # @return (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
117
- def decode_png_with_adam7_interlacing(stream, width, height, color_mode)
118
- canvas = new(width, height)
119
- pixel_size = Color.bytesize(color_mode)
120
- start_pos = 0
121
- for pass in 0...7 do
118
+ def decode_png_with_adam7_interlacing(stream, width, height, color_mode, depth)
119
+ canvas = new(width, height)
120
+ start_pos = 0
121
+ for pass in 0...7
122
122
  sm_width, sm_height = adam7_pass_size(pass, width, height)
123
- sm = decode_png_image_pass(stream, sm_width, sm_height, color_mode, start_pos)
123
+ sm = decode_png_image_pass(stream, sm_width, sm_height, color_mode, depth, start_pos)
124
124
  adam7_merge_pass(pass, canvas, sm)
125
- start_pos += (sm_width * sm_height * pixel_size) + sm_height
125
+ start_pos += ChunkyPNG::Color.pass_bytesize(color_mode, depth, sm_width, sm_height)
126
126
  end
127
127
  canvas
128
128
  end
129
+
130
+ # Extract 4 consecutive bits from a byte.
131
+ # @param [Integer] byte The byte (0..255) value to extract a 4 bit value from.
132
+ # @param [Integer] index The index within the byte. This should be either 0 or 2;
133
+ # the value will be modded by 2 to enforce this.
134
+ # @return [Integer] The extracted 4bit value (0..15)
135
+ def decode_png_extract_4bit_value(byte, index)
136
+ (index & 0x01 == 0) ? ((byte & 0xf0) >> 4) : (byte & 0x0f)
137
+ end
138
+
139
+ # Extract 2 consecutive bits from a byte.
140
+ # @param [Integer] byte The byte (0..255) value to extract a 2 bit value from.
141
+ # @param [Integer] index The index within the byte. This should be either 0, 1, 2, or 3;
142
+ # the value will be modded by 4 to enforce this.
143
+ # @return [Integer] The extracted 2 bit value (0..3)
144
+ def decode_png_extract_2bit_value(byte, index)
145
+ bitshift = 6 - ((index & 0x03) << 1)
146
+ (byte & (0x03 << bitshift)) >> bitshift
147
+ end
148
+
149
+ # Extract a bit from a byte on a given index.
150
+ # @param [Integer] byte The byte (0..255) value to extract a a bit from.
151
+ # @param [Integer] index The index within the byte. This should be 0..7;
152
+ # the value will be modded by 8 to enforce this.
153
+ # @return [Integer] Either 1 or 0.
154
+ def decode_png_extract_1bit_value(byte, index)
155
+ bitshift = 7 - (index & 0x07)
156
+ (byte & (0x01 << bitshift)) >> bitshift
157
+ end
158
+
159
+ # Resamples a 16 bit value to an 8 bit value. This will discard some color information.
160
+ # @param [Integer] value The 16 bit value to resample.
161
+ # @return [Integer] The 8 bit resampled value
162
+ def decode_png_resample_16bit_value(value)
163
+ value >> 8
164
+ end
165
+
166
+ # Resamples a 4 bit value to an 8 bit value.
167
+ # @param [Integer] value The 4 bit value to resample.
168
+ # @return [Integer] The 8 bit resampled value.
169
+ def decode_png_resample_4bit_value(value)
170
+ case value
171
+ when 0x00; 0
172
+ when 0x01; 17
173
+ when 0x02; 34
174
+ when 0x03; 51
175
+ when 0x04; 68
176
+ when 0x05; 85
177
+ when 0x06; 102
178
+ when 0x07; 119
179
+ when 0x08; 137
180
+ when 0x09; 154
181
+ when 0x0a; 171
182
+ when 0x0b; 188
183
+ when 0x0c; 205
184
+ when 0x0d; 222
185
+ when 0x0e; 239
186
+ when 0x0f; 255
187
+ end
188
+ end
189
+
190
+ # Resamples a 2 bit value to an 8 bit value.
191
+ # @param [Integer] value The 2 bit value to resample.
192
+ # @return [Integer] The 8 bit resampled value.
193
+ def decode_png_resample_2bit_value(value)
194
+ case value
195
+ when 0x00; 0x00
196
+ when 0x01; 0x55
197
+ when 0x02; 0xaa
198
+ when 0x03; 0xff
199
+ end
200
+ end
201
+
202
+ # Decodes a scanline of a 1-bit, indexed image into a row of pixels.
203
+ # @param [String] stream The stream to decode from.
204
+ # @param [Integer] pos The position in the stream on qhich the scanline starts (including the filter byte).
205
+ # @param [Integer] width The width in pixels of the scanline.
206
+ # @return [Array<Integer>] An array of decoded pixels.
207
+ def decode_png_pixels_from_scanline_indexed_1bit(stream, pos, width)
208
+ (0...width).map do |index|
209
+ palette_pos = decode_png_extract_1bit_value(stream.getbyte(pos + 1 + (index >> 3)), index)
210
+ decoding_palette[palette_pos]
211
+ end
212
+ end
213
+
214
+ # Decodes a scanline of a 2-bit, indexed image into a row of pixels.
215
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
216
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
217
+ def decode_png_pixels_from_scanline_indexed_2bit(stream, pos, width)
218
+ (0...width).map do |index|
219
+ palette_pos = decode_png_extract_2bit_value(stream.getbyte(pos + 1 + (index >> 2)), index)
220
+ decoding_palette[palette_pos]
221
+ end
222
+ end
223
+
224
+ # Decodes a scanline of a 4-bit, indexed image into a row of pixels.
225
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
226
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
227
+ def decode_png_pixels_from_scanline_indexed_4bit(stream, pos, width)
228
+ (0...width).map do |index|
229
+ palette_pos = decode_png_extract_4bit_value(stream.getbyte(pos + 1 + (index >> 1)), index)
230
+ decoding_palette[palette_pos]
231
+ end
232
+ end
233
+
234
+ # Decodes a scanline of a 8-bit, indexed image into a row of pixels.
235
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
236
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
237
+ def decode_png_pixels_from_scanline_indexed_8bit(stream, pos, width)
238
+ (1..width).map { |i| decoding_palette[stream.getbyte(pos + i)] }
239
+ end
240
+
241
+ # Decodes a scanline of an 8-bit, true color image with transparency into a row of pixels.
242
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
243
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
244
+ def decode_png_pixels_from_scanline_truecolor_alpha_8bit(stream, pos, width)
245
+ stream.unpack("@#{pos + 1}N#{width}")
246
+ end
247
+
248
+ # Decodes a scanline of a 16-bit, true color image with transparency into a row of pixels.
249
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
250
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
251
+ def decode_png_pixels_from_scanline_truecolor_alpha_16bit(stream, pos, width)
252
+ [].tap do |pixels|
253
+ stream.unpack("@#{pos + 1}n#{width * 4}").each_slice(4) do |r, g, b, a|
254
+ pixels << ChunkyPNG::Color.rgba(decode_png_resample_16bit_value(r), decode_png_resample_16bit_value(g),
255
+ decode_png_resample_16bit_value(b), decode_png_resample_16bit_value(a))
256
+ end
257
+ end
258
+ end
259
+
260
+ # Decodes a scanline of an 8-bit, true color image into a row of pixels.
261
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
262
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
263
+ def decode_png_pixels_from_scanline_truecolor_8bit(stream, pos, width)
264
+ stream.unpack("@#{pos + 1}" << ('NX' * width)).map { |c| c | 0x000000ff }
265
+ end
266
+
267
+ # Decodes a scanline of a 16-bit, true color image into a row of pixels.
268
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
269
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
270
+ def decode_png_pixels_from_scanline_truecolor_16bit(stream, pos, width)
271
+ [].tap do |pixels|
272
+ stream.unpack("@#{pos + 1}n#{width * 3}").each_slice(3) do |r, g, b|
273
+ pixels << ChunkyPNG::Color.rgb(decode_png_resample_16bit_value(r), decode_png_resample_16bit_value(g), decode_png_resample_16bit_value(b))
274
+ end
275
+ end
276
+ end
277
+
278
+ # Decodes a scanline of an 8-bit, grayscale image with transparency into a row of pixels.
279
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
280
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
281
+ def decode_png_pixels_from_scanline_grayscale_alpha_8bit(stream, pos, width)
282
+ (0...width).map { |i| ChunkyPNG::Color.grayscale_alpha(stream.getbyte(pos + (i * 2) + 1), stream.getbyte(pos + (i * 2) + 2)) }
283
+ end
284
+
285
+ # Decodes a scanline of a 16-bit, grayscale image with transparency into a row of pixels.
286
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
287
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
288
+ def decode_png_pixels_from_scanline_grayscale_alpha_16bit(stream, pos, width)
289
+ [].tap do |pixels|
290
+ stream.unpack("@#{pos + 1}n#{width * 2}").each_slice(2) do |g, a|
291
+ pixels << ChunkyPNG::Color.grayscale_alpha(decode_png_resample_16bit_value(g), decode_png_resample_16bit_value(a))
292
+ end
293
+ end
294
+ end
295
+
296
+ # Decodes a scanline of a 1-bit, grayscale image into a row of pixels.
297
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
298
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
299
+ def decode_png_pixels_from_scanline_grayscale_1bit(stream, pos, width)
300
+ (0...width).map do |index|
301
+ value = decode_png_extract_1bit_value(stream.getbyte(pos + 1 + (index >> 3)), index)
302
+ value == 1 ? ChunkyPNG::Color::WHITE : ChunkyPNG::Color::BLACK
303
+ end
304
+ end
305
+
306
+ # Decodes a scanline of a 2-bit, grayscale image into a row of pixels.
307
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
308
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
309
+ def decode_png_pixels_from_scanline_grayscale_2bit(stream, pos, width)
310
+ (0...width).map do |index|
311
+ value = decode_png_extract_2bit_value(stream.getbyte(pos + 1 + (index >> 2)), index)
312
+ ChunkyPNG::Color.grayscale(decode_png_resample_2bit_value(value))
313
+ end
314
+ end
315
+
316
+ # Decodes a scanline of a 4-bit, grayscale image into a row of pixels.
317
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
318
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
319
+ def decode_png_pixels_from_scanline_grayscale_4bit(stream, pos, width)
320
+ (0...width).map do |index|
321
+ value = decode_png_extract_4bit_value(stream.getbyte(pos + 1 + (index >> 1)), index)
322
+ ChunkyPNG::Color.grayscale(decode_png_resample_4bit_value(value))
323
+ end
324
+ end
325
+
326
+ # Decodes a scanline of an 8-bit, grayscale image into a row of pixels.
327
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
328
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
329
+ def decode_png_pixels_from_scanline_grayscale_8bit(stream, pos, width)
330
+ (1..width).map { |i| ChunkyPNG::Color.grayscale(stream.getbyte(pos + i)) }
331
+ end
332
+
333
+ # Decodes a scanline of a 16-bit, grayscale image into a row of pixels.
334
+ # @params (see #decode_png_pixels_from_scanline_indexed_1bit)
335
+ # @return (see #decode_png_pixels_from_scanline_indexed_1bit)
336
+ def decode_png_pixels_from_scanline_grayscale_16bit(stream, pos, width)
337
+ values = stream.unpack("@#{pos + 1}n#{width}")
338
+ values.map { |value| ChunkyPNG::Color.grayscale(decode_png_resample_16bit_value(value)) }
339
+ end
340
+
341
+ # Returns the method name to use to decode scanlines into pixels.
342
+ # @param [Integer] color_mode The color mode of the image.
343
+ # @param [Integer] depth The bit depth of the image.
344
+ # @return [Symbol] The method name to use for decoding, to be called on the canvas class.
345
+ # @raise [ChunkyPNG::NotSupported] when the color_mode and/or bit depth is not supported.
346
+ def decode_png_pixels_from_scanline_method(color_mode, depth)
347
+ decoder_method = case color_mode
348
+ when ChunkyPNG::COLOR_TRUECOLOR; :"decode_png_pixels_from_scanline_truecolor_#{depth}bit"
349
+ when ChunkyPNG::COLOR_TRUECOLOR_ALPHA; :"decode_png_pixels_from_scanline_truecolor_alpha_#{depth}bit"
350
+ when ChunkyPNG::COLOR_INDEXED; :"decode_png_pixels_from_scanline_indexed_#{depth}bit"
351
+ when ChunkyPNG::COLOR_GRAYSCALE; :"decode_png_pixels_from_scanline_grayscale_#{depth}bit"
352
+ when ChunkyPNG::COLOR_GRAYSCALE_ALPHA; :"decode_png_pixels_from_scanline_grayscale_alpha_#{depth}bit"
353
+ else nil
354
+ end
355
+
356
+ raise ChunkyPNG::NotSupported, "No decoder found for color mode #{color_mode} and #{depth}-bit depth!" unless respond_to?(decoder_method)
357
+ decoder_method
358
+ end
129
359
 
130
360
  # Decodes a single PNG image pass width a given width, height and color
131
361
  # mode, to a Canvas, starting at the given position in the stream.
@@ -139,36 +369,28 @@ module ChunkyPNG
139
369
  # @param color_mode (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
140
370
  # @param [Integer] start_pos The position in the pixel stream to start reading.
141
371
  # @return (see ChunkyPNG::Canvas::PNGDecoding#decode_png_pixelstream)
142
- def decode_png_image_pass(stream, width, height, color_mode, start_pos)
143
- stream << ChunkyPNG::EXTRA_BYTE if color_mode == ChunkyPNG::COLOR_TRUECOLOR
144
- pixel_size = Color.bytesize(color_mode)
145
- pixel_decoder = case color_mode
146
- when ChunkyPNG::COLOR_TRUECOLOR; lambda { |s, pos| s.unpack("@#{pos + 1}" << ('NX' * width)).map { |c| c | 0x000000ff } }
147
- when ChunkyPNG::COLOR_TRUECOLOR_ALPHA; lambda { |s, pos| s.unpack("@#{pos + 1}N#{width}") }
148
- when ChunkyPNG::COLOR_INDEXED; lambda { |s, pos| (1..width).map { |i| decoding_palette[s.getbyte(pos + i)] } }
149
- when ChunkyPNG::COLOR_GRAYSCALE; lambda { |s, pos| (1..width).map { |i| ChunkyPNG::Color.grayscale(s.getbyte(pos + i)) } }
150
- when ChunkyPNG::COLOR_GRAYSCALE_ALPHA; lambda { |s, pos| (0...width).map { |i| ChunkyPNG::Color.grayscale_alpha(s.getbyte(pos + (i * 2) + 1), s.getbyte(pos + (i * 2) + 2)) } }
151
- else raise ChunkyPNG::NotSupported, "No suitable pixel decoder found for color mode #{color_mode}!"
152
- end
372
+ def decode_png_image_pass(stream, width, height, color_mode, depth, start_pos)
153
373
 
154
374
  pixels = []
155
- if width > 0
375
+ if width > 0 && height > 0
156
376
 
157
- raise ChunkyPNG::ExpectationFailed, "Invalid stream length!" unless stream.length - start_pos >= width * height * pixel_size + height
377
+ stream << ChunkyPNG::EXTRA_BYTE if color_mode == ChunkyPNG::COLOR_TRUECOLOR
378
+ pixel_decoder = decode_png_pixels_from_scanline_method(color_mode, depth)
379
+ line_length = ChunkyPNG::Color.scanline_bytesize(color_mode, depth, width)
380
+ pixel_size = ChunkyPNG::Color.pixel_bytesize(color_mode, depth)
158
381
 
159
- decoded_bytes = Array.new(width * pixel_size, 0)
160
- line_length = width * pixel_size
161
- pos, prev_pos = start_pos, nil
382
+ raise ChunkyPNG::ExpectationFailed, "Invalid stream length!" unless stream.bytesize - start_pos >= ChunkyPNG::Color.pass_bytesize(color_mode, depth, width, height)
162
383
 
384
+ pos, prev_pos = start_pos, nil
163
385
  for line_no in 0...height do
164
386
  decode_png_str_scanline(stream, pos, prev_pos, line_length, pixel_size)
165
- pixels += pixel_decoder.call(stream, pos)
387
+ pixels += send(pixel_decoder, stream, pos, width)
166
388
 
167
389
  prev_pos = pos
168
390
  pos += line_length + 1
169
391
  end
170
392
  end
171
-
393
+
172
394
  new(width, height, pixels)
173
395
  end
174
396