chunky_png 0.10.5 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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