1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.nn.benchmark.util; 18 19 import android.content.res.AssetManager; 20 21 import java.io.ByteArrayOutputStream; 22 import java.io.IOException; 23 import java.io.InputStream; 24 import java.nio.ByteBuffer; 25 import java.nio.ByteOrder; 26 27 /** 28 * Input/Output utilities. 29 */ 30 public final class IOUtils { IOUtils()31 private IOUtils() {} 32 33 /** Reads float values from a byte array. */ readFloats(byte[] bytes, int dataSize)34 public static float[] readFloats(byte[] bytes, int dataSize) { 35 ByteBuffer buffer = ByteBuffer.wrap(bytes); 36 buffer.order(ByteOrder.LITTLE_ENDIAN); 37 int size = bytes.length / dataSize; 38 float[] result = new float[size]; 39 for (int i = 0; i < size; ++i) { 40 if (dataSize == 4) { 41 result[i] = buffer.getFloat(); 42 } else if (dataSize == 1) { 43 result[i] = (float)(buffer.get() & 0xff); 44 } 45 } 46 return result; 47 } 48 49 /** Reads data in native byte order */ readAsset(AssetManager assetManager, String assetFilename, int dataBytesSize)50 public static byte[] readAsset(AssetManager assetManager, String assetFilename, 51 int dataBytesSize) 52 throws IOException { 53 try (InputStream in = assetManager.open(assetFilename)) { 54 byte[] buffer = new byte[8192]; 55 int bytesRead; 56 ByteArrayOutputStream output = new ByteArrayOutputStream(); 57 while ((bytesRead = in.read(buffer)) != -1) { 58 output.write(buffer, 0, bytesRead); 59 } 60 61 byte[] result = output.toByteArray(); 62 // Do we need to swap data endianess? 63 if (dataBytesSize > 1 && ByteOrder.nativeOrder() != ByteOrder.LITTLE_ENDIAN) { 64 if (dataBytesSize == 4) { 65 invertOrder4(result); 66 } if (dataBytesSize == 2) { 67 invertOrder2(result); 68 } else { 69 throw new IllegalArgumentException( 70 "Byte order swapping for " + dataBytesSize 71 + " bytes is not implmemented (yet)"); 72 } 73 } 74 return result; 75 } 76 } 77 78 /** Reverses endianness on array of 4 byte elements */ invertOrder4(byte[] data)79 private static void invertOrder4(byte[] data) { 80 if (data.length % 4 != 0) { 81 throw new IllegalArgumentException("Data is not 4 byte aligned"); 82 } 83 for (int i = 0; i < data.length; i += 4) { 84 byte a = data[i]; 85 byte b = data[i + 1]; 86 data[i] = data[i + 3]; 87 data[i + 1] = data[i + 2]; 88 data[i + 2] = b; 89 data[i + 3] = a; 90 } 91 } 92 93 /** Reverses endianness on array of 2 byte elements */ invertOrder2(byte[] data)94 private static void invertOrder2(byte[] data) { 95 if (data.length % 2 != 0) { 96 throw new IllegalArgumentException("Data is not 2 byte aligned"); 97 } 98 for (int i = 0; i < data.length; i += 2) { 99 byte a = data[i]; 100 data[i] = data[i + 1]; 101 data[i + 1] = a; 102 } 103 } 104 } 105