Skip to content

Commit c164515

Browse files
committed
Tool for compressing/decompressing ETC1 textures.
The ETC1 texture format is commonly supported by OpenGL ES 2.0-capable GPUs. For historical reasons ETC1 texture files have the default extension .PKM This tool relies on the libETC1 library to compress and decompress the image data.
1 parent e499caf commit c164515

File tree

6 files changed

+828
-17
lines changed

6 files changed

+828
-17
lines changed

samples/ApiDemos/AndroidManifest.xml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1405,7 +1405,17 @@
14051405
<category android:name="android.intent.category.SAMPLE_CODE" />
14061406
</intent-filter>
14071407
</activity>
1408-
1408+
1409+
<activity android:name=".graphics.CompressedTextureActivity"
1410+
android:label="Graphics/OpenGL ES/Compressed Texture"
1411+
android:theme="@android:style/Theme.NoTitleBar"
1412+
android:configChanges="orientation|keyboardHidden">
1413+
<intent-filter>
1414+
<action android:name="android.intent.action.MAIN" />
1415+
<category android:name="android.intent.category.SAMPLE_CODE" />
1416+
</intent-filter>
1417+
</activity>
1418+
14091419
<activity android:name=".graphics.GLSurfaceViewActivity"
14101420
android:label="Graphics/OpenGL ES/GLSurfaceView"
14111421
android:theme="@android:style/Theme.NoTitleBar"
32 KB
Binary file not shown.
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/*
2+
* Copyright (C) 2008 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.example.android.apis.graphics;
18+
19+
import java.io.ByteArrayInputStream;
20+
import java.io.ByteArrayOutputStream;
21+
import java.io.IOException;
22+
import java.io.InputStream;
23+
import java.nio.Buffer;
24+
import java.nio.ByteBuffer;
25+
import java.nio.ByteOrder;
26+
27+
import javax.microedition.khronos.opengles.GL10;
28+
29+
import android.app.Activity;
30+
import android.opengl.ETC1Util;
31+
import android.opengl.GLES10;
32+
import android.opengl.GLSurfaceView;
33+
import android.os.Bundle;
34+
import android.util.Log;
35+
36+
import com.example.android.apis.R;
37+
38+
/**
39+
* Demonstrate how to use ETC1 format compressed textures.
40+
* This sample can be recompiled to use either resource-based
41+
* textures (compressed offline using the etc1tool), or
42+
* textures created on the fly by compressing images.
43+
*
44+
*/
45+
public class CompressedTextureActivity extends Activity {
46+
private final static String TAG = "CompressedTextureActivity";
47+
/**
48+
* Choose between creating a compressed texture on the fly or
49+
* loading a compressed texture from a resource.
50+
*/
51+
private final static boolean TEST_CREATE_TEXTURE = false;
52+
/**
53+
* When creating a compressed texture on the fly, choose
54+
* whether or not to use the i/o stream APIs.
55+
*/
56+
private final static boolean USE_STREAM_IO = false;
57+
58+
@Override
59+
protected void onCreate(Bundle savedInstanceState) {
60+
super.onCreate(savedInstanceState);
61+
mGLView = new GLSurfaceView(this);
62+
mGLView.setEGLConfigChooser(false);
63+
StaticTriangleRenderer.TextureLoader loader;
64+
if (TEST_CREATE_TEXTURE) {
65+
loader = new SyntheticCompressedTextureLoader();
66+
} else {
67+
loader = new CompressedTextureLoader();
68+
}
69+
mGLView.setRenderer(new StaticTriangleRenderer(this, loader));
70+
setContentView(mGLView);
71+
}
72+
73+
@Override
74+
protected void onPause() {
75+
super.onPause();
76+
mGLView.onPause();
77+
}
78+
79+
@Override
80+
protected void onResume() {
81+
super.onResume();
82+
mGLView.onResume();
83+
}
84+
85+
/**
86+
* Demonstrate how to load a compressed texture from an APK resource.
87+
*
88+
*/
89+
private class CompressedTextureLoader implements StaticTriangleRenderer.TextureLoader {
90+
public void load(GL10 gl) {
91+
Log.w(TAG, "ETC1 texture support: " + ETC1Util.isETC1Supported());
92+
InputStream input = getResources().openRawResource(R.raw.androids);
93+
try {
94+
ETC1Util.loadTexture(GLES10.GL_TEXTURE_2D, 0, 0,
95+
GLES10.GL_RGB, GLES10.GL_UNSIGNED_SHORT_5_6_5, input);
96+
} catch (IOException e) {
97+
Log.w(TAG, "Could not load texture: " + e);
98+
} finally {
99+
try {
100+
input.close();
101+
} catch (IOException e) {
102+
// ignore exception thrown from close.
103+
}
104+
}
105+
}
106+
}
107+
108+
/**
109+
* Demonstrate how to create a compressed texture on the fly.
110+
*/
111+
private class SyntheticCompressedTextureLoader implements StaticTriangleRenderer.TextureLoader {
112+
public void load(GL10 gl) {
113+
int width = 128;
114+
int height = 128;
115+
Buffer image = createImage(width, height);
116+
ETC1Util.ETC1Texture etc1Texture = ETC1Util.compressTexture(image, width, height, 3, 3 * width);
117+
if (USE_STREAM_IO) {
118+
// Test the ETC1Util APIs for reading and writing compressed textures to I/O streams.
119+
try {
120+
ByteArrayOutputStream bos = new ByteArrayOutputStream();
121+
ETC1Util.writeTexture(etc1Texture, bos);
122+
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
123+
ETC1Util.loadTexture(GLES10.GL_TEXTURE_2D, 0, 0,
124+
GLES10.GL_RGB, GLES10.GL_UNSIGNED_SHORT_5_6_5, bis);
125+
} catch (IOException e) {
126+
Log.w(TAG, "Could not load texture: " + e);
127+
}
128+
} else {
129+
ETC1Util.loadTexture(GLES10.GL_TEXTURE_2D, 0, 0,
130+
GLES10.GL_RGB, GLES10.GL_UNSIGNED_SHORT_5_6_5, etc1Texture);
131+
}
132+
}
133+
134+
private Buffer createImage(int width, int height) {
135+
int stride = 3 * width;
136+
ByteBuffer image = ByteBuffer.allocateDirect(height * stride)
137+
.order(ByteOrder.nativeOrder());
138+
139+
// Fill with a pretty "munching squares" pattern:
140+
for (int t = 0; t < height; t++) {
141+
byte red = (byte)(255-2*t);
142+
byte green = (byte)(2*t);
143+
byte blue = 0;
144+
for (int x = 0; x < width; x++) {
145+
int y = x ^ t;
146+
image.position(stride*y+x*3);
147+
image.put(red);
148+
image.put(green);
149+
image.put(blue);
150+
}
151+
}
152+
image.position(0);
153+
return image;
154+
}
155+
}
156+
private GLSurfaceView mGLView;
157+
}

