    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.imaging.common;
    018
    019import java.nio.ByteOrder;
    020
    021/**
    022 * Convenience methods for converting data types to and from
    023 * byte arrays.
    024 */
    025public final class ByteConversions {
    026    private ByteConversions() {
    027    }
    028
    029    public static byte[] toBytes(final short value, final ByteOrder byteOrder) {
    030        final byte[] result = new byte[2];
    031        toBytes(value, byteOrder, result, 0);
    032        return result;
    033    }
    034
    035    public static byte[] toBytes(final short[] values, final ByteOrder byteOrder) {
    036        return toBytes(values, 0, values.length, byteOrder);
    037    }
    038
    039    private static byte[] toBytes(final short[] values, final int offset, final int length, final ByteOrder byteOrder) {
    040        final byte[] result = new byte[length * 2];
    041        for (int i = 0; i < length; i++) {
    042            toBytes(values[offset + i], byteOrder, result, i * 2);
    043        }
    044        return result;
    045    }
    046
    047    private static void toBytes(final short value, final ByteOrder byteOrder, final byte[] result, final int offset) {
    048        if (byteOrder == ByteOrder.BIG_ENDIAN) {
    049            result[offset + 0] = (byte) (value >> 8);
    050            result[offset + 1] = (byte) (value >> 0);
    051        } else {
    052            result[offset + 1] = (byte) (value >> 8);
    053            result[offset + 0] = (byte) (value >> 0);
    054        }
    055    }
    056
    057    public static byte[] toBytes(final int value, final ByteOrder byteOrder) {
    058        final byte[] result = new byte[4];
    059        toBytes(value, byteOrder, result, 0);
    060        return result;
    061    }
    062
    063    public static byte[] toBytes(final int[] values, final ByteOrder byteOrder) {
    064        return toBytes(values, 0, values.length, byteOrder);
    065    }
    066
    067    private static byte[] toBytes(final int[] values, final int offset, final int length, final ByteOrder byteOrder) {
    068        final byte[] result = new byte[length * 4];
    069        for (int i = 0; i < length; i++) {
    070            toBytes(values[offset + i], byteOrder, result, i * 4);
    071        }
    072        return result;
    073    }
    074
    075    private static void toBytes(final int value, final ByteOrder byteOrder, final byte[] result, final int offset) {
    076        if (byteOrder == ByteOrder.BIG_ENDIAN) {
    077            result[offset + 0] = (byte) (value >> 24);
    078            result[offset + 1] = (byte) (value >> 16);
    079            result[offset + 2] = (byte) (value >> 8);
    080            result[offset + 3] = (byte) (value >> 0);
    081        } else {
    082            result[offset + 3] = (byte) (value >> 24);
    083            result[offset + 2] = (byte) (value >> 16);
    084            result[offset + 1] = (byte) (value >> 8);
    085            result[offset + 0] = (byte) (value >> 0);
    086        }
    087    }
    088
    089    public static byte[] toBytes(final float value, final ByteOrder byteOrder) {
    090        final byte[] result = new byte[4];
    091        toBytes(value, byteOrder, result, 0);
    092        return result;
    093    }
    094
    095    public static byte[] toBytes(final float[] values, final ByteOrder byteOrder) {
    096        return toBytes(values, 0, values.length, byteOrder);
    097    }
    098
    099    private static byte[] toBytes(final float[] values, final int offset, final int length, final ByteOrder byteOrder) {
    100        final byte[] result = new byte[length * 4];
    101        for (int i = 0; i < length; i++) {
    102            toBytes(values[offset + i], byteOrder, result, i * 4);
    103        }
    104        return result;
    105    }
    106
    107    private static void toBytes(final float value, final ByteOrder byteOrder, final byte[] result, final int offset) {
    108        final int bits = Float.floatToRawIntBits(value);
    109        if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
    110            result[offset + 0] = (byte) (0xff & (bits >> 0));
    111            result[offset + 1] = (byte) (0xff & (bits >> 8));
    112            result[offset + 2] = (byte) (0xff & (bits >> 16));
    113            result[offset + 3] = (byte) (0xff & (bits >> 24));
    114        } else {
    115            result[offset + 3] = (byte) (0xff & (bits >> 0));
    116            result[offset + 2] = (byte) (0xff & (bits >> 8));
    117            result[offset + 1] = (byte) (0xff & (bits >> 16));
    118            result[offset + 0] = (byte) (0xff & (bits >> 24));
    119        }
    120    }
    121
    122    public static byte[] toBytes(final double value, final ByteOrder byteOrder) {
    123        final byte[] result = new byte[8];
    124        toBytes(value, byteOrder, result, 0);
    125        return result;
    126    }
    127
    128    public static byte[] toBytes(final double[] values, final ByteOrder byteOrder) {
    129        return toBytes(values, 0, values.length, byteOrder);
    130    }
    131
    132    private static byte[] toBytes(final double[] values, final int offset,
    133            final int length, final ByteOrder byteOrder) {
    134        final byte[] result = new byte[length * 8];
    135        for (int i = 0; i < length; i++) {
    136            toBytes(values[offset + i], byteOrder, result, i * 8);
    137        }
    138        return result;
    139    }
    140
    141    private static void toBytes(final double value, final ByteOrder byteOrder, final byte[] result, final int offset) {
    142        final long bits = Double.doubleToRawLongBits(value);
    143        if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
    144            result[offset + 0] = (byte) (0xff & (bits >> 0));
    145            result[offset + 1] = (byte) (0xff & (bits >> 8));
    146            result[offset + 2] = (byte) (0xff & (bits >> 16));
    147            result[offset + 3] = (byte) (0xff & (bits >> 24));
    148            result[offset + 4] = (byte) (0xff & (bits >> 32));
    149            result[offset + 5] = (byte) (0xff & (bits >> 40));
    150            result[offset + 6] = (byte) (0xff & (bits >> 48));
    151            result[offset + 7] = (byte) (0xff & (bits >> 56));
    152        } else {
    153            result[offset + 7] = (byte) (0xff & (bits >> 0));
    154            result[offset + 6] = (byte) (0xff & (bits >> 8));
    155            result[offset + 5] = (byte) (0xff & (bits >> 16));
    156            result[offset + 4] = (byte) (0xff & (bits >> 24));
    157            result[offset + 3] = (byte) (0xff & (bits >> 32));
    158            result[offset + 2] = (byte) (0xff & (bits >> 40));
    159            result[offset + 1] = (byte) (0xff & (bits >> 48));
    160            result[offset + 0] = (byte) (0xff & (bits >> 56));
    161        }
    162    }
    163
    164    public static byte[] toBytes(final RationalNumber value, final ByteOrder byteOrder) {
    165        final byte[] result = new byte[8];
    166        toBytes(value, byteOrder, result, 0);
    167        return result;
    168    }
    169
    170    public static byte[] toBytes(final RationalNumber[] values, final ByteOrder byteOrder) {
    171        return toBytes(values, 0, values.length, byteOrder);
    172    }
    173
    174    private static byte[] toBytes(final RationalNumber[] values, final int offset,
    175            final int length, final ByteOrder byteOrder) {
    176        final byte[] result = new byte[length * 8];
    177        for (int i = 0; i < length; i++) {
    178            toBytes(values[offset + i], byteOrder, result, i * 8);
    179        }
    180        return result;
    181    }
    182
    183    private static void toBytes(final RationalNumber value, final ByteOrder byteOrder,
    184            final byte[] result, final int offset) {
    185        if (byteOrder == ByteOrder.BIG_ENDIAN) {
    186            result[offset + 0] = (byte) (value.numerator >> 24);
    187            result[offset + 1] = (byte) (value.numerator >> 16);
    188            result[offset + 2] = (byte) (value.numerator >> 8);
    189            result[offset + 3] = (byte) (value.numerator >> 0);
    190            result[offset + 4] = (byte) (value.divisor >> 24);
    191            result[offset + 5] = (byte) (value.divisor >> 16);
    192            result[offset + 6] = (byte) (value.divisor >> 8);
    193            result[offset + 7] = (byte) (value.divisor >> 0);
    194        } else {
    195            result[offset + 3] = (byte) (value.numerator >> 24);
    196            result[offset + 2] = (byte) (value.numerator >> 16);
    197            result[offset + 1] = (byte) (value.numerator >> 8);
    198            result[offset + 0] = (byte) (value.numerator >> 0);
    199            result[offset + 7] = (byte) (value.divisor >> 24);
    200            result[offset + 6] = (byte) (value.divisor >> 16);
    201            result[offset + 5] = (byte) (value.divisor >> 8);
    202            result[offset + 4] = (byte) (value.divisor >> 0);
    203        }
    204    }
    205
    206    public static short toShort(final byte[] bytes, final ByteOrder byteOrder) {
    207        return toShort(bytes, 0, byteOrder);
    208    }
    209
    210    private static short toShort(final byte[] bytes, final int offset, final ByteOrder byteOrder) {
    211        return (short) toUInt16(bytes, offset, byteOrder);
    212    }
    213
    214    public static short[] toShorts(final byte[] bytes, final ByteOrder byteOrder) {
    215        return toShorts(bytes, 0, bytes.length, byteOrder);
    216    }
    217
    218    private static short[] toShorts(final byte[] bytes, final int offset,
    219            final int length, final ByteOrder byteOrder) {
    220        final short[] result = new short[length / 2];
    221        for (int i = 0; i < result.length; i++) {
    222            result[i] = toShort(bytes, offset + 2 * i, byteOrder);
    223        }
    224        return result;
    225    }
    226
    227    public static int toUInt16(final byte[] bytes, final ByteOrder byteOrder) {
    228        return toUInt16(bytes, 0, byteOrder);
    229    }
    230
    231    public static int toUInt16(final byte[] bytes, final int offset, final ByteOrder byteOrder) {
    232        final int byte0 = 0xff & bytes[offset + 0];
    233        final int byte1 = 0xff & bytes[offset + 1];
    234        if (byteOrder == ByteOrder.BIG_ENDIAN) {
    235            return ((byte0 << 8) | byte1);
    236        } else {
    237            return ((byte1 << 8) | byte0);
    238        }
    239    }
    240
    241    public static int[] toUInt16s(final byte[] bytes, final ByteOrder byteOrder) {
    242        return toUInt16s(bytes, 0, bytes.length, byteOrder);
    243    }
    244
    245    private static int[] toUInt16s(final byte[] bytes, final int offset, final int length,
    246            final ByteOrder byteOrder) {
    247        final int[] result = new int[length / 2];
    248        for (int i = 0; i < result.length; i++) {
    249            result[i] = toUInt16(bytes, offset + 2 * i, byteOrder);
    250        }
    251        return result;
    252    }
    253
    254    public static int toInt(final byte[] bytes, final ByteOrder byteOrder) {
    255        return toInt(bytes, 0, byteOrder);
    256    }
    257
    258    public static int toInt(final byte[] bytes, final int offset, final ByteOrder byteOrder) {
    259        final int byte0 = 0xff & bytes[offset + 0];
    260        final int byte1 = 0xff & bytes[offset + 1];
    261        final int byte2 = 0xff & bytes[offset + 2];
    262        final int byte3 = 0xff & bytes[offset + 3];
    263        if (byteOrder == ByteOrder.BIG_ENDIAN) {
    264            return (byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3;
    265        } else {
    266            return (byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0;
    267        }
    268    }
    269
    270    public static int[] toInts(final byte[] bytes, final ByteOrder byteOrder) {
    271        return toInts(bytes, 0, bytes.length, byteOrder);
    272    }
    273
    274    private static int[] toInts(final byte[] bytes, final int offset, final int length,
    275            final ByteOrder byteOrder) {
    276        final int[] result = new int[length / 4];
    277        for (int i = 0; i < result.length; i++) {
    278            result[i] = toInt(bytes, offset + 4 * i, byteOrder);
    279        }
    280        return result;
    281    }
    282
    283    public static float toFloat(final byte[] bytes, final ByteOrder byteOrder) {
    284        return toFloat(bytes, 0, byteOrder);
    285    }
    286
    287    private static float toFloat(final byte[] bytes, final int offset, final ByteOrder byteOrder) {
    288        final int byte0 = 0xff & bytes[offset + 0];
    289        final int byte1 = 0xff & bytes[offset + 1];
    290        final int byte2 = 0xff & bytes[offset + 2];
    291        final int byte3 = 0xff & bytes[offset + 3];
    292        final int bits;
    293        if (byteOrder == ByteOrder.BIG_ENDIAN) {
    294            bits = (byte0 << 24) | (byte1 << 16) | (byte2 << 8) | (byte3 << 0);
    295        } else {
    296            bits = (byte3 << 24) | (byte2 << 16) | (byte1 << 8) | (byte0 << 0);
    297        }
    298        return Float.intBitsToFloat(bits);
    299    }
    300
    301    public static float[] toFloats(final byte[] bytes, final ByteOrder byteOrder) {
    302        return toFloats(bytes, 0, bytes.length, byteOrder);
    303    }
    304
    305    private static float[] toFloats(final byte[] bytes, final int offset,
    306            final int length, final ByteOrder byteOrder) {
    307        final float[] result = new float[length / 4];
    308        for (int i = 0; i < result.length; i++) {
    309            result[i] = toFloat(bytes, offset + 4 * i, byteOrder);
    310        }
    311        return result;
    312    }
    313
    314    public static double toDouble(final byte[] bytes, final ByteOrder byteOrder) {
    315        return toDouble(bytes, 0, byteOrder);
    316    }
    317
    318    private static double toDouble(final byte[] bytes, final int offset, final ByteOrder byteOrder) {
    319        final long byte0 = 0xffL & bytes[offset + 0];
    320        final long byte1 = 0xffL & bytes[offset + 1];
    321        final long byte2 = 0xffL & bytes[offset + 2];
    322        final long byte3 = 0xffL & bytes[offset + 3];
    323        final long byte4 = 0xffL & bytes[offset + 4];
    324        final long byte5 = 0xffL & bytes[offset + 5];
    325        final long byte6 = 0xffL & bytes[offset + 6];
    326        final long byte7 = 0xffL & bytes[offset + 7];
    327        final long bits;
    328        if (byteOrder == ByteOrder.BIG_ENDIAN) {
    329            bits = (byte0 << 56) | (byte1 << 48) | (byte2 << 40)
    330                    | (byte3 << 32) | (byte4 << 24) | (byte5 << 16)
    331                    | (byte6 << 8) | (byte7 << 0);
    332        } else {
    333            bits = (byte7 << 56) | (byte6 << 48) | (byte5 << 40)
    334                    | (byte4 << 32) | (byte3 << 24) | (byte2 << 16)
    335                    | (byte1 << 8) | (byte0 << 0);
    336        }
    337        return Double.longBitsToDouble(bits);
    338    }
    339
    340    public static double[] toDoubles(final byte[] bytes, final ByteOrder byteOrder) {
    341        return toDoubles(bytes, 0, bytes.length, byteOrder);
    342    }
    343
    344    private static double[] toDoubles(final byte[] bytes, final int offset,
    345            final int length, final ByteOrder byteOrder) {
    346        final double[] result = new double[length / 8];
    347        for (int i = 0; i < result.length; i++) {
    348            result[i] = toDouble(bytes, offset + 8 * i, byteOrder);
    349        }
    350        return result;
    351    }
    352
    353    public static RationalNumber toRational(final byte[] bytes, final ByteOrder byteOrder) {
    354        return toRational(bytes, 0, byteOrder);
    355    }
    356
    357    private static RationalNumber toRational(final byte[] bytes, final int offset, final ByteOrder byteOrder) {
    358        final int byte0 = 0xff & bytes[offset + 0];
    359        final int byte1 = 0xff & bytes[offset + 1];
    360        final int byte2 = 0xff & bytes[offset + 2];
    361        final int byte3 = 0xff & bytes[offset + 3];
    362        final int byte4 = 0xff & bytes[offset + 4];
    363        final int byte5 = 0xff & bytes[offset + 5];
    364        final int byte6 = 0xff & bytes[offset + 6];
    365        final int byte7 = 0xff & bytes[offset + 7];
    366        final int numerator;
    367        final int divisor;
    368        if (byteOrder == ByteOrder.BIG_ENDIAN) {
    369            numerator = (byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3;
    370            divisor = (byte4 << 24) | (byte5 << 16) | (byte6 << 8) | byte7;
    371        } else {
    372            numerator = (byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0;
    373            divisor = (byte7 << 24) | (byte6 << 16) | (byte5 << 8) | byte4;
    374        }
    375        return new RationalNumber(numerator, divisor);
    376    }
    377
    378    public static RationalNumber[] toRationals(final byte[] bytes, final ByteOrder byteOrder) {
    379        return toRationals(bytes, 0, bytes.length, byteOrder);
    380    }
    381
    382    private static RationalNumber[] toRationals(final byte[] bytes,
    383            final int offset, final int length, final ByteOrder byteOrder) {
    384        final RationalNumber[] result = new RationalNumber[length / 8];
    385        for (int i = 0; i < result.length; i++) {
    386            result[i] = toRational(bytes, offset + 8 * i, byteOrder);
    387        }
    388        return result;
    389    }
    390}