1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.imaging.common;
18
19 import java.nio.ByteOrder;
20 import java.util.Arrays;
21
22
23
24
25 public final class ByteConversions {
26 public static byte[] toBytes(final double value, final ByteOrder byteOrder) {
27 final byte[] result = new byte[8];
28 toBytes(value, byteOrder, result, 0);
29 return result;
30 }
31
32 private static void toBytes(final double value, final ByteOrder byteOrder, final byte[] result, final int offset) {
33 final long bits = Double.doubleToRawLongBits(value);
34 if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
35 result[offset + 0] = (byte) (0xff & bits >> 0);
36 result[offset + 1] = (byte) (0xff & bits >> 8);
37 result[offset + 2] = (byte) (0xff & bits >> 16);
38 result[offset + 3] = (byte) (0xff & bits >> 24);
39 result[offset + 4] = (byte) (0xff & bits >> 32);
40 result[offset + 5] = (byte) (0xff & bits >> 40);
41 result[offset + 6] = (byte) (0xff & bits >> 48);
42 result[offset + 7] = (byte) (0xff & bits >> 56);
43 } else {
44 result[offset + 7] = (byte) (0xff & bits >> 0);
45 result[offset + 6] = (byte) (0xff & bits >> 8);
46 result[offset + 5] = (byte) (0xff & bits >> 16);
47 result[offset + 4] = (byte) (0xff & bits >> 24);
48 result[offset + 3] = (byte) (0xff & bits >> 32);
49 result[offset + 2] = (byte) (0xff & bits >> 40);
50 result[offset + 1] = (byte) (0xff & bits >> 48);
51 result[offset + 0] = (byte) (0xff & bits >> 56);
52 }
53 }
54
55 public static byte[] toBytes(final double[] values, final ByteOrder byteOrder) {
56 return toBytes(values, 0, values.length, byteOrder);
57 }
58
59 private static byte[] toBytes(final double[] values, final int offset, final int length, final ByteOrder byteOrder) {
60 final byte[] result = Allocator.byteArray(length * 8);
61 for (int i = 0; i < length; i++) {
62 toBytes(values[offset + i], byteOrder, result, i * 8);
63 }
64 return result;
65 }
66
67 public static byte[] toBytes(final float value, final ByteOrder byteOrder) {
68 final byte[] result = new byte[4];
69 toBytes(value, byteOrder, result, 0);
70 return result;
71 }
72
73 private static void toBytes(final float value, final ByteOrder byteOrder, final byte[] result, final int offset) {
74 final int bits = Float.floatToRawIntBits(value);
75 if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
76 result[offset + 0] = (byte) (0xff & bits >> 0);
77 result[offset + 1] = (byte) (0xff & bits >> 8);
78 result[offset + 2] = (byte) (0xff & bits >> 16);
79 result[offset + 3] = (byte) (0xff & bits >> 24);
80 } else {
81 result[offset + 3] = (byte) (0xff & bits >> 0);
82 result[offset + 2] = (byte) (0xff & bits >> 8);
83 result[offset + 1] = (byte) (0xff & bits >> 16);
84 result[offset + 0] = (byte) (0xff & bits >> 24);
85 }
86 }
87
88 public static byte[] toBytes(final float[] values, final ByteOrder byteOrder) {
89 return toBytes(values, 0, values.length, byteOrder);
90 }
91
92 private static byte[] toBytes(final float[] values, final int offset, final int length, final ByteOrder byteOrder) {
93 final byte[] result = Allocator.byteArray(length * 4);
94 for (int i = 0; i < length; i++) {
95 toBytes(values[offset + i], byteOrder, result, i * 4);
96 }
97 return result;
98 }
99
100 public static byte[] toBytes(final int value, final ByteOrder byteOrder) {
101 final byte[] result = new byte[4];
102 toBytes(value, byteOrder, result, 0);
103 return result;
104 }
105
106 private static void toBytes(final int value, final ByteOrder byteOrder, final byte[] result, final int offset) {
107 if (byteOrder == ByteOrder.BIG_ENDIAN) {
108 result[offset + 0] = (byte) (value >> 24);
109 result[offset + 1] = (byte) (value >> 16);
110 result[offset + 2] = (byte) (value >> 8);
111 result[offset + 3] = (byte) (value >> 0);
112 } else {
113 result[offset + 3] = (byte) (value >> 24);
114 result[offset + 2] = (byte) (value >> 16);
115 result[offset + 1] = (byte) (value >> 8);
116 result[offset + 0] = (byte) (value >> 0);
117 }
118 }
119
120 public static byte[] toBytes(final int[] values, final ByteOrder byteOrder) {
121 return toBytes(values, 0, values.length, byteOrder);
122 }
123
124 private static byte[] toBytes(final int[] values, final int offset, final int length, final ByteOrder byteOrder) {
125 final byte[] result = Allocator.byteArray(length * 4);
126 for (int i = 0; i < length; i++) {
127 toBytes(values[offset + i], byteOrder, result, i * 4);
128 }
129 return result;
130 }
131
132
133
134
135
136
137
138
139 public static byte[] toBytes(final long value, final ByteOrder byteOrder) {
140 final byte[] result = new byte[8];
141 toBytes(value, byteOrder, result, 0);
142 return result;
143 }
144
145 private static void toBytes(final long value, final ByteOrder byteOrder, final byte[] result, final int offset) {
146 if (byteOrder == ByteOrder.BIG_ENDIAN) {
147 result[offset + 0] = (byte) (value >> 56);
148 result[offset + 1] = (byte) (value >> 48);
149 result[offset + 2] = (byte) (value >> 40);
150 result[offset + 3] = (byte) (value >> 32);
151 result[offset + 4] = (byte) (value >> 24);
152 result[offset + 5] = (byte) (value >> 16);
153 result[offset + 6] = (byte) (value >> 8);
154 result[offset + 7] = (byte) value;
155 } else {
156 result[offset + 7] = (byte) (value >> 56);
157 result[offset + 6] = (byte) (value >> 48);
158 result[offset + 5] = (byte) (value >> 40);
159 result[offset + 4] = (byte) (value >> 32);
160 result[offset + 3] = (byte) (value >> 24);
161 result[offset + 2] = (byte) (value >> 16);
162 result[offset + 1] = (byte) (value >> 8);
163 result[offset + 0] = (byte) value;
164 }
165 }
166
167 public static byte[] toBytes(final RationalNumber value, final ByteOrder byteOrder) {
168 final byte[] result = new byte[8];
169 toBytes(value, byteOrder, result, 0);
170 return result;
171 }
172
173 private static void toBytes(final RationalNumber value, final ByteOrder byteOrder, final byte[] result, final int offset) {
174 if (byteOrder == ByteOrder.BIG_ENDIAN) {
175 result[offset + 0] = (byte) (value.numerator >> 24);
176 result[offset + 1] = (byte) (value.numerator >> 16);
177 result[offset + 2] = (byte) (value.numerator >> 8);
178 result[offset + 3] = (byte) (value.numerator >> 0);
179 result[offset + 4] = (byte) (value.divisor >> 24);
180 result[offset + 5] = (byte) (value.divisor >> 16);
181 result[offset + 6] = (byte) (value.divisor >> 8);
182 result[offset + 7] = (byte) (value.divisor >> 0);
183 } else {
184 result[offset + 3] = (byte) (value.numerator >> 24);
185 result[offset + 2] = (byte) (value.numerator >> 16);
186 result[offset + 1] = (byte) (value.numerator >> 8);
187 result[offset + 0] = (byte) (value.numerator >> 0);
188 result[offset + 7] = (byte) (value.divisor >> 24);
189 result[offset + 6] = (byte) (value.divisor >> 16);
190 result[offset + 5] = (byte) (value.divisor >> 8);
191 result[offset + 4] = (byte) (value.divisor >> 0);
192 }
193 }
194
195 public static byte[] toBytes(final RationalNumber[] values, final ByteOrder byteOrder) {
196 return toBytes(values, 0, values.length, byteOrder);
197 }
198
199 private static byte[] toBytes(final RationalNumber[] values, final int offset, final int length, final ByteOrder byteOrder) {
200 final byte[] result = Allocator.byteArray(length * 8);
201 for (int i = 0; i < length; i++) {
202 toBytes(values[offset + i], byteOrder, result, i * 8);
203 }
204 return result;
205 }
206
207 public static byte[] toBytes(final short value, final ByteOrder byteOrder) {
208 final byte[] result = new byte[2];
209 toBytes(value, byteOrder, result, 0);
210 return result;
211 }
212
213 private static void toBytes(final short value, final ByteOrder byteOrder, final byte[] result, final int offset) {
214 if (byteOrder == ByteOrder.BIG_ENDIAN) {
215 result[offset + 0] = (byte) (value >> 8);
216 result[offset + 1] = (byte) (value >> 0);
217 } else {
218 result[offset + 1] = (byte) (value >> 8);
219 result[offset + 0] = (byte) (value >> 0);
220 }
221 }
222
223 public static byte[] toBytes(final short[] values, final ByteOrder byteOrder) {
224 return toBytes(values, 0, values.length, byteOrder);
225 }
226
227 private static byte[] toBytes(final short[] values, final int offset, final int length, final ByteOrder byteOrder) {
228 final byte[] result = Allocator.byteArray(length * 2);
229 for (int i = 0; i < length; i++) {
230 toBytes(values[offset + i], byteOrder, result, i * 2);
231 }
232 return result;
233 }
234
235 public static double toDouble(final byte[] bytes, final ByteOrder byteOrder) {
236 return toDouble(bytes, 0, byteOrder);
237 }
238
239 private static double toDouble(final byte[] bytes, final int offset, final ByteOrder byteOrder) {
240 final long byte0 = 0xffL & bytes[offset + 0];
241 final long byte1 = 0xffL & bytes[offset + 1];
242 final long byte2 = 0xffL & bytes[offset + 2];
243 final long byte3 = 0xffL & bytes[offset + 3];
244 final long byte4 = 0xffL & bytes[offset + 4];
245 final long byte5 = 0xffL & bytes[offset + 5];
246 final long byte6 = 0xffL & bytes[offset + 6];
247 final long byte7 = 0xffL & bytes[offset + 7];
248 final long bits;
249 if (byteOrder == ByteOrder.BIG_ENDIAN) {
250 bits = byte0 << 56 | byte1 << 48 | byte2 << 40 | byte3 << 32 | byte4 << 24 | byte5 << 16 | byte6 << 8 | byte7 << 0;
251 } else {
252 bits = byte7 << 56 | byte6 << 48 | byte5 << 40 | byte4 << 32 | byte3 << 24 | byte2 << 16 | byte1 << 8 | byte0 << 0;
253 }
254 return Double.longBitsToDouble(bits);
255 }
256
257 public static double[] toDoubles(final byte[] bytes, final ByteOrder byteOrder) {
258 return toDoubles(bytes, 0, bytes.length, byteOrder);
259 }
260
261 private static double[] toDoubles(final byte[] bytes, final int offset, final int length, final ByteOrder byteOrder) {
262 final double[] result = Allocator.doubleArray(length / 8);
263 Arrays.setAll(result, i -> toDouble(bytes, offset + 8 * i, byteOrder));
264 return result;
265 }
266
267 public static float toFloat(final byte[] bytes, final ByteOrder byteOrder) {
268 return toFloat(bytes, 0, byteOrder);
269 }
270
271 private static float toFloat(final byte[] bytes, final int offset, final ByteOrder byteOrder) {
272 final int byte0 = 0xff & bytes[offset + 0];
273 final int byte1 = 0xff & bytes[offset + 1];
274 final int byte2 = 0xff & bytes[offset + 2];
275 final int byte3 = 0xff & bytes[offset + 3];
276 final int bits;
277 if (byteOrder == ByteOrder.BIG_ENDIAN) {
278 bits = byte0 << 24 | byte1 << 16 | byte2 << 8 | byte3 << 0;
279 } else {
280 bits = byte3 << 24 | byte2 << 16 | byte1 << 8 | byte0 << 0;
281 }
282 return Float.intBitsToFloat(bits);
283 }
284
285 public static float[] toFloats(final byte[] bytes, final ByteOrder byteOrder) {
286 return toFloats(bytes, 0, bytes.length, byteOrder);
287 }
288
289 private static float[] toFloats(final byte[] bytes, final int offset, final int length, final ByteOrder byteOrder) {
290 final float[] result = Allocator.floatArray(length / 4);
291 for (int i = 0; i < result.length; i++) {
292 result[i] = toFloat(bytes, offset + 4 * i, byteOrder);
293 }
294 return result;
295 }
296
297 public static int toInt(final byte[] bytes, final ByteOrder byteOrder) {
298 return toInt(bytes, 0, byteOrder);
299 }
300
301 public static int toInt(final byte[] bytes, final int offset, final ByteOrder byteOrder) {
302 final int byte0 = 0xff & bytes[offset + 0];
303 final int byte1 = 0xff & bytes[offset + 1];
304 final int byte2 = 0xff & bytes[offset + 2];
305 final int byte3 = 0xff & bytes[offset + 3];
306 if (byteOrder == ByteOrder.BIG_ENDIAN) {
307 return byte0 << 24 | byte1 << 16 | byte2 << 8 | byte3;
308 }
309 return byte3 << 24 | byte2 << 16 | byte1 << 8 | byte0;
310 }
311
312 public static int[] toInts(final byte[] bytes, final ByteOrder byteOrder) {
313 return toInts(bytes, 0, bytes.length, byteOrder);
314 }
315
316 private static int[] toInts(final byte[] bytes, final int offset, final int length, final ByteOrder byteOrder) {
317 final int[] result = Allocator.intArray(length / 4);
318 Arrays.setAll(result, i -> toInt(bytes, offset + 4 * i, byteOrder));
319 return result;
320 }
321
322
323
324
325
326
327
328
329
330 public static long toLong(final byte[] bytes, final ByteOrder byteOrder) {
331 return toLong(bytes, 0, byteOrder);
332 }
333
334 private static long toLong(final byte[] bytes, final int offset, final ByteOrder byteOrder) {
335 final long byte0 = 0xffL & bytes[offset + 0];
336 final long byte1 = 0xffL & bytes[offset + 1];
337 final long byte2 = 0xffL & bytes[offset + 2];
338 final long byte3 = 0xffL & bytes[offset + 3];
339 final long byte4 = 0xffL & bytes[offset + 4];
340 final long byte5 = 0xffL & bytes[offset + 5];
341 final long byte6 = 0xffL & bytes[offset + 6];
342 final long byte7 = 0xffL & bytes[offset + 7];
343
344 if (byteOrder == ByteOrder.BIG_ENDIAN) {
345 return byte0 << 56 | byte1 << 48 | byte2 << 40 | byte3 << 32 | byte4 << 24 | byte5 << 16 | byte6 << 8 | byte7;
346 }
347 return byte7 << 56 | byte6 << 48 | byte5 << 40 | byte4 << 32 | byte3 << 24 | byte2 << 16 | byte1 << 8 | byte0;
348 }
349
350
351
352
353
354
355
356
357
358 public static long[] toLongs(final byte[] bytes, final ByteOrder byteOrder) {
359 return toLongs(bytes, 0, bytes.length, byteOrder);
360 }
361
362 private static long[] toLongs(final byte[] bytes, final int offset, final int length, final ByteOrder byteOrder) {
363 final long[] result = Allocator.longArray(length / 8);
364 Arrays.setAll(result, i -> toLong(bytes, offset + 8 * i, byteOrder));
365 return result;
366 }
367
368
369
370
371
372
373
374
375
376 public static RationalNumber toRational(final byte[] bytes, final ByteOrder byteOrder, final boolean unsignedType) {
377 return toRational(bytes, 0, byteOrder, unsignedType);
378 }
379
380 private static RationalNumber toRational(final byte[] bytes, final int offset, final ByteOrder byteOrder, final boolean unsignedType) {
381 final int byte0 = 0xff & bytes[offset + 0];
382 final int byte1 = 0xff & bytes[offset + 1];
383 final int byte2 = 0xff & bytes[offset + 2];
384 final int byte3 = 0xff & bytes[offset + 3];
385 final int byte4 = 0xff & bytes[offset + 4];
386 final int byte5 = 0xff & bytes[offset + 5];
387 final int byte6 = 0xff & bytes[offset + 6];
388 final int byte7 = 0xff & bytes[offset + 7];
389 final int numerator;
390 final int divisor;
391 if (byteOrder == ByteOrder.BIG_ENDIAN) {
392 numerator = byte0 << 24 | byte1 << 16 | byte2 << 8 | byte3;
393 divisor = byte4 << 24 | byte5 << 16 | byte6 << 8 | byte7;
394 } else {
395 numerator = byte3 << 24 | byte2 << 16 | byte1 << 8 | byte0;
396 divisor = byte7 << 24 | byte6 << 16 | byte5 << 8 | byte4;
397 }
398 return new RationalNumber(numerator, divisor, unsignedType);
399 }
400
401 public static RationalNumber[] toRationals(final byte[] bytes, final ByteOrder byteOrder, final boolean unsignedType) {
402 return toRationals(bytes, 0, bytes.length, byteOrder, unsignedType);
403 }
404
405 private static RationalNumber[] toRationals(final byte[] bytes, final int offset, final int length, final ByteOrder byteOrder, final boolean unsignedType) {
406 final RationalNumber[] result = new RationalNumber[length / 8];
407 Arrays.setAll(result, i -> toRational(bytes, offset + 8 * i, byteOrder, unsignedType));
408 return result;
409 }
410
411 public static short toShort(final byte[] bytes, final ByteOrder byteOrder) {
412 return toShort(bytes, 0, byteOrder);
413 }
414
415 private static short toShort(final byte[] bytes, final int offset, final ByteOrder byteOrder) {
416 return (short) toUInt16(bytes, offset, byteOrder);
417 }
418
419 public static short[] toShorts(final byte[] bytes, final ByteOrder byteOrder) {
420 return toShorts(bytes, 0, bytes.length, byteOrder);
421 }
422
423 private static short[] toShorts(final byte[] bytes, final int offset, final int length, final ByteOrder byteOrder) {
424 final short[] result = Allocator.shortArray(length / 2);
425 for (int i = 0; i < result.length; i++) {
426 result[i] = toShort(bytes, offset + 2 * i, byteOrder);
427 }
428 return result;
429 }
430
431 public static int toUInt16(final byte[] bytes, final ByteOrder byteOrder) {
432 return toUInt16(bytes, 0, byteOrder);
433 }
434
435 public static int toUInt16(final byte[] bytes, final int offset, final ByteOrder byteOrder) {
436 final int byte0 = 0xff & bytes[offset + 0];
437 final int byte1 = 0xff & bytes[offset + 1];
438 if (byteOrder == ByteOrder.BIG_ENDIAN) {
439 return byte0 << 8 | byte1;
440 }
441 return byte1 << 8 | byte0;
442 }
443
444 public static int[] toUInt16s(final byte[] bytes, final ByteOrder byteOrder) {
445 return toUInt16s(bytes, 0, bytes.length, byteOrder);
446 }
447
448 private static int[] toUInt16s(final byte[] bytes, final int offset, final int length, final ByteOrder byteOrder) {
449 final int[] result = Allocator.intArray(length / 2);
450 Arrays.setAll(result, i -> toUInt16(bytes, offset + 2 * i, byteOrder));
451 return result;
452 }
453
454 private ByteConversions() {
455 }
456 }