Skip to content

Commit 45985ce

Browse files
authored
Merge pull request #27 from EmbroidePy/0.1.20
+Hus Reader
2 parents aa6994c + ce5d5d2 commit 45985ce

File tree

5 files changed

+442
-0
lines changed

5 files changed

+442
-0
lines changed
Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
/*
2+
* To change this license header, choose License Headers in Project Properties.
3+
* To change this template file, choose Tools | Templates
4+
* and open the template in the editor.
5+
*/
6+
package org.embroideryio.embroideryio;
7+
8+
import java.nio.ByteBuffer;
9+
import java.util.Arrays;
10+
11+
12+
/**
13+
*
14+
* @author Tat
15+
*/
16+
public class EmbCompress {
17+
public static ByteBuffer expand(ByteBuffer data, int uncompressed_size) {
18+
EmbCompress compress = new EmbCompress();
19+
return compress.decompress(data, uncompressed_size);
20+
}
21+
22+
int bit_position = 0;
23+
ByteBuffer input_data = null;
24+
int block_elements = -1;
25+
Huffman character_huffman = null;
26+
Huffman distance_huffman = null;
27+
28+
public EmbCompress() {
29+
}
30+
31+
public int get_bits(int start_pos_in_bits, int length) {
32+
int end_pos_in_bits = start_pos_in_bits + length - 1;
33+
int start_pos_in_bytes = start_pos_in_bits / 8;
34+
int end_pos_in_bytes = end_pos_in_bits / 8;
35+
int value = 0;
36+
for (int i = start_pos_in_bytes, s = end_pos_in_bytes + 1; i < s; i++) {
37+
value <<= 8;
38+
try {
39+
value |= input_data.get(i) & 0xFF;
40+
}
41+
catch (IndexOutOfBoundsException e) {
42+
//pass
43+
}
44+
}
45+
int unused_bits_right_of_sample = (8 - (end_pos_in_bits + 1) % 8) % 8;
46+
int mask_sample_bits = (1 << length) - 1;
47+
int original = (value >> unused_bits_right_of_sample) & mask_sample_bits;
48+
return original;
49+
}
50+
51+
public int pop(int bit_count) {
52+
int value = peek(bit_count);
53+
slide(bit_count);
54+
return value;
55+
}
56+
57+
public int peek(int bit_count) {
58+
return get_bits(bit_position, bit_count);
59+
}
60+
61+
public void slide(int bit_count) {
62+
bit_position += bit_count;
63+
}
64+
65+
public int read_variable_length() {
66+
int m = pop(3);
67+
if (m != 7) {
68+
return m;
69+
}
70+
for (int q = 0, r = 13; q < r; q++) {
71+
// max read is 16 bit, 3 bits already used. It can't exceed 16-3
72+
int s = pop(1);
73+
if (s == 1) {
74+
m += 1;
75+
}
76+
else {
77+
break;
78+
}
79+
}
80+
return m;
81+
}
82+
83+
public Huffman load_character_length_huffman() {
84+
int count = pop(5);
85+
if (count == 0) {
86+
int v = pop(5);
87+
return new Huffman(v); // value=v
88+
}
89+
else {
90+
int[] huffman_code_lengths = new int[count];
91+
int index = 0;
92+
while (index < count) {
93+
if (index == 3) { // Special index 3, skip up to 3 elements.
94+
index += pop(2);
95+
}
96+
huffman_code_lengths[index] = read_variable_length();
97+
index += 1;
98+
}
99+
Huffman huffman = new Huffman(huffman_code_lengths, 8);
100+
huffman.build_table();
101+
return huffman;
102+
}
103+
104+
}
105+
106+
public Huffman load_character_huffman(Huffman length_huffman) {
107+
int count = pop(9);
108+
if (count == 0) {
109+
int v = pop(9);
110+
return new Huffman(v); // value=v
111+
}
112+
else {
113+
int[] huffman_code_lengths = new int[count];
114+
int index = 0;
115+
while (index < count) {
116+
int[] h = length_huffman.lookup(peek(16));
117+
int c = h[0];
118+
slide(h[1]);
119+
switch (c) {
120+
case 0:
121+
//# C == 0, skip 1.
122+
c = 1;
123+
index += c;
124+
break;
125+
case 1:
126+
//# C == 1, skip 3 + read(4)
127+
c = 3 + pop(4);
128+
index += c;
129+
break;
130+
case 2:
131+
// # C == 2, skip 20 + read(9)
132+
c = 20 + pop(9);
133+
index += c;
134+
break;
135+
default:
136+
c -= 2;
137+
huffman_code_lengths[index] = c;
138+
index += 1;
139+
break;
140+
}
141+
}
142+
Huffman huffman = new Huffman(huffman_code_lengths);
143+
huffman.build_table();
144+
return huffman;
145+
}
146+
}
147+
148+
public Huffman load_distance_huffman() {
149+
int count = pop(5);
150+
if (count == 0) {
151+
int v = pop(5);
152+
return new Huffman(v); // value=v
153+
}
154+
else {
155+
int index = 0;
156+
int[] lengths = new int[count];
157+
for (int i = 0; i < count; i++) {
158+
lengths[index] = read_variable_length();
159+
index += 1;
160+
}
161+
Huffman huffman = new Huffman(lengths);
162+
huffman.build_table();
163+
return huffman;
164+
}
165+
}
166+
167+
public void load_block() {
168+
block_elements = pop(16);
169+
Huffman character_length_huffman = load_character_length_huffman();
170+
character_huffman = load_character_huffman(character_length_huffman);
171+
distance_huffman = load_distance_huffman();
172+
}
173+
174+
public int get_token() {
175+
if (block_elements <= 0) {
176+
load_block();
177+
}
178+
block_elements -= 1;
179+
int[] h = character_huffman.lookup(peek(16));
180+
slide(h[1]);
181+
return h[0];
182+
}
183+
184+
public int get_position() {
185+
int[] h = distance_huffman.lookup(peek(16));
186+
slide(h[1]);
187+
if (h[0] == 0) {
188+
return 0;
189+
}
190+
int v = h[0] - 1;
191+
v = (1 << v) + pop(v);
192+
return v;
193+
}
194+
195+
public ByteBuffer decompress(ByteBuffer input_data_set, int uncompressed_size) {
196+
input_data = input_data_set;
197+
ByteBuffer output_data = ByteBuffer.allocate(uncompressed_size);
198+
block_elements = -1;
199+
int bits_total = input_data.array().length * 8;
200+
while ((bits_total > bit_position) && ((uncompressed_size == -1) || (output_data.array().length <= uncompressed_size))) {
201+
int character = get_token();
202+
if (character <= 255) { //# literal.
203+
output_data.put((byte) character);
204+
}
205+
else if (character == 510) {
206+
break; //# END
207+
}
208+
else {
209+
int length = character - 253; //# Min length is 3. 256-253=3.
210+
int back = get_position() + 1;
211+
int position = output_data.array().length - back;
212+
if (back > length){
213+
//# Entire lookback is already within output data.
214+
output_data.put(Arrays.copyOfRange(output_data.array(), position, position + length));
215+
}
216+
else {
217+
//# Will read & write the same data at some point.
218+
for (int i = position, s = position + length; i < s; i++) {
219+
output_data.put(output_data.get(i));
220+
}
221+
}
222+
}
223+
}
224+
return output_data;
225+
}
226+
227+
public class Huffman {
228+
int default_value;
229+
int[] lengths;
230+
int[] table = new int[0];
231+
int table_width = 0;
232+
233+
public Huffman(int value) {
234+
this.default_value = value;
235+
}
236+
237+
public Huffman(int[] lengths) {
238+
this.lengths = lengths;
239+
}
240+
241+
public Huffman(int[] lengths, int value) {
242+
this.default_value = value;
243+
this.lengths = lengths;
244+
this.table_width = 0;
245+
}
246+
247+
/*
248+
Build an index huffman table based on the lengths. lowest index value wins in a tie.
249+
*/
250+
public void build_table() {
251+
int m = Integer.MIN_VALUE;
252+
for (int q : lengths) { // m = max(lengths)
253+
if (q > m) {
254+
m = q;
255+
}
256+
}
257+
table_width = m;
258+
int size = (1 << table_width);
259+
for (int bit_length = 1, s = table_width + 1; bit_length < s; bit_length++) {
260+
size /= 2;
261+
for (int len_index = 0, ss = lengths.length; len_index < ss; len_index++) {
262+
int length = lengths[len_index];
263+
if (length == bit_length) {
264+
int[] old_table = table;
265+
int[] new_table = Arrays.copyOf(old_table, old_table.length + size);
266+
Arrays.fill(new_table, old_table.length, new_table.length, len_index);
267+
table = new_table;
268+
}
269+
}
270+
}
271+
}
272+
273+
/*
274+
lookup into the index, returns value and length
275+
must be requested with 2 bytes.
276+
*/
277+
public int[] lookup(int byte_lookup) {
278+
if (table.length == 0) {
279+
return new int[] { default_value, 0 };
280+
}
281+
int v = table[byte_lookup >> (16 - table_width)];
282+
return new int[] { v, lengths[v] };
283+
}
284+
}
285+
}

