ETC1Util.java revision c086ca1fa7cebc3e9a51abd4be4688346225c2e4
1a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich/* 2c086ca1fa7cebc3e9a51abd4be4688346225c2e4Dan Bornstein * Copyright (C) 2009 The Android Open Source Project 3a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * 4a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Licensed under the Apache License, Version 2.0 (the "License"); 5a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * you may not use this file except in compliance with the License. 6a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * You may obtain a copy of the License at 7a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * 8c086ca1fa7cebc3e9a51abd4be4688346225c2e4Dan Bornstein * http://www.apache.org/licenses/LICENSE-2.0 9a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * 10a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Unless required by applicable law or agreed to in writing, software 11a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * distributed under the License is distributed on an "AS IS" BASIS, 12a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * See the License for the specific language governing permissions and 14a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * limitations under the License. 15a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich */ 16a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich 17a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichpackage android.opengl; 18a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich 19a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichimport java.io.IOException; 20a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichimport java.io.InputStream; 21a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichimport java.io.OutputStream; 22a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichimport java.nio.Buffer; 23a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichimport java.nio.ByteBuffer; 24a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichimport java.nio.ByteOrder; 25a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich 26a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich/** 27a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Utility methods for using ETC1 compressed textures. 28a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * 29a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich */ 30a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevichpublic class ETC1Util { 31a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich /** 32a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Convenience method to load an ETC1 texture whether or not the active OpenGL context 33a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * supports the ETC1 texture compression format. 34a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param target the texture target. 35a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param level the texture level 36a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param border the border size. Typically 0. 37a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param fallbackFormat the format to use if ETC1 texture compression is not supported. 38a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Must be GL_RGB. 39a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param fallbackType the type to use if ETC1 texture compression is not supported. 40a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Can be either GL_UNSIGNED_SHORT_5_6_5, which implies 16-bits-per-pixel, 41a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * or GL_UNSIGNED_BYTE, which implies 24-bits-per-pixel. 42a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param input the input stream containing an ETC1 texture in PKM format. 43a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @throws IOException 44a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich */ 45a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich public static void loadTexture(int target, int level, int border, 46a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich int fallbackFormat, int fallbackType, InputStream input) 47a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich throws IOException { 48a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich loadTexture(target, level, border, fallbackFormat, fallbackType, createTexture(input)); 49a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich } 50a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich 51a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich /** 52a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Convenience method to load an ETC1 texture whether or not the active OpenGL context 53a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * supports the ETC1 texture compression format. 54a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param target the texture target. 55a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param level the texture level 56a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param border the border size. Typically 0. 57a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param fallbackFormat the format to use if ETC1 texture compression is not supported. 58a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Must be GL_RGB. 59a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param fallbackType the type to use if ETC1 texture compression is not supported. 60a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Can be either GL_UNSIGNED_SHORT_5_6_5, which implies 16-bits-per-pixel, 61a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * or GL_UNSIGNED_BYTE, which implies 24-bits-per-pixel. 62a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param texture the ETC1 to load. 63a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich */ 64a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich public static void loadTexture(int target, int level, int border, 65a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich int fallbackFormat, int fallbackType, ETC1Texture texture) { 66a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich if (fallbackFormat != GLES10.GL_RGB) { 67a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich throw new IllegalArgumentException("fallbackFormat must be GL_RGB"); 68a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich } 69a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich if (! (fallbackType == GLES10.GL_UNSIGNED_SHORT_5_6_5 70a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich || fallbackType == GLES10.GL_UNSIGNED_BYTE)) { 71a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich throw new IllegalArgumentException("Unsupported fallbackType"); 72a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich } 73a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich 74a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich int width = texture.getWidth(); 75a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich int height = texture.getHeight(); 76a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich Buffer data = texture.getData(); 77a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich if (isETC1Supported()) { 78a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich int imageSize = data.remaining(); 79a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich GLES10.glCompressedTexImage2D(target, level, ETC1.ETC1_RGB8_OES, width, height, 80a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich border, imageSize, data); 81a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich } else { 82a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich boolean useShorts = fallbackType != GLES10.GL_UNSIGNED_BYTE; 83a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich int pixelSize = useShorts ? 2 : 3; 84a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich int stride = pixelSize * width; 85a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich ByteBuffer decodedData = ByteBuffer.allocateDirect(stride*height) 86a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich .order(ByteOrder.nativeOrder()); 87a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich ETC1.decodeImage(data, decodedData, width, height, pixelSize, stride); 88a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich GLES10.glTexImage2D(target, level, fallbackFormat, width, height, border, 89a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich fallbackFormat, fallbackType, decodedData); 90a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich } 91a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich } 92a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich 93a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich /** 94a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Check if ETC1 texture compression is supported by the active OpenGL ES context. 958af9649d44745adba8be4db4e96af053ba32f2c5Jack Palevich * @return true if the active OpenGL ES context supports ETC1 texture compression. 96a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich */ 97a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich public static boolean isETC1Supported() { 98a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich int[] results = new int[20]; 99a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich GLES10.glGetIntegerv(GLES10.GL_NUM_COMPRESSED_TEXTURE_FORMATS, results, 0); 100a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich int numFormats = results[0]; 101a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich if (numFormats > results.length) { 102a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich results = new int[numFormats]; 103a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich } 104a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich GLES10.glGetIntegerv(GLES10.GL_COMPRESSED_TEXTURE_FORMATS, results, 0); 105a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich for (int i = 0; i < numFormats; i++) { 106a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich if (results[i] == ETC1.ETC1_RGB8_OES) { 107a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich return true; 108a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich } 109a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich } 110a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich return false; 111a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich } 112a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich 113a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich /** 114a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * A utility class encapsulating a compressed ETC1 texture. 115a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich */ 116a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich public static class ETC1Texture { 117a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich public ETC1Texture(int width, int height, ByteBuffer data) { 118a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich mWidth = width; 119a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich mHeight = height; 120a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich mData = data; 121a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich } 122a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich 123a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich /** 124a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Get the width of the texture in pixels. 125a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @return the width of the texture in pixels. 126a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich */ 127a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich public int getWidth() { return mWidth; } 128a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich 129a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich /** 130a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Get the height of the texture in pixels. 131a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @return the width of the texture in pixels. 132a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich */ 133a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich public int getHeight() { return mHeight; } 134a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich 135a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich /** 136a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Get the compressed data of the texture. 137a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @return the texture data. 138a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich */ 139a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich public ByteBuffer getData() { return mData; } 140a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich 141a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich private int mWidth; 142a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich private int mHeight; 143a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich private ByteBuffer mData; 144a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich } 145a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich 146a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich /** 147a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Create a new ETC1Texture from an input stream containing a PKM formatted compressed texture. 148a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param input an input stream containing a PKM formatted compressed texture. 149a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @return an ETC1Texture read from the input stream. 150a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @throws IOException 151a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich */ 152a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich public static ETC1Texture createTexture(InputStream input) throws IOException { 153a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich int width = 0; 154a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich int height = 0; 155a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich byte[] ioBuffer = new byte[4096]; 156a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich { 157a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich if (input.read(ioBuffer, 0, ETC1.ETC_PKM_HEADER_SIZE) != ETC1.ETC_PKM_HEADER_SIZE) { 158a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich throw new IOException("Unable to read PKM file header."); 159a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich } 160a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich ByteBuffer headerBuffer = ByteBuffer.allocateDirect(ETC1.ETC_PKM_HEADER_SIZE) 161a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich .order(ByteOrder.nativeOrder()); 162a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich headerBuffer.put(ioBuffer, 0, ETC1.ETC_PKM_HEADER_SIZE).position(0); 163a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich if (!ETC1.isValid(headerBuffer)) { 164a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich throw new IOException("Not a PKM file."); 165a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich } 166a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich width = ETC1.getWidth(headerBuffer); 167a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich height = ETC1.getHeight(headerBuffer); 168a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich } 169a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich int encodedSize = ETC1.getEncodedDataSize(width, height); 170a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich ByteBuffer dataBuffer = ByteBuffer.allocateDirect(encodedSize).order(ByteOrder.nativeOrder()); 171a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich for (int i = 0; i < encodedSize; ) { 172a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich int chunkSize = Math.min(ioBuffer.length, encodedSize - i); 173a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich if (input.read(ioBuffer, 0, chunkSize) != chunkSize) { 174a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich throw new IOException("Unable to read PKM file data."); 175a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich } 176a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich dataBuffer.put(ioBuffer, 0, chunkSize); 177a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich i += chunkSize; 178a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich } 179a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich dataBuffer.position(0); 180a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich return new ETC1Texture(width, height, dataBuffer); 181a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich } 182a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich 183a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich /** 184a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Helper function that compresses an image into an ETC1Texture. 185a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param input a native order direct buffer containing the image data 186a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param width the width of the image in pixels 187a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param height the height of the image in pixels 188a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param pixelSize the size of a pixel in bytes (2 or 3) 189a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param stride the width of a line of the image in bytes 190a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @return the ETC1 texture. 191a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich */ 192a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich public static ETC1Texture compressTexture(Buffer input, int width, int height, int pixelSize, int stride){ 193a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich int encodedImageSize = ETC1.getEncodedDataSize(width, height); 194a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich ByteBuffer compressedImage = ByteBuffer.allocateDirect(encodedImageSize). 195a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich order(ByteOrder.nativeOrder()); 196a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich ETC1.encodeImage(input, width, height, 3, stride, compressedImage); 197a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich return new ETC1Texture(width, height, compressedImage); 198a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich } 199a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich 200a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich /** 201a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * Helper function that writes an ETC1Texture to an output stream formatted as a PKM file. 202a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param texture the input texture. 203a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @param output the stream to write the formatted texture data to. 204a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich * @throws IOException 205a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich */ 206a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich public static void writeTexture(ETC1Texture texture, OutputStream output) throws IOException { 207a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich ByteBuffer dataBuffer = texture.getData(); 208a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich int originalPosition = dataBuffer.position(); 209a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich try { 210a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich int width = texture.getWidth(); 211a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich int height = texture.getHeight(); 212a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich ByteBuffer header = ByteBuffer.allocateDirect(ETC1.ETC_PKM_HEADER_SIZE).order(ByteOrder.nativeOrder()); 213a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich ETC1.formatHeader(header, width, height); 214a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich byte[] ioBuffer = new byte[4096]; 215a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich header.get(ioBuffer, 0, ETC1.ETC_PKM_HEADER_SIZE); 216a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich output.write(ioBuffer, 0, ETC1.ETC_PKM_HEADER_SIZE); 217a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich int encodedSize = ETC1.getEncodedDataSize(width, height); 218a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich for (int i = 0; i < encodedSize; ) { 219a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich int chunkSize = Math.min(ioBuffer.length, encodedSize - i); 220a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich dataBuffer.get(ioBuffer, 0, chunkSize); 221a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich output.write(ioBuffer, 0, chunkSize); 222a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich i += chunkSize; 223a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich } 224a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich } finally { 225a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich dataBuffer.position(originalPosition); 226a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich } 227a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich } 228a6276fdd4253c3a7150ab675678c750473ab6c45Jack Palevich} 229