-
Notifications
You must be signed in to change notification settings - Fork 29
Expand file tree
/
Copy pathicowdx.lua
More file actions
159 lines (152 loc) · 4.05 KB
/
icowdx.lua
File metadata and controls
159 lines (152 loc) · 4.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
-- icowdx.lua (cross-platform)
-- 2021.04.18
--[[
Getting some info from Windows icons (ICO images):
- the number of images;
- a list of available sizes;
- plugin can check that the specific size is available (see "aun" below).
]]
local aun = {"16x16", "24x24", "32x32", "48x48", "64x64", "96x96", "128x128", "256x256", "512x512"}
local ar = {}
local filename = ''
function ContentGetSupportedField(FieldIndex)
if FieldIndex == 0 then
return "Number of images", "", 1
elseif FieldIndex == 1 then
return "List of sizes", "", 8
elseif FieldIndex == 2 then
return "Has", table.concat(aun, '|'), 6
end
return "", "", 0
end
function ContentGetDefaultSortOrder(FieldIndex)
return 1; --or -1
end
function ContentGetDetectString()
return 'EXT="ICO"'
end
function ContentGetValue(FileName, FieldIndex, UnitIndex, flags)
if FieldIndex > 2 then return nil end
local t
if filename ~= FileName then
t = string.lower(SysUtils.ExtractFileExt(FileName))
if t ~= '.ico' then return nil end
local at = SysUtils.FileGetAttr(FileName)
if at < 0 then return nil end
if math.floor(at / 0x00000010) % 2 ~= 0 then return nil end
local h = io.open(FileName, 'rb')
if h == nil then return nil end
local d = h:read(4)
if BinToNumLE(d, 1, 4) ~= 0x00010000 then
h:close()
return nil
end
ar = {0, ''}
d = h:read(2)
ar[1] = BinToNumLE(d, 1, 2)
if ar[1] > 0 then
local c = ar[1]
local al1 = {}
local al2 = {}
local al3 = {}
local nw, nh, nc, w
while true do
if c == 0 then break end
-- width
d = h:read(2)
nw = string.byte(d, 1)
-- height
nh = string.byte(d, 2)
if (nw == 0x00) and (nh == 0x00) then
-- >= 256px
h:seek('cur', 10)
d = h:read(4)
nc = h:seek()
nw = BinToNumLE(d, 1, 4)
h:seek('set', nw)
d = h:read(8)
nw = BinToNumBE(d, 1, 4)
nh = BinToNumBE(d, 5, 8)
if (nw == 0x89504e47) and (nh == 0x0d0a1a0a) then
h:seek('cur', 4)
d = h:read(4)
if d == 'IHDR' then
d = h:read(8)
-- width
nw = BinToNumBE(d, 1, 4)
-- height
nh = BinToNumBE(d, 5, 8)
end
else
nw, nh = 0x0100, 0x0100
end
h:seek('set', nc)
else
h:seek('cur', 14)
end
w = tonumber(nw, 10)
t = w .. 'x' .. tonumber(nh, 10)
if w > 99 then
al3[#al3 + 1] = t
elseif w > 9 then
al2[#al2 + 1] = t
else
al1[#al1 + 1] = t
end
c = c - 1
end
h:close()
local sr = '; '
if #al1 > 0 then
table.sort(al1)
sr = sr .. al1[1] .. '; '
for i = 2, #al1 do
if al1[i] ~= al1[i - 1] then sr = sr .. al1[i] .. '; ' end
end
end
if #al2 > 0 then
table.sort(al2)
sr = sr .. al2[1] .. '; '
for i = 2, #al2 do
if al2[i] ~= al2[i - 1] then sr = sr .. al2[i] .. '; ' end
end
end
if #al3 > 0 then
table.sort(al3)
sr = sr .. al3[1] .. '; '
for i = 2, #al3 do
if al3[i] ~= al3[i - 1] then sr = sr .. al3[i] .. '; ' end
end
end
ar[2] = sr
else
return nil
end
filename = FileName
end
if FieldIndex == 0 then
return ar[1]
elseif FieldIndex == 1 then
if string.len(ar[2]) > 4 then return string.sub(ar[2], 3, -3) end
elseif FieldIndex == 2 then
if aun[UnitIndex + 1] ~= nil then
t = string.find(ar[2], '; ' .. aun[UnitIndex + 1] .. ';', 1, true)
if t == nil then return false else return true end
end
end
return nil
end
function BinToNumLE(d, n1, n2)
local r = ''
for i = n1, n2 do
r = string.format('%02x', string.byte(d, i)) .. r
end
return tonumber('0x' .. r)
end
function BinToNumBE(d, n1, n2)
local r = ''
for i = n1, n2 do
r = r .. string.format('%02x', string.byte(d, i))
end
return tonumber('0x' .. r)
end