core/src/main/java/org/embroideryio/embroideryio/EmbPattern.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,8 @@ public static EmbPattern.Reader getReaderByFilename(String filename) {
974974
case "f00":
975975
case "f01":
976976
return new FxyReader();
977+
case "hus":
978+
return new HusReader();
977979
case "inb":
978980
return new InbReader();
979981
case "inf":

core/src/main/java/org/embroideryio/embroideryio/EmbThread.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ public EmbThread(int color, String description, String catalogNumber) {
5050
this.catalogNumber = catalogNumber;
5151
}
5252

53+
public EmbThread(String hex) {
54+
this.color = EmbThread.parseHex(hex);
55+
}
56+
5357
public EmbThread(int red, int green, int blue, String description, String catalogNumber) {
5458
this.color = newColor(red,green,blue);
5559
this.description = description;
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package org.embroideryio.embroideryio;
2+
3+
/**
4+
* Created by Tat on 12/8/2016.
5+
*/
6+
7+
8+
public class EmbThreadHus extends EmbThread {
9+
10+
public static EmbThreadHus[] getThreadSet() {
11+
return new EmbThreadHus[]{
12+
new EmbThreadHus("#000000", "Black", "026"),
13+
new EmbThreadHus("#0000e7", "Blue", "005"),
14+
new EmbThreadHus("#00c600", "Green", "002"),
15+
new EmbThreadHus("#ff0000", "Red", "014"),
16+
new EmbThreadHus("#840084", "Purple", "008"),
17+
new EmbThreadHus("#ffff00", "Yellow", "020"),
18+
new EmbThreadHus("#848484", "Grey", "024"),
19+
new EmbThreadHus("#8484e7", "Light Blue", "006"),
20+
new EmbThreadHus("#00ff84", "Light Green", "003"),
21+
new EmbThreadHus("#ff7b31", "Orange", "017"),
22+
new EmbThreadHus("#ff8ca5", "Pink", "011"),
23+
new EmbThreadHus("#845200", "Brown", "028"),
24+
new EmbThreadHus("#ffffff", "White", "022"),
25+
new EmbThreadHus("#000084", "Dark Blue", "004"),
26+
new EmbThreadHus("#008400", "Dark Green", "001"),
27+
new EmbThreadHus("#7b0000", "Dark Red", "013"),
28+
new EmbThreadHus("#ff6384", "Light Red", "015"),
29+
new EmbThreadHus("#522952", "Dark Purple", "007"),
30+
new EmbThreadHus("#ff00ff", "Light Purple", "009"),
31+
new EmbThreadHus("#ffde00", "Dark Yellow", "019"),
32+
new EmbThreadHus("#ffff9c", "Light Yellow", "021"),
33+
new EmbThreadHus("#525252", "Dark Grey", "025"),
34+
new EmbThreadHus("#d6d6d6", "Light Grey", "023"),
35+
new EmbThreadHus("#ff5208", "Dark Orange", "016"),
36+
new EmbThreadHus("#ff9c5a", "Light Orange", "018"),
37+
new EmbThreadHus("#ff52b5", "Dark Pink", "010"),
38+
new EmbThreadHus("#ffc6de", "Light Pink", "012"),
39+
new EmbThreadHus("#523100", "Dark Brown", "027"),
40+
new EmbThreadHus("#b5a584", "Light Brown", "029"),
41+
};
42+
}
43+
44+
45+
public EmbThreadHus(String color, String description, String catalogNumber) {
46+
super();
47+
this.setColor(EmbThread.parseColor(color));
48+
this.description = description;
49+
this.catalogNumber = catalogNumber;
50+
this.brand = "Hus";
51+
this.chart = "Hus";
52+
}
53+
}

0 commit comments

Comments
 (0)