From ea811d952c4ec71b0b98ba2fc4eb4fb411cb1fe5 Mon Sep 17 00:00:00 2001 From: Michael Berkowitz Date: Tue, 9 Feb 2021 19:51:47 -0500 Subject: [PATCH] Smarter about choosing right color mode/bit depth --- lib/ex_png/chunks/image_data.ex | 67 +- lib/ex_png/chunks/palette.ex | 16 + lib/ex_png/image.ex | 7 + lib/ex_png/image/decoding.ex | 2 +- lib/ex_png/image/encoding.ex | 80 ++- lib/ex_png/pixel.ex | 13 + lib/ex_png/raw_data.ex | 6 + lib/ex_png/utilities.ex | 16 + prof/readwrite2.prof | 836 +++++++------------------ test/ex_png/chunks/image_data_test.exs | 62 ++ test/ex_png/image_test.exs | 20 +- test/png_suite/filtering/f99n0g04.png | Bin 0 -> 426 bytes 12 files changed, 484 insertions(+), 641 deletions(-) create mode 100644 lib/ex_png/utilities.ex create mode 100644 test/ex_png/chunks/image_data_test.exs create mode 100644 test/png_suite/filtering/f99n0g04.png diff --git a/lib/ex_png/chunks/image_data.ex b/lib/ex_png/chunks/image_data.ex index e96eb2e..d2bdaff 100644 --- a/lib/ex_png/chunks/image_data.ex +++ b/lib/ex_png/chunks/image_data.ex @@ -8,6 +8,11 @@ defmodule ExPng.Chunks.ImageData do decoded by `ExPng`. """ + use ExPng.Constants + + alias ExPng.Image + import ExPng.Utilities, only: [reduce_to_binary: 1] + @type t :: %__MODULE__{ data: binary, type: :IDAT @@ -49,31 +54,64 @@ defmodule ExPng.Chunks.ImageData do <> <> type <> data <> <> end - def from_pixels(pixels) do + def from_pixels(image, header) do + palette = Image.unique_pixels(image) data = - Enum.map(pixels, fn line -> - Task.async(fn -> line_to_binary(line) end) + Enum.map(image.pixels, fn line -> + Task.async(fn -> line_to_binary(line, header, palette) end) end) |> Enum.map(fn task -> Task.await(task) end) - |> Enum.reverse() - |> Enum.reduce(&Kernel.<>/2) + |> reduce_to_binary() - %__MODULE__{data: data} + {%__MODULE__{data: data}, %ExPng.Chunks.Palette{palette: palette}} end ## PRIVATE - defp line_to_binary(line) do - Enum.reduce(line, <<0>>, fn pixel, acc -> - acc <> <> - end) + defp line_to_binary(line, %{color_mode: @indexed} = header, palette) do + bit_depth = header.bit_depth + chunk_size = div(8, bit_depth) + line = + line + |> Enum.map(fn pixel -> Enum.find_index(palette, fn p -> p == pixel end) end) + |> Enum.map(fn i -> + Integer.to_string(i, 2) + |> String.pad_leading(bit_depth, "0") + end) + |> Enum.chunk_every(chunk_size, chunk_size) + |> Enum.map(fn byte -> + byte = + byte + |> Enum.join("") + |> String.pad_trailing(8, "0") + |> String.to_integer(2) + <> + end) + |> reduce_to_binary() + <<0>> <> line + end + + defp line_to_binary(line, %{bit_depth: 1} = _header, _palette) do + line = + line + |> Enum.map(& div(&1.b, 255)) + |> Enum.chunk_every(8) + |> Enum.map(fn bits -> Enum.join(bits, "") |> String.to_integer(2) end) + |> Enum.map(fn byte -> <> end) + |> reduce_to_binary() + <<0>> <> line end - defp reduce_to_binary(chunks) do - Enum.reduce(chunks, <<>>, fn chunk, acc -> - acc <> chunk + defp line_to_binary(line, %{bit_depth: 8} = header, _palette) do + Enum.reduce(line, <<0>>, fn pixel, acc -> + acc <> case header.color_mode do + @truecolor_alpha -> <> + @truecolor -> <> + @grayscale_alpha -> <> + @grayscale -> <> + end end) end @@ -94,7 +132,6 @@ defmodule ExPng.Chunks.ImageData do :zlib.close(zstream) deflated_data |> List.flatten() - |> Enum.reverse() - |> Enum.reduce(&Kernel.<>/2) + |> reduce_to_binary() end end diff --git a/lib/ex_png/chunks/palette.ex b/lib/ex_png/chunks/palette.ex index e850216..a37ef2d 100644 --- a/lib/ex_png/chunks/palette.ex +++ b/lib/ex_png/chunks/palette.ex @@ -6,6 +6,8 @@ defmodule ExPng.Chunks.Palette do alias ExPng.Pixel + import ExPng.Utilities, only: [reduce_to_binary: 1] + @type t :: %__MODULE__{ type: :PLTE, data: binary(), @@ -20,6 +22,20 @@ defmodule ExPng.Chunks.Palette do end end + @behaviour ExPng.Encodeable + + @impl true + def to_bytes(%__MODULE__{palette: palette}, _encoding_options \\ []) do + data = + Enum.map(palette, fn pixel -> <> end) + |> reduce_to_binary() + length = byte_size(data) + type = <<80, 76, 84, 69>> + crc = :erlang.crc32([type, data]) + + <> <> type <> data <> <> + end + ## PRIVATE defp parse_palette(data) do diff --git a/lib/ex_png/image.ex b/lib/ex_png/image.ex index 5a1e95c..e82daed 100644 --- a/lib/ex_png/image.ex +++ b/lib/ex_png/image.ex @@ -77,6 +77,13 @@ defmodule ExPng.Image do end end + @spec unique_pixels(__MODULE__.t) :: integer() + def unique_pixels(%__MODULE__{pixels: pixels}) do + pixels + |> List.flatten() + |> Enum.uniq() + end + defdelegate erase(image), to: Drawing defdelegate draw(image, coordinates, color), to: Drawing defdelegate at(image, coordinates), to: Drawing diff --git a/lib/ex_png/image/decoding.ex b/lib/ex_png/image/decoding.ex index 014de8a..b41b3f4 100644 --- a/lib/ex_png/image/decoding.ex +++ b/lib/ex_png/image/decoding.ex @@ -34,7 +34,7 @@ defmodule ExPng.Image.Decoding do image.header_chunk.bit_depth, image.header_chunk.color_mode, image.palette_chunk - ) + ) |> Enum.take(data.header_chunk.width) end) %Image{ diff --git a/lib/ex_png/image/encoding.ex b/lib/ex_png/image/encoding.ex index 998cf14..9d4f055 100644 --- a/lib/ex_png/image/encoding.ex +++ b/lib/ex_png/image/encoding.ex @@ -7,31 +7,97 @@ defmodule ExPng.Image.Encoding do use ExPng.Constants alias ExPng.Chunks.{End, Header, ImageData} - alias ExPng.{Image, RawData} + alias ExPng.{Image, Pixel, RawData} def to_raw_data(%Image{} = image) do header = build_header(image) - image_data_chunk = ImageData.from_pixels(image.pixels) + {image_data_chunk, palette} = ImageData.from_pixels(image, header) - { - :ok, + raw_data = %RawData{ header_chunk: header, data_chunk: image_data_chunk, end_chunk: %End{} } - } + + raw_data = case header.color_mode do + @indexed -> + %{raw_data | + palette_chunk: palette + } + _ -> raw_data + end + + {:ok, raw_data} end defp build_header(%Image{} = image) do + {bit_depth, color_mode} = bit_depth_and_color_mode(image) %Header{ width: image.width, height: image.height, - bit_depth: 8, - color_mode: @truecolor_alpha, + bit_depth: bit_depth, + color_mode: color_mode, compression: 0, filter: 0, interlace: 0 } end + + # 1. black and white + # 2. grayscale (alpha) + # 3. indexed + # 4. truecolor (alpha) + defp bit_depth_and_color_mode(%Image{} = image) do + case black_and_white?(image) do + true -> {1, @grayscale} + false -> + case {indexable?(image), opaque?(image), grayscale?(image)} do + {_, true, true} -> {8, @grayscale} + {_, false, true} -> {8, @grayscale_alpha} + {true, _, _} -> {indexed_bit_depth(image), @indexed} + {_, true, false} -> {8, @truecolor} + {_, false, false} -> {8, @truecolor_alpha} + end + end + end + + defp indexed_bit_depth(%Image{} = image) do + case unique_pixel_count(image) do + i when i <= 2 -> 1 + i when i <= 4 -> 2 + i when i <= 16 -> 4 + i when i <= 256 -> 8 + end + end + + defp indexable?(%Image{} = image) do + image + |> unique_pixel_count() + |> Kernel.<=(256) + end + + defp unique_pixel_count(%Image{} = image) do + image + |> Image.unique_pixels() + |> length() + end + + defp opaque?(%Image{pixels: pixels}) do + pixels + |> List.flatten() + |> Enum.all?(&Pixel.opaque?/1) + end + + defp grayscale?(%Image{pixels: pixels}) do + pixels + |> List.flatten() + |> Enum.all?(&Pixel.grayscale?/1) + end + + defp black_and_white?(%Image{pixels: pixels}) do + pixels + |> List.flatten() + |> Enum.all?(&Pixel.black_or_white?/1) + end end diff --git a/lib/ex_png/pixel.ex b/lib/ex_png/pixel.ex index 8b9f760..dce42f1 100644 --- a/lib/ex_png/pixel.ex +++ b/lib/ex_png/pixel.ex @@ -61,6 +61,19 @@ defmodule ExPng.Pixel do """ @spec white() :: __MODULE__.t() def white, do: grayscale(255) + + @spec opaque?(__MODULE__.t()) :: boolean + def opaque?(%__MODULE__{a: 255}), do: true + def opaque?(_), do: false + + @spec grayscale?(__MODULE__.t()) :: boolean + def grayscale?(%__MODULE__{r: gr, g: gr, b: gr}), do: true + def grayscale?(_), do: false + + @spec black_or_white?(__MODULE__.t()) :: boolean + def black_or_white?(%__MODULE__{r: 0, g: 0, b: 0, a: 255}), do: true + def black_or_white?(%__MODULE__{r: 255, g: 255, b: 255, a: 255}), do: true + def black_or_white?(_), do: false end defimpl Inspect, for: ExPng.Pixel do diff --git a/lib/ex_png/raw_data.ex b/lib/ex_png/raw_data.ex index 424d16c..3509380 100644 --- a/lib/ex_png/raw_data.ex +++ b/lib/ex_png/raw_data.ex @@ -52,9 +52,15 @@ defmodule ExPng.RawData do def to_file(%__MODULE__{} = raw_data, filename, encoding_options \\ []) do image_data = ImageData.to_bytes(raw_data.data_chunk, encoding_options) + palette_data = case raw_data.palette_chunk do + nil -> "" + palette -> Palette.to_bytes(palette) + end + data = @signature <> Header.to_bytes(raw_data.header_chunk) <> + palette_data <> image_data <> End.to_bytes(raw_data.end_chunk) diff --git a/lib/ex_png/utilities.ex b/lib/ex_png/utilities.ex new file mode 100644 index 0000000..c927742 --- /dev/null +++ b/lib/ex_png/utilities.ex @@ -0,0 +1,16 @@ +defmodule ExPng.Utilities do + @moduledoc """ + Shared utility functions. + """ + + @doc """ + Accepts a list of binaries and reduces them to a single + binary + """ + @spec reduce_to_binary([binary]) :: binary + def reduce_to_binary(list) do + list + |> Enum.reverse() + |> Enum.reduce(&Kernel.<>/2) + end +end diff --git a/prof/readwrite2.prof b/prof/readwrite2.prof index 4280e53..a9b4dac 100644 --- a/prof/readwrite2.prof +++ b/prof/readwrite2.prof @@ -1,610 +1,242 @@ Compiling 1 file (.ex) Warmup... Reading trace data... -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -................................................., -.................................................. -......................... End of trace! Processing data... Creating output... Done! - CNT ACC (ms) OWN (ms) -Total 17049785 24807.334 25927.685 -:proc_lib.init_p/5 250 30036.389 11.937 -:suspend 6812 28916.038 0.000 -Enum.reduce/3 63241 25545.343 86.604 -Enum."-reduce/3-lists^foldl/2-0-"/3 187005 25543.441 1220.986 -:fprof.apply_start_stop/4 0 24807.334 0.011 -anonymous fn/0 in :elixir_compiler_1.__FILE__/1 1 24807.322 0.006 -ExPng.Image.from_file/1 1 24595.962 0.007 -ExPng.Image.Decoding.from_raw_data/1 1 24593.159 0.008 -ExPng.Image.Decoding.filter_pass/1 1 24232.146 0.007 -anonymous fn/3 in ExPng.Image.Decoding.filter_pass/1 250 24231.431 0.991 -ExPng.Image.Line.filter_pass/3 494 24228.098 3.118 -anonymous fn/5 in ExPng.Image.Line.filter_pass/3 60250 23229.351 361.923 -Enum.at/2 121010 21694.291 159.623 -Enum.at/3 121010 21511.970 289.344 -Enum.slice_any/3 121010 21200.968 311.051 -Enum.drop_list/2 15157116 20638.291 20520.332 -:proc_lib.init_p_do_apply/3 250 1374.889 3.379 -Task.Supervised.reply/4 250 1371.510 5.682 -Task.Supervised.reply/5 250 1342.217 5.609 -Task.Supervised.invoke_mfa/2 250 1322.160 3.176 -:erlang.apply/2 250 1318.984 2.022 -anonymous fn/1 in ExPng.Chunks.ImageData.from_pixels/1 250 1316.962 1.898 -ExPng.Chunks.ImageData.line_to_binary/1 250 1315.064 1.985 -Enum.reduce_range_inc/4 187482 1082.576 403.161 -anonymous fn/6 in ExPng.Image.Line.filter_pass/3 180750 669.604 453.072 -Enum.map/2 4 569.301 0.017 -Enum."-map/2-lists^map/1-0-"/2 756 569.284 6.778 -anonymous fn/2 in ExPng.Chunks.ImageData.line_to_binary/1 62500 399.111 372.924 -:garbage_collect 10406 369.906 369.906 -anonymous fn/2 in ExPng.Image.Decoding.from_raw_data/1 250 358.520 0.253 -ExPng.Image.Line.to_pixels/4 250 358.267 0.253 -ExPng.Image.Line."-to_pixels/4-lc$^5/1-9-"/1 62750 358.013 194.160 -Enum.take_list/2 121010 248.307 138.038 -ExPng.Image.to_file/2 1 211.354 0.003 -ExPng.Image.Encoding.to_raw_data/1 1 210.817 0.003 -ExPng.Chunks.ImageData.from_pixels/1 1 210.813 0.017 -ExPng.Image.Line.calculate_paeth_delta/3 180750 194.339 192.015 -anonymous fn/1 in ExPng.Chunks.ImageData.from_pixels/1 250 161.908 1.387 -Task.async/1 250 160.521 1.372 -Task.async/3 250 159.149 7.302 -Range.new/2 62494 153.599 72.968 -ExPng.Image.Line."-filter_pass/3-lc$^10/1-3-"/2 60491 146.847 143.366 -ExPng.Image.Line."-filter_pass/3-lc$^11/1-4-"/2 60491 144.221 132.324 -Task.Supervised.start_link/4 250 141.816 2.267 -:proc_lib.spawn_link/3 250 139.549 5.310 -anonymous fn/4 in ExPng.Image.Line.filter_pass/3 750 137.598 3.398 -Enum.with_index/1 244 135.473 0.256 -Enum.with_index/2 244 135.217 0.517 -Enum.do_with_index/2 61244 134.453 133.324 -ExPng.Pixel.rgb/3 62500 117.801 63.262 -anonymous fn/2 in ExPng.Image.Line.filter_pass/3 60250 65.790 63.714 -:erlang.spawn_link/3 250 62.861 62.861 -anonymous fn/3 in ExPng.Image.Line.filter_pass/3 1494 24.438 5.369 -Task.Supervised.initial_call/1 250 17.063 3.900 -:erlang.send/2 500 15.628 15.628 -ExPng.Image.Line.build_pad_for_filter/1 244 13.712 1.072 -Enum.take/2 244 9.287 0.800 -Process.put/2 500 9.255 6.372 -Enum.reduce/2 252 8.775 0.350 -Task.Supervised.get_initial_call/1 250 8.489 5.489 -Enum."-reduce/2-lists^foldl/2-0-"/3 2492 8.425 5.649 -Enumerable.reduce/3 244 7.368 0.790 -Task.Supervised.put_callers/1 250 6.548 1.967 -Task.get_owner/1 250 6.548 2.253 -:erlang.put/2 1000 6.393 6.393 -:proc_lib.get_my_name/0 250 6.385 2.226 -Enumerable.Function.reduce/3 244 5.694 0.359 -anonymous fn/4 in Stream.unfold/2 244 5.335 0.372 -anonymous fn/4 in ExPng.Image.Line.filter_pass/3 4482 5.277 5.139 -Stream.do_unfold/4 976 4.963 3.351 -Process.info/2 250 4.295 2.226 -:proc_lib.proc_info/2 250 4.159 2.355 -anonymous fn/1 in ExPng.Chunks.ImageData.from_pixels/1 250 4.062 0.687 -:erlang.process_info/2 501 3.873 3.826 -ExPng.Image.Line."-filter_pass/3-lc$^0/1-0-"/2 1506 3.823 3.568 -Task.await/1 250 3.375 0.674 -:erlang.fun_info/2 500 3.000 3.000 -ExPng.RawData.from_file/1 1 2.796 0.014 -Task.await/2 250 2.701 1.306 -anonymous fn/5 in ExPng.Image.Line.filter_pass/3 2250 2.468 2.427 -ExPng.Color.pixel_bytesize/1 250 2.342 0.484 -ExPng.RawData.from_chunks/2 1 2.224 0.010 -ExPng.Color.pixel_bytesize/2 250 1.858 0.677 -ExPng.Chunks.ImageData.merge/1 1 1.806 0.061 -anonymous fn/2 in ExPng.Image.Line.filter_pass/3 1494 1.767 1.656 -:proc_lib.trans_init/3 250 1.759 1.759 -ExPng.Image.Line."-filter_pass/3-lc$^5/1-1-"/2 753 1.729 1.709 -ExPng.Image.Decoding.build_lines/1 1 1.723 0.006 -ExPng.Image.Decoding."-build_lines/1-lc$^0/1-0-"/2 251 1.702 1.320 -:zlib.dequeue_all_chunks/2 2 1.646 0.003 -:zlib.dequeue_all_chunks_1/3 47 1.643 0.249 -ExPng.Image.Line."-filter_pass/3-lc$^6/1-2-"/2 753 1.592 1.589 -Enum.reverse/1 248 1.557 0.741 -ExPng.Chunks.ImageData.inflate/1 1 1.447 0.016 -:erlang.demonitor/2 255 1.404 0.790 -:zlib.inflate/2 1 1.392 0.002 -:zlib.inflate/3 1 1.390 0.020 -:zlib.dequeue_next_chunk/2 47 1.280 0.070 -:erlang.monitor/2 254 1.256 1.256 -:lists.reverse/2 494 1.201 0.928 -:zlib."-fun.inflate_nif/4-"/4 12 1.138 0.054 -:lists.reverse/1 246 1.127 0.656 -:zlib.inflate_nif/4 12 1.084 1.084 -Task.get_callers/1 250 1.053 1.053 -:proc_lib.get_ancestors/0 250 0.996 0.996 -Enum.drop/2 245 0.981 0.360 -ExPng.Color.pixel_bitsize/2 251 0.901 0.635 -Enumerable.impl_for!/1 244 0.884 0.620 -anonymous fn/2 in Enum.take/2 732 0.825 0.766 -anonymous fn/2 in ExPng.Image.Line.filter_pass/3 750 0.821 0.788 -anonymous fn/1 in Stream.cycle/1 732 0.787 0.787 -Stream.cycle/1 244 0.739 0.456 -anonymous fn/2 in ExPng.Image.Line.build_pad_for_filter/1 488 0.625 0.625 -:erts_internal.flush_monitor_messages/3 251 0.613 0.613 -ExPng.RawData.to_file/2 1 0.534 0.004 -ExPng.Chunks.ImageData.to_bytes/1 1 0.449 0.003 -ExPng.Chunks.ImageData.deflate/1 1 0.441 0.008 -ExPng.Image.Line.new/2 250 0.342 0.342 -ExPng.RawData.parse_chunks/2 11 0.336 0.102 -:zlib.deflate/3 1 0.329 0.005 -ExPng.Color.to_bytesize/1 251 0.288 0.281 -anonymous fn/2 in ExPng.Chunks.ImageData.from_pixels/1 249 0.287 0.268 -Stream.unfold/2 244 0.283 0.283 -ExPng.Color.channels_for_color_mode/1 251 0.266 0.266 -Enumerable.impl_for/1 244 0.264 0.264 -Enum.to_list/1 244 0.247 0.246 -List.flatten/1 2 0.184 0.004 -:lists.flatten/1 2 0.180 0.004 -:lists.do_flatten/2 64 0.176 0.176 -File.read/1 1 0.169 0.008 -:file.call/2 2 0.162 0.008 -:file.read_file/1 1 0.159 0.005 -:file.check_and_call/2 1 0.153 0.006 -:gen_server.call/3 2 0.151 0.008 -ExPng.RawData.find_end/1 1 0.149 0.008 -ExPng.RawData.find_image_data/1 1 0.146 0.004 -ExPng.RawData.validate_crc/3 11 0.144 0.044 -ExPng.Chunks.ImageData.reduce_to_binary/1 2 0.144 0.005 -:gen.call/4 2 0.143 0.004 -Enum.split_with/2 1 0.142 0.012 -:gen.do_for_proc/2 2 0.139 0.007 -Enum.reject/2 2 0.136 0.005 -Enum.reject_list/2 17 0.131 0.094 -anonymous fn/4 in :gen.call/4 2 0.128 0.003 -:gen.do_call/4 2 0.125 0.029 -Enum."-split_with/2-lists^foldl/2-0-"/3 11 0.122 0.059 -ExPng.RawData.find_palette/2 1 0.113 0.007 -ExPng.RawData.find_chunk/2 2 0.111 0.004 -Enum.find/2 2 0.107 0.006 -:erlang.crc32/1 14 0.103 0.101 -Enum.find/3 2 0.101 0.004 -Enum.find_list/3 16 0.097 0.075 -ExPng.Chunks.from_type/2 11 0.075 0.028 -:zlib."-fun.deflate_nif/4-"/4 35 0.072 0.035 -File.write/2 1 0.071 0.001 -File.write/3 1 0.070 0.003 -anonymous fn/2 in ExPng.Chunks.ImageData.reduce_to_binary/1 14 0.067 0.054 -:file.write_file/3 1 0.065 0.003 -anonymous fn/3 in Enum.split_with/2 10 0.063 0.043 -:file.do_write_file/3 1 0.060 0.003 -:zlib.append_iolist/2 49 0.059 0.059 -ExPng.RawData.parse_ihdr/1 1 0.053 0.019 -:zlib.deflate_nif/4 35 0.037 0.036 -:file.open/2 1 0.034 0.005 -ExPng.Chunks.Ancillary.new/2 7 0.031 0.015 -anonymous fn/2 in ExPng.RawData.find_chunk/2 15 0.022 0.022 -:zlib.inflateInit/1 1 0.021 0.002 -:erlang.binary_to_atom/2 10 0.021 0.021 -anonymous fn/1 in ExPng.RawData.find_image_data/1 10 0.020 0.020 -:zlib.inflateInit/2 1 0.019 0.005 -:zlib.enqueue_input/2 2 0.019 0.007 -:zlib.exception_on_need_dict/2 1 0.015 0.007 -ExPng.Color.line_bytesize/1 1 0.015 0.003 -:zlib.inflateInit/3 1 0.014 0.006 -:zlib.deflateInit/1 1 0.014 0.001 -:zlib.deflateInit/2 1 0.013 0.001 -:file.write/2 1 0.013 0.002 -anonymous fn/2 in ExPng.RawData.find_end/1 8 0.013 0.013 -:zlib.deflateInit/6 1 0.012 0.006 -ExPng.Color.line_bytesize/3 1 0.012 0.004 -:zlib.open/0 2 0.011 0.003 -:file.check_args/1 6 0.011 0.011 -anonymous fn/2 in ExPng.RawData.find_palette/2 7 0.011 0.011 -ExPng.Chunks.Header.new/2 1 0.011 0.007 -:zlib.restore_progress/2 2 0.010 0.007 -:io.request/2 1 0.010 0.002 -:file.close/1 1 0.010 0.002 -:zlib.enqueue_input_1/2 2 0.009 0.005 -:erlang.send/3 2 0.009 0.009 -anonymous fn/2 in ExPng.Chunks.ImageData.deflate/1 9 0.009 0.009 -:zlib.open_nif/0 2 0.008 0.007 -:file.file_request/2 1 0.008 0.004 -:zlib.close/1 2 0.007 0.004 -:io.execute_request/2 1 0.007 0.004 -ExPng.Chunks.Header.to_bytes/1 1 0.007 0.004 -:zlib.inflateEnd/1 1 0.006 0.003 -:zlib.inflate_opts/0 1 0.005 0.003 -:zlib.inflateInit_nif/3 1 0.004 0.004 -:zlib.enqueue_nif/2 2 0.004 0.004 -:erlang.whereis/1 2 0.004 0.004 -ExPng.Chunks.ImageData.new/2 2 0.004 0.004 -:zlib.inflateEnd_nif/1 1 0.003 0.003 -:zlib.getStash_nif/1 2 0.003 0.003 -:zlib.deflate_opts/1 1 0.003 0.002 -:zlib.close_nif/1 2 0.003 0.003 -:zlib.arg_flush/1 2 0.003 0.003 -:zlib.arg_bitsz/1 2 0.003 0.003 -:lists.member/2 3 0.003 0.003 -:erlang.list_to_tuple/1 2 0.003 0.003 -:erlang.iolist_to_iovec/1 2 0.003 0.003 -IO.chardata_to_string/1 2 0.003 0.003 -anonymous fn/1 in ExPng.Chunks.ImageData.merge/1 2 0.003 0.003 -ExPng.Chunks.Header.validate_color_mode/1 2 0.003 0.003 -ExPng.Chunks.Header.validate_bit_depth/1 2 0.003 0.003 -ExPng.Chunks.End.to_bytes/1 1 0.003 0.002 -:zlib.proplist_get_value/3 1 0.002 0.002 -:zlib.deflateEnd/1 1 0.002 0.001 -:zlib.arg_eos_behavior/1 1 0.002 0.002 -:file.make_binary/1 2 0.002 0.002 -:file.file_name/1 2 0.002 0.002 -:zlib.deflateInit_nif/6 1 0.001 0.001 -:zlib.deflateEnd_nif/1 1 0.001 0.001 -:zlib.arg_strategy/1 1 0.001 0.001 -:zlib.arg_method/1 1 0.001 0.001 -:zlib.arg_mem/1 1 0.001 0.001 -:zlib.arg_level/1 1 0.001 0.001 -:io.io_request/2 1 0.001 0.001 -:fprof."-apply_start_stop/4-after$^1/0-0-"/3 1 0.001 0.001 -File.normalize_modes/2 1 0.001 0.001 -ExPng.Image.Encoding.build_header/1 1 0.001 0.001 -ExPng.Chunks.End.new/2 1 0.001 0.001 -:undefined 0 0.000 0.000 + CNT ACC (ms) OWN (ms) +Total 17049785 24807.334 25927.685 +:proc_lib.init_p/5 250 30036.389 11.937 +:suspend 6812 28916.038 0.000 +Enum.reduce/3 63241 25545.343 86.604 +Enum."-reduce/3-lists^foldl/2-0-"/3 187005 25543.441 1220.986 +:fprof.apply_start_stop/4 0 24807.334 0.011 +anonymous fn/0 in :elixir_compiler_1.__FILE__/1 1 24807.322 0.006 +ExPng.Image.from_file/1 1 24595.962 0.007 +ExPng.Image.Decoding.from_raw_data/1 1 24593.159 0.008 +ExPng.Image.Decoding.filter_pass/1 1 24232.146 0.007 +anonymous fn/3 in ExPng.Image.Decoding.filter_pass/1 250 24231.431 0.991 +ExPng.Image.Line.filter_pass/3 494 24228.098 3.118 +anonymous fn/5 in ExPng.Image.Line.filter_pass/3 60250 23229.351 361.923 +Enum.at/2 121010 21694.291 159.623 +Enum.at/3 121010 21511.970 289.344 +Enum.slice_any/3 121010 21200.968 311.051 +Enum.drop_list/2 15157116 20638.291 20520.332 +:proc_lib.init_p_do_apply/3 250 1374.889 3.379 +Task.Supervised.reply/4 250 1371.510 5.682 +Task.Supervised.reply/5 250 1342.217 5.609 +Task.Supervised.invoke_mfa/2 250 1322.160 3.176 +:erlang.apply/2 250 1318.984 2.022 +anonymous fn/1 in ExPng.Chunks.ImageData.from_pixels/1 250 1316.962 1.898 +ExPng.Chunks.ImageData.line_to_binary/1 250 1315.064 1.985 +Enum.reduce_range_inc/4 187482 1082.576 403.161 +anonymous fn/6 in ExPng.Image.Line.filter_pass/3 180750 669.604 453.072 +Enum.map/2 4 569.301 0.017 +Enum."-map/2-lists^map/1-0-"/2 756 569.284 6.778 +anonymous fn/2 in ExPng.Chunks.ImageData.line_to_binary/1 62500 399.111 372.924 +:garbage_collect 10406 369.906 369.906 +anonymous fn/2 in ExPng.Image.Decoding.from_raw_data/1 250 358.520 0.253 +ExPng.Image.Line.to_pixels/4 250 358.267 0.253 +ExPng.Image.Line."-to_pixels/4-lc$^5/1-9-"/1 62750 358.013 194.160 +Enum.take_list/2 121010 248.307 138.038 +ExPng.Image.to_file/2 1 211.354 0.003 +ExPng.Image.Encoding.to_raw_data/1 1 210.817 0.003 +ExPng.Chunks.ImageData.from_pixels/1 1 210.813 0.017 +ExPng.Image.Line.calculate_paeth_delta/3 180750 194.339 192.015 +anonymous fn/1 in ExPng.Chunks.ImageData.from_pixels/1 250 161.908 1.387 +Task.async/1 250 160.521 1.372 +Task.async/3 250 159.149 7.302 +Range.new/2 62494 153.599 72.968 +ExPng.Image.Line."-filter_pass/3-lc$^10/1-3-"/2 60491 146.847 143.366 +ExPng.Image.Line."-filter_pass/3-lc$^11/1-4-"/2 60491 144.221 132.324 +Task.Supervised.start_link/4 250 141.816 2.267 +:proc_lib.spawn_link/3 250 139.549 5.310 +anonymous fn/4 in ExPng.Image.Line.filter_pass/3 750 137.598 3.398 +Enum.with_index/1 244 135.473 0.256 +Enum.with_index/2 244 135.217 0.517 +Enum.do_with_index/2 61244 134.453 133.324 +ExPng.Pixel.rgb/3 62500 117.801 63.262 +anonymous fn/2 in ExPng.Image.Line.filter_pass/3 60250 65.790 63.714 +:erlang.spawn_link/3 250 62.861 62.861 +anonymous fn/3 in ExPng.Image.Line.filter_pass/3 1494 24.438 5.369 +Task.Supervised.initial_call/1 250 17.063 3.900 +:erlang.send/2 500 15.628 15.628 +ExPng.Image.Line.build_pad_for_filter/1 244 13.712 1.072 +Enum.take/2 244 9.287 0.800 +Process.put/2 500 9.255 6.372 +Enum.reduce/2 252 8.775 0.350 +Task.Supervised.get_initial_call/1 250 8.489 5.489 +Enum."-reduce/2-lists^foldl/2-0-"/3 2492 8.425 5.649 +Enumerable.reduce/3 244 7.368 0.790 +Task.Supervised.put_callers/1 250 6.548 1.967 +Task.get_owner/1 250 6.548 2.253 +:erlang.put/2 1000 6.393 6.393 +:proc_lib.get_my_name/0 250 6.385 2.226 +Enumerable.Function.reduce/3 244 5.694 0.359 +anonymous fn/4 in Stream.unfold/2 244 5.335 0.372 +anonymous fn/4 in ExPng.Image.Line.filter_pass/3 4482 5.277 5.139 +Stream.do_unfold/4 976 4.963 3.351 +Process.info/2 250 4.295 2.226 +:proc_lib.proc_info/2 250 4.159 2.355 +anonymous fn/1 in ExPng.Chunks.ImageData.from_pixels/1 250 4.062 0.687 +:erlang.process_info/2 501 3.873 3.826 +ExPng.Image.Line."-filter_pass/3-lc$^0/1-0-"/2 1506 3.823 3.568 +Task.await/1 250 3.375 0.674 +:erlang.fun_info/2 500 3.000 3.000 +ExPng.RawData.from_file/1 1 2.796 0.014 +Task.await/2 250 2.701 1.306 +anonymous fn/5 in ExPng.Image.Line.filter_pass/3 2250 2.468 2.427 +ExPng.Color.pixel_bytesize/1 250 2.342 0.484 +ExPng.RawData.from_chunks/2 1 2.224 0.010 +ExPng.Color.pixel_bytesize/2 250 1.858 0.677 +ExPng.Chunks.ImageData.merge/1 1 1.806 0.061 +anonymous fn/2 in ExPng.Image.Line.filter_pass/3 1494 1.767 1.656 +:proc_lib.trans_init/3 250 1.759 1.759 +ExPng.Image.Line."-filter_pass/3-lc$^5/1-1-"/2 753 1.729 1.709 +ExPng.Image.Decoding.build_lines/1 1 1.723 0.006 +ExPng.Image.Decoding."-build_lines/1-lc$^0/1-0-"/2 251 1.702 1.320 +:zlib.dequeue_all_chunks/2 2 1.646 0.003 +:zlib.dequeue_all_chunks_1/3 47 1.643 0.249 +ExPng.Image.Line."-filter_pass/3-lc$^6/1-2-"/2 753 1.592 1.589 +Enum.reverse/1 248 1.557 0.741 +ExPng.Chunks.ImageData.inflate/1 1 1.447 0.016 +:erlang.demonitor/2 255 1.404 0.790 +:zlib.inflate/2 1 1.392 0.002 +:zlib.inflate/3 1 1.390 0.020 +:zlib.dequeue_next_chunk/2 47 1.280 0.070 +:erlang.monitor/2 254 1.256 1.256 +:lists.reverse/2 494 1.201 0.928 +:zlib."-fun.inflate_nif/4-"/4 12 1.138 0.054 +:lists.reverse/1 246 1.127 0.656 +:zlib.inflate_nif/4 12 1.084 1.084 +Task.get_callers/1 250 1.053 1.053 +:proc_lib.get_ancestors/0 250 0.996 0.996 +Enum.drop/2 245 0.981 0.360 +ExPng.Color.pixel_bitsize/2 251 0.901 0.635 +Enumerable.impl_for!/1 244 0.884 0.620 +anonymous fn/2 in Enum.take/2 732 0.825 0.766 +anonymous fn/2 in ExPng.Image.Line.filter_pass/3 750 0.821 0.788 +anonymous fn/1 in Stream.cycle/1 732 0.787 0.787 +Stream.cycle/1 244 0.739 0.456 +anonymous fn/2 in ExPng.Image.Line.build_pad_for_filter/1 488 0.625 0.625 +:erts_internal.flush_monitor_messages/3 251 0.613 0.613 +ExPng.RawData.to_file/2 1 0.534 0.004 +ExPng.Chunks.ImageData.to_bytes/1 1 0.449 0.003 +ExPng.Chunks.ImageData.deflate/1 1 0.441 0.008 +ExPng.Image.Line.new/2 250 0.342 0.342 +ExPng.RawData.parse_chunks/2 11 0.336 0.102 +:zlib.deflate/3 1 0.329 0.005 +ExPng.Color.to_bytesize/1 251 0.288 0.281 +anonymous fn/2 in ExPng.Chunks.ImageData.from_pixels/1 249 0.287 0.268 +Stream.unfold/2 244 0.283 0.283 +ExPng.Color.channels_for_color_mode/1 251 0.266 0.266 +Enumerable.impl_for/1 244 0.264 0.264 +Enum.to_list/1 244 0.247 0.246 +List.flatten/1 2 0.184 0.004 +:lists.flatten/1 2 0.180 0.004 +:lists.do_flatten/2 64 0.176 0.176 +File.read/1 1 0.169 0.008 +:file.call/2 2 0.162 0.008 +:file.read_file/1 1 0.159 0.005 +:file.check_and_call/2 1 0.153 0.006 +:gen_server.call/3 2 0.151 0.008 +ExPng.RawData.find_end/1 1 0.149 0.008 +ExPng.RawData.find_image_data/1 1 0.146 0.004 +ExPng.RawData.validate_crc/3 11 0.144 0.044 +ExPng.Chunks.ImageData.reduce_to_binary/1 2 0.144 0.005 +:gen.call/4 2 0.143 0.004 +Enum.split_with/2 1 0.142 0.012 +:gen.do_for_proc/2 2 0.139 0.007 +Enum.reject/2 2 0.136 0.005 +Enum.reject_list/2 17 0.131 0.094 +anonymous fn/4 in :gen.call/4 2 0.128 0.003 +:gen.do_call/4 2 0.125 0.029 +Enum."-split_with/2-lists^foldl/2-0-"/3 11 0.122 0.059 +ExPng.RawData.find_palette/2 1 0.113 0.007 +ExPng.RawData.find_chunk/2 2 0.111 0.004 +Enum.find/2 2 0.107 0.006 +:erlang.crc32/1 14 0.103 0.101 +Enum.find/3 2 0.101 0.004 +Enum.find_list/3 16 0.097 0.075 +ExPng.Chunks.from_type/2 11 0.075 0.028 +:zlib."-fun.deflate_nif/4-"/4 35 0.072 0.035 +File.write/2 1 0.071 0.001 +File.write/3 1 0.070 0.003 +anonymous fn/2 in ExPng.Chunks.ImageData.reduce_to_binary/1 14 0.067 0.054 +:file.write_file/3 1 0.065 0.003 +anonymous fn/3 in Enum.split_with/2 10 0.063 0.043 +:file.do_write_file/3 1 0.060 0.003 +:zlib.append_iolist/2 49 0.059 0.059 +ExPng.RawData.parse_ihdr/1 1 0.053 0.019 +:zlib.deflate_nif/4 35 0.037 0.036 +:file.open/2 1 0.034 0.005 +ExPng.Chunks.Ancillary.new/2 7 0.031 0.015 +anonymous fn/2 in ExPng.RawData.find_chunk/2 15 0.022 0.022 +:zlib.inflateInit/1 1 0.021 0.002 +:erlang.binary_to_atom/2 10 0.021 0.021 +anonymous fn/1 in ExPng.RawData.find_image_data/1 10 0.020 0.020 +:zlib.inflateInit/2 1 0.019 0.005 +:zlib.enqueue_input/2 2 0.019 0.007 +:zlib.exception_on_need_dict/2 1 0.015 0.007 +ExPng.Color.line_bytesize/1 1 0.015 0.003 +:zlib.inflateInit/3 1 0.014 0.006 +:zlib.deflateInit/1 1 0.014 0.001 +:zlib.deflateInit/2 1 0.013 0.001 +:file.write/2 1 0.013 0.002 +anonymous fn/2 in ExPng.RawData.find_end/1 8 0.013 0.013 +:zlib.deflateInit/6 1 0.012 0.006 +ExPng.Color.line_bytesize/3 1 0.012 0.004 +:zlib.open/0 2 0.011 0.003 +:file.check_args/1 6 0.011 0.011 +anonymous fn/2 in ExPng.RawData.find_palette/2 7 0.011 0.011 +ExPng.Chunks.Header.new/2 1 0.011 0.007 +:zlib.restore_progress/2 2 0.010 0.007 +:io.request/2 1 0.010 0.002 +:file.close/1 1 0.010 0.002 +:zlib.enqueue_input_1/2 2 0.009 0.005 +:erlang.send/3 2 0.009 0.009 +anonymous fn/2 in ExPng.Chunks.ImageData.deflate/1 9 0.009 0.009 +:zlib.open_nif/0 2 0.008 0.007 +:file.file_request/2 1 0.008 0.004 +:zlib.close/1 2 0.007 0.004 +:io.execute_request/2 1 0.007 0.004 +ExPng.Chunks.Header.to_bytes/1 1 0.007 0.004 +:zlib.inflateEnd/1 1 0.006 0.003 +:zlib.inflate_opts/0 1 0.005 0.003 +:zlib.inflateInit_nif/3 1 0.004 0.004 +:zlib.enqueue_nif/2 2 0.004 0.004 +:erlang.whereis/1 2 0.004 0.004 +ExPng.Chunks.ImageData.new/2 2 0.004 0.004 +:zlib.inflateEnd_nif/1 1 0.003 0.003 +:zlib.getStash_nif/1 2 0.003 0.003 +:zlib.deflate_opts/1 1 0.003 0.002 +:zlib.close_nif/1 2 0.003 0.003 +:zlib.arg_flush/1 2 0.003 0.003 +:zlib.arg_bitsz/1 2 0.003 0.003 +:lists.member/2 3 0.003 0.003 +:erlang.list_to_tuple/1 2 0.003 0.003 +:erlang.iolist_to_iovec/1 2 0.003 0.003 +IO.chardata_to_string/1 2 0.003 0.003 +anonymous fn/1 in ExPng.Chunks.ImageData.merge/1 2 0.003 0.003 +ExPng.Chunks.Header.validate_color_mode/1 2 0.003 0.003 +ExPng.Chunks.Header.validate_bit_depth/1 2 0.003 0.003 +ExPng.Chunks.End.to_bytes/1 1 0.003 0.002 +:zlib.proplist_get_value/3 1 0.002 0.002 +:zlib.deflateEnd/1 1 0.002 0.001 +:zlib.arg_eos_behavior/1 1 0.002 0.002 +:file.make_binary/1 2 0.002 0.002 +:file.file_name/1 2 0.002 0.002 +:zlib.deflateInit_nif/6 1 0.001 0.001 +:zlib.deflateEnd_nif/1 1 0.001 0.001 +:zlib.arg_strategy/1 1 0.001 0.001 +:zlib.arg_method/1 1 0.001 0.001 +:zlib.arg_mem/1 1 0.001 0.001 +:zlib.arg_level/1 1 0.001 0.001 +:io.io_request/2 1 0.001 0.001 +:fprof."-apply_start_stop/4-after$^1/0-0-"/3 1 0.001 0.001 +File.normalize_modes/2 1 0.001 0.001 +ExPng.Image.Encoding.build_header/1 1 0.001 0.001 +ExPng.Chunks.End.new/2 1 0.001 0.001 +:undefined 0 0.000 0.000 diff --git a/test/ex_png/chunks/image_data_test.exs b/test/ex_png/chunks/image_data_test.exs new file mode 100644 index 0000000..8dcb74a --- /dev/null +++ b/test/ex_png/chunks/image_data_test.exs @@ -0,0 +1,62 @@ +defmodule ExPng.Chunks.ImageDataTest do + use ExUnit.Case + use ExPng.Constants + + alias ExPng.{Image, Pixel} + alias ExPng.Chunks.{Header, ImageData} + + setup do + image = %Image{ + pixels: [ + [Pixel.white(), Pixel.black()], + [Pixel.rgba(100, 200, 100, 100), Pixel.rgb(100, 200, 255)] + ] + } + {:ok, image: image} + end + + describe "from_pixels" do + test "grayscale, bit depth 1", context do + {image_data, _} = image_data_from_pixels(context.image, 1, @grayscale) + assert image_data.data == <<0, 2, 0, 1>> + end + + test "grayscale, bit depth 8", context do + {image_data, _} = image_data_from_pixels(context.image, 8, @grayscale) + assert image_data.data == <<0, 255, 0, 0, 100, 255>> + end + + test "indexed, bit_depth 1", context do + {image_data, palette} = image_data_from_pixels(context.image, 2, @indexed) + assert image_data.data == <<0, 16, 0, 176>> + assert palette.palette == [ + Pixel.white(), + Pixel.black(), + Pixel.rgba(100, 200, 100, 100), + Pixel.rgb(100, 200, 255) + ] + end + + test "grayscale alpha, bit depth 8", context do + {image_data, _} = image_data_from_pixels(context.image, 8, @grayscale_alpha) + assert image_data.data == <<0, 255, 255, 0, 255, 0, 100, 100, 255, 255>> + end + + test "truecolor alpha, bit depth 8", context do + {image_data, _} = image_data_from_pixels(context.image, 8, @truecolor_alpha) + assert image_data.data == + << + 0, 255, 255, 255, 255, 0, 0, 0, 255, + 0, 100, 200, 100, 100, 100, 200, 255, 255 + >> + end + end + + defp image_data_from_pixels(image, bit_depth, color_mode) do + header = %Header{ + bit_depth: bit_depth, + color_mode: color_mode + } + ImageData.from_pixels(image, header) + end +end diff --git a/test/ex_png/image_test.exs b/test/ex_png/image_test.exs index 7c9c6d1..fd5794b 100644 --- a/test/ex_png/image_test.exs +++ b/test/ex_png/image_test.exs @@ -5,26 +5,14 @@ defmodule ExPng.ImageTest do alias ExPng.{Image, Pixel} describe "round trip" do - test "for grayscale images" do - for file <- Path.wildcard("test/png_suite/basic/basn0g*.png") do + test "for non-interlaced images" do + for file <- Path.wildcard("test/png_suite/basic/basn*.png") do assert_round_trip(file) end end - test "for grayscale interlaced images" do - for file <- Path.wildcard("test/png_suite/basic/basi0g*.png") do - assert_round_trip(file) - end - end - - test "for truecolor images" do - for file <- Path.wildcard("test/png_suite/basic/basn2c*.png") do - assert_round_trip(file) - end - end - - test "for paletted images" do - for file <- Path.wildcard("test/png_suite/basic/basn3p*.png") do + test "for interlaced images" do + for file <- Path.wildcard("test/png_suite/basic/basi*.png") do assert_round_trip(file) end end diff --git a/test/png_suite/filtering/f99n0g04.png b/test/png_suite/filtering/f99n0g04.png new file mode 100644 index 0000000000000000000000000000000000000000..0b521c1d56ac6ba14d82547eea5c87dae391cfba GIT binary patch literal 426 zcmV;b0agBqP)R*H$WiHScT#vd?>UqJiKVd^cv0p+pyQ zGH|gKM+__s5&6}tHkZ;`DS5Y9+rZhQ zwP@N_D-FoTR{3vH