Skip to content

Instantly share code, notes, and snippets.

@m-2k
Last active October 5, 2015 15:24
Show Gist options
  • Save m-2k/d6fb6237e1a3e3670623 to your computer and use it in GitHub Desktop.
Save m-2k/d6fb6237e1a3e3670623 to your computer and use it in GitHub Desktop.
-module(bpg_info).
-author('Andrey Martemyanov').
-compile(export_all).
-record(bpg_info, {
pixel_format,
alpha,
bit_depth,
color_space,
extension_present,
limited_range,
animation,
picture_width,
picture_height
}).
bpg_info({filename,FileName}) ->
case file:open(FileName, [read,raw,binary]) of
{ok, IoDevice} ->
case file:read(IoDevice, 14) of
{ok,Data} -> file:close(IoDevice), bpg_info({data,Data});
eof -> file:close(IoDevice), {error,small_file};
{error, Reason} -> file:close(IoDevice), {error,Reason}
end;
_ -> {error,wrong_file_name}
end;
bpg_info({data,<<Header:14/binary,_/binary>>}) ->
FileMagic = 16#425047fb, % "BPGû"
case Header of
<<FileMagic:32,PixelFormat:3,Alpha1Flag:1,BitDepthMinus8:4,ColorSpace:4,
ExtensionPresentFlag:1,Alpha2Flag:1,LimitedRangeFlag:1,AnimationFlag:1,
PictureDimensions:8/binary>> ->
{ok,PictureWidth,PictureHeight}=bpg_dimensions(PictureDimensions),
{ok,#bpg_info{
pixel_format=case PixelFormat of
0 -> grayscale;
1 -> '4:2:0-jpeg';
2 -> '4:2:2-jpeg';
3 -> '4:4:4';
4 -> '4:2:0-mpeg2';
5 -> '4:2:2-mpeg2' end,
alpha=case {Alpha1Flag,Alpha2Flag} of
{0,0} -> no_alpha;
{1,0} -> alpha_color_not_premultiplied;
{1,1} -> alpha_color_premultiplied;
{0,1} -> alpha_CMYK end,
bit_depth=BitDepthMinus8+8,
color_space=case ColorSpace of
0 -> {'YCbCr','BT 601', 5};
1 -> {'RGB', undefined,unedfined};
2 -> {'YCgCo', undefined, 8};
3 -> {'YCbCr', 'BT 709', 1};
4 -> {'YCbCr', 'BT 2020', 9};
5 -> { reserved, 'BT 2020', undefined};
_ -> { reserved, undefined, undefined} end,
extension_present=case ExtensionPresentFlag of 0 -> false; 1 -> true end,
limited_range=case LimitedRangeFlag of 0 -> false; 1 -> true end,
animation=case AnimationFlag of 0 -> false; 1 -> true end,
picture_width=PictureWidth,
picture_height=PictureHeight}};
_ -> {error,wrong_bpg_header}
end.
bpg_dimensions(Bytes) ->
ReadUE7 = fun ReadUE7(<<1:1,Byte7:7,Tail/binary>>,Number) ->
ReadUE7(Tail,<<Number/bitstring,Byte7:7>>);
ReadUE7(<<0:1,Byte7:7,Tail/binary>>,Number) ->
Size=bit_size(Number)+7,
<<UE7:Size>> = <<Number/bitstring,Byte7:7>>,
{ok,UE7,Tail}
end,
ReadUE7Array = fun ReadUE7Array(<<>>,_,Acc) -> {error,wrong_data};
ReadUE7Array(_,0,Acc) -> Acc;
ReadUE7Array(ByteList,Count,Acc) ->
{ok,Num,Tail}=ReadUE7(ByteList,<<>>),
ReadUE7Array(Tail,Count-1,[Num|Acc])
end,
case ReadUE7Array(Bytes,2,[]) of
[H,W] -> {ok,W,H};
Error -> Error end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment