diff options
Diffstat (limited to 'lib/percept/src/egd_png.erl')
-rwxr-xr-x | lib/percept/src/egd_png.erl | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/lib/percept/src/egd_png.erl b/lib/percept/src/egd_png.erl new file mode 100755 index 0000000000..3a0aaeef31 --- /dev/null +++ b/lib/percept/src/egd_png.erl @@ -0,0 +1,104 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + + +%% This code was originally written by Dan Gudmundsson for png-handling in +%% wings3d (e3d__png). +%% +%% @doc egd +%% + +-module(egd_png). + +-export([binary/3]). + +-include("egd.hrl"). + +-define(MAGIC, 137,$P,$N,$G,$\r,$\n,26,$\n). + +-define(GREYSCALE, 0). +-define(TRUECOLOUR, 2). +-define(INDEXED, 3). +-define(GREYSCALE_A, 4). +-define(TRUECOLOUR_A,6). + +-define(MAX_WBITS,15). + +-define(CHUNK, 240). + +-define(get4p1(Idx),((Idx) bsr 4)). +-define(get4p2(Idx),((Idx) band 16#0F)). +-define(get2p1(Idx),((Idx) bsr 6)). +-define(get2p2(Idx),(((Idx) bsr 4) band 3)). +-define(get2p3(Idx),(((Idx) bsr 2) band 3)). +-define(get2p4(Idx),((Idx) band 3)). +-define(get1p1(Idx),((Idx) bsr 7)). +-define(get1p2(Idx),(((Idx) bsr 6) band 1)). +-define(get1p3(Idx),(((Idx) bsr 5) band 1)). +-define(get1p4(Idx),(((Idx) bsr 4) band 1)). +-define(get1p5(Idx),(((Idx) bsr 3) band 1)). +-define(get1p6(Idx),(((Idx) bsr 2) band 1)). +-define(get1p7(Idx),(((Idx) bsr 1) band 1)). +-define(get1p8(Idx),((Idx) band 1)). + +binary(W, H, Bitmap) when is_binary(Bitmap) -> + Z = zlib:open(), + Binary = bitmap2png(W, H, Bitmap, Z), + zlib:close(Z), + Binary. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Begin Tainted + +bitmap2png(W, H, Bitmap,Z) -> + HDR = create_chunk(<<"IHDR",W:32,H:32,8:8,(png_type(r8g8b8)):8,0:8,0:8,0:8>>,Z), + DATA = create_chunk(["IDAT",compress_image(0,3*W,Bitmap,[])],Z), + END = create_chunk(<<"IEND">>,Z), + list_to_binary([?MAGIC,HDR,DATA,END]). + +compress_image(I,RowLen, Bin, Acc) -> + Pos = I*RowLen, + case Bin of + <<_:Pos/binary,Row:RowLen/binary,_/binary>> -> + Filtered = filter_row(Row,RowLen), + compress_image(I+1,RowLen,Bin,[Filtered|Acc]); + _ when Pos == size(Bin) -> + Filtered = list_to_binary(lists:reverse(Acc)), + Compressed = zlib:compress(Filtered), + Compressed + end. + +filter_row(Row,_RowLen) -> + [0,Row]. + +% dialyzer warnings +%png_type(g8) -> ?GREYSCALE; +%png_type(a8) -> ?GREYSCALE; +%png_type(r8g8b8a8) -> ?TRUECOLOUR_A; +png_type(r8g8b8) -> ?TRUECOLOUR. + +create_chunk(Bin,Z) when is_list(Bin) -> + create_chunk(list_to_binary(Bin),Z); +create_chunk(Bin,Z) when is_binary(Bin) -> + Sz = size(Bin)-4, + Crc = zlib:crc32(Z,Bin), + <<Sz:32,Bin/binary,Crc:32>>. + +% End tainted |