Skip to content

Commit a5ba0fd

Browse files
committed
FEAT: added a simple codec for decoding/encoding ICO files
(cherry picked from commit fd67a59)
1 parent ea3aab8 commit a5ba0fd

File tree

9 files changed

+132
-0
lines changed

9 files changed

+132
-0
lines changed

make/rebol3.nest

+7
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,12 @@ include-codec-tar: [mezz-lib-files: %mezz/codec-tar.reb ]
447447
; other codecs:
448448
include-codec-bbcode: [mezz-lib-files: %mezz/codec-bbcode.reb ]
449449
include-codec-html-entities: [mezz-lib-files: %mezz/codec-html-entities.reb]
450+
include-codec-ico: [
451+
; at this moment ico can be encoded only from pngs!
452+
:include-native-png-codec
453+
mezz-lib-files: %mezz/codec-ico.reb
454+
mezz-lib-files: %mezz/codec-image-ext.reb ; png/size? function
455+
]
450456
include-codec-json: [mezz-lib-files: %mezz/codec-json.reb ]
451457
include-codec-xml: [mezz-lib-files: %mezz/codec-xml.reb ]
452458
include-codec-swf: [mezz-lib-files: %mezz/codec-swf.reb ]
@@ -505,6 +511,7 @@ include-rebol-bulk: [
505511
:include-codec-tar
506512
:include-codec-bbcode
507513
:include-codec-html-entities
514+
:include-codec-ico
508515
:include-codec-json
509516
:include-codec-xml
510517
:include-codec-swf

src/mezz/codec-ico.reb

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
REBOL [
2+
title: "REBOL 3 codec for ICO files"
3+
name: 'codec-ico
4+
author: rights: "Oldes"
5+
version: 0.0.1
6+
history: [6-Mar-2021 "Oldes" {Initial version}]
7+
]
8+
9+
system/options/log/ico: 2
10+
register-codec [
11+
name: 'ico
12+
title: "Windows icon or cursor file"
13+
suffixes: [%.ico %.cur]
14+
15+
decode: function [
16+
{Extract content of the ICO file}
17+
data [binary! file! url!]
18+
][
19+
unless binary? data [ data: read data ]
20+
sys/log/info 'ICO ["^[[1;32mDecode ICO data^[[m (^[[1m" length? data "^[[mbytes )"]
21+
bin: binary data
22+
;- ICONDIR:
23+
binary/read bin [ tmp: UI16LE type: UI16LE num: UI16LE ]
24+
unless all [tmp = 0 any [type = 1 type = 2] ] [return none]
25+
icons: copy []
26+
repeat n num [
27+
binary/read bin [
28+
width: UI8
29+
height: UI8
30+
colors: UI8
31+
UI8
32+
planes: UI16LE
33+
bpp: UI16LE
34+
size: UI32LE
35+
ofs: UI32LE
36+
]
37+
binary/read bin [
38+
pos: INDEX
39+
ATz :ofs
40+
data: BYTES :size
41+
AT :pos
42+
]
43+
if width = 0 [width: 256]
44+
if height = 0 [height: 256]
45+
sys/log/more 'ICO ["Image^[[1;33m" n "^[[0;36mbpp:^[[33m" bpp "^[[36mcolors:^[[33m" colors "^[[36msize:^[[33m" as-pair width height]
46+
append/only icons reduce [width bpp data]
47+
]
48+
icons
49+
]
50+
encode: function [
51+
data [block!]
52+
][
53+
out: binary 30000
54+
images: copy []
55+
parse data [
56+
some [
57+
set file: file! (
58+
bin: read/binary file
59+
if size: codecs/png/size? bin [
60+
append/only images reduce ['png to integer! size/1 32 bin]
61+
]
62+
)
63+
]
64+
]
65+
imgs: length? images
66+
offset: 6 + (imgs * 16)
67+
img-data: clear #{}
68+
binary/write out [UI16LE 0 UI16LE 1 UI16LE :imgs]
69+
70+
forall images [
71+
set [type: size: bpp: bin:] images/1
72+
bytes: length? bin
73+
if size = 256 [size: 0]
74+
binary/write out [
75+
UI8 :size
76+
UI8 :size
77+
UI16LE 0 ;colors
78+
UI16LE 0 ;planes
79+
UI16LE :bpp
80+
UI32LE :bytes
81+
UI32LE :offset
82+
]
83+
append img-data bin
84+
offset: offset + length? bin
85+
]
86+
binary/write out img-data
87+
copy out/buffer
88+
]
89+
90+
identify: function [data [binary!]][
91+
parse b [#{0000} [#{0100} | #{0200}] to end] ;.ico or .cur
92+
]
93+
]

src/tests/units/codecs-test.r3

+32
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,38 @@ if find codecs 'unixtime [
280280
===end-group===
281281
]
282282

283+
if all [
284+
find codecs 'ICO
285+
find codecs 'PNG
286+
][
287+
===start-group=== "ICO codec"
288+
--test-- "ICO encode"
289+
--assert all [
290+
binary? bin: try [codecs/ico/encode [
291+
%units/files/ico/icon_16.png
292+
%units/files/ico/icon_24.png
293+
%units/files/ico/icon_32.png
294+
%units/files/ico/icon_48.png
295+
%units/files/ico/icon_128.png
296+
]]
297+
#{35FB14C61A0E81F4FC525B9243116D3C} = checksum bin 'md5
298+
]
299+
--test-- "ICO decode"
300+
--assert all [
301+
block? ico: try [codecs/ico/decode %units/files/test.ico]
302+
ico/1/1 = 16 ico/1/2 = 32 binary? ico/1/3
303+
ico/2/1 = 24 ico/2/2 = 32 binary? ico/2/3
304+
ico/3/1 = 32 ico/3/2 = 32 binary? ico/3/3
305+
ico/4/1 = 48 ico/4/2 = 32 binary? ico/4/3
306+
ico/5/1 = 128 ico/5/2 = 32 binary? ico/5/3
307+
]
308+
--assert all [
309+
image? img: try [decode 'png ico/1/3]
310+
16x16 = img/size
311+
]
312+
===end-group===
313+
]
314+
283315
if find codecs 'JSON [
284316
===start-group=== "JSON codec"
285317
--test-- "JSON encode/decode"
2.12 KB
Loading

src/tests/units/files/ico/icon_16.png

1.54 KB
Loading

src/tests/units/files/ico/icon_24.png

1.77 KB
Loading

src/tests/units/files/ico/icon_32.png

1.82 KB
Loading

src/tests/units/files/ico/icon_48.png

1.83 KB
Loading

src/tests/units/files/test.ico

9.17 KB
Binary file not shown.

0 commit comments

Comments
 (0)