samples/ApiDemos/src/com/example/android/apis/graphics/StaticTriangleRenderer.java

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,25 @@
5050
*/
5151
public class StaticTriangleRenderer implements GLSurfaceView.Renderer{
5252

53+
public interface TextureLoader {
54+
/**
55+
* Load a texture into the currently bound OpenGL texture.
56+
*/
57+
void load(GL10 gl);
58+
}
59+
5360
public StaticTriangleRenderer(Context context) {
61+
init(context, new RobotTextureLoader());
62+
}
63+
64+
public StaticTriangleRenderer(Context context, TextureLoader loader) {
65+
init(context, loader);
66+
}
67+
68+
private void init(Context context, TextureLoader loader) {
5469
mContext = context;
5570
mTriangle = new Triangle();
71+
mTextureLoader = loader;
5672
}
5773

5874
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
@@ -99,22 +115,7 @@ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
99115

100116
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
101117
GL_REPLACE);
102-
103-
InputStream is = mContext.getResources()
104-
.openRawResource(R.raw.robot);
105-
Bitmap bitmap;
106-
try {
107-
bitmap = BitmapFactory.decodeStream(is);
108-
} finally {
109-
try {
110-
is.close();
111-
} catch(IOException e) {
112-
// Ignore.
113-
}
114-
}
115-
116-
GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);
117-
bitmap.recycle();
118+
mTextureLoader.load(gl);
118119
}
119120

120121
public void onDrawFrame(GL10 gl) {
@@ -181,6 +182,27 @@ public void onSurfaceChanged(GL10 gl, int w, int h) {
181182
private Context mContext;
182183
private Triangle mTriangle;
183184
private int mTextureID;
185+
private TextureLoader mTextureLoader;
186+
187+
private class RobotTextureLoader implements TextureLoader {
188+
public void load(GL10 gl) {
189+
InputStream is = mContext.getResources().openRawResource(
190+
R.raw.robot);
191+
Bitmap bitmap;
192+
try {
193+
bitmap = BitmapFactory.decodeStream(is);
194+
} finally {
195+
try {
196+
is.close();
197+
} catch (IOException e) {
198+
// Ignore.
199+
}
200+
}
201+
202+
GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);
203+
bitmap.recycle();
204+
}
205+
}
184206

185207
static class Triangle {
186208
public Triangle() {

tools/etc1tool/Android.mk

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Copyright 2009 Google Inc. All Rights Reserved.
2+
#
3+
# Android.mk for etc1tool
4+
#
5+
6+
LOCAL_PATH:= $(call my-dir)
7+
8+
include $(CLEAR_VARS)
9+
10+
LOCAL_SRC_FILES := etc1tool.cpp
11+
12+
LOCAL_C_INCLUDES += external/libpng
13+
LOCAL_C_INCLUDES += external/zlib
14+
LOCAL_C_INCLUDES += build/libs/host/include
15+
LOCAL_C_INCLUDES += frameworks/base/opengl/include
16+
17+
#LOCAL_WHOLE_STATIC_LIBRARIES :=
18+
LOCAL_STATIC_LIBRARIES := \
19+
libhost \
20+
libutils \
21+
libcutils \
22+
libexpat \
23+
libpng \
24+
libETC1
25+
26+
LOCAL_LDLIBS := -lz
27+
28+
ifeq ($(HOST_OS),linux)
29+
LOCAL_LDLIBS += -lrt
30+
endif
31+
32+
ifeq ($(HOST_OS),windows)
33+
ifeq ($(strip $(USE_CYGWIN),),)
34+
LOCAL_LDLIBS += -lws2_32
35+
endif
36+
endif
37+
38+
LOCAL_MODULE := etc1tool
39+
40+
include $(BUILD_HOST_EXECUTABLE)

0 commit comments

Comments
 (0)