├── LICENSE
├── README.md
├── images
├── dds_A1R5G5B5.dds
├── dds_A1R5G5B5_mipmap.dds
├── dds_A4R4G4B4.dds
├── dds_A4R4G4B4_mipmap.dds
├── dds_A8B8G8R8.dds
├── dds_A8B8G8R8_mipmap.dds
├── dds_A8R8G8B8.dds
├── dds_A8R8G8B8_mipmap.dds
├── dds_DXT1.dds
├── dds_DXT1_mipmap.dds
├── dds_DXT2.dds
├── dds_DXT2_mipmap.dds
├── dds_DXT3.dds
├── dds_DXT3_mipmap.dds
├── dds_DXT4.dds
├── dds_DXT4_mipmap.dds
├── dds_DXT5.dds
├── dds_DXT5_mipmap.dds
├── dds_R5G6B5.dds
├── dds_R5G6B5_mipmap.dds
├── dds_R8G8B8.dds
├── dds_R8G8B8_mipmap.dds
├── dds_X1R5G5B5.dds
├── dds_X1R5G5B5_mipmap.dds
├── dds_X4R4G4B4.dds
├── dds_X4R4G4B4_mipmap.dds
├── dds_X8B8G8R8.dds
├── dds_X8B8G8R8_mipmap.dds
├── dds_X8R8G8B8.dds
└── dds_X8R8G8B8_mipmap.dds
├── samples
├── DDSBitmapViewer_Android
│ ├── DDSBitmapViewerActivity.java
│ └── DDSBitmapViewer_Android.png
├── DDSGLViewer_Android
│ ├── DDSGLSurfaceView.java
│ ├── DDSGLViewerActivity.java
│ └── DDSGLViewer_Android.png
├── DDSGLViewer_iOS
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── DDSGLViewer_iOS.png
│ ├── Shader.fsh
│ ├── Shader.vsh
│ ├── ViewController.h
│ ├── ViewController.m
│ └── main.m
├── DDSImageViewer_iOS
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── DDSCollectionViewController.h
│ ├── DDSCollectionViewController.m
│ ├── DDSImageViewer_iOS.png
│ ├── ViewController.h
│ ├── ViewController.m
│ └── main.m
├── DDSSwingBufferedImage
│ ├── DDSSwingBufferedImage.java
│ └── DDSSwingBufferedImage.png
├── DDSWebGLViewer_GWT
│ ├── DDSWebGLViewer_GWT.png
│ └── TexturedCube.java
└── DDSWebViewer_GWT
│ ├── DDSWebViewer_GWT.png
│ └── ImageCanvasTest.java
└── src
├── c
├── dds_reader.c
└── dds_reader.h
└── java
└── DDSReader.java
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Kenji Sasaki
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DDSReader
2 | DDS image reader for Java and C.
3 |
4 | 
5 |
6 | Online DDS Canvas Demo page is http://npe-net.appspot.com/npesdk/gwt/ddsimagedemo/index.html
7 |
8 | 
9 |
10 | Online DDS WebGL Texture Demo page is http://npe-net.appspot.com/npesdk/gwt/ddswebgldemo/index.html
11 |
12 |
13 |
14 |
15 |
16 | ## License
17 |
18 | Released under the MIT license.
19 |
20 | https://github.com/npedotnet/DDSReader/blob/master/LICENSE
21 |
22 | ## Getting Started
23 |
24 | ### 1. Add the source code to your project.
25 |
26 | **Java**
27 | - Add src/java/DDSReader.java to your project, and modify package statement.
28 |
29 | **C**
30 | - Add src/c/dds_reader.{c,h} to your project.
31 |
32 | ### 2. Create a DDS binary data buffer.
33 |
34 | **Java**
35 | ```java
36 | FileInputStream fis = new FileInputStream(new File("test.dds"));
37 | byte [] buffer = new byte[fis.available()];
38 | fis.read(buffer);
39 | fis.close();
40 | ```
41 |
42 | **C**
43 | ```c
44 | #include "dds_reader.h"
45 |
46 | FILE *file = fopen("test.dds", "rb");
47 | if(file) {
48 | int size;
49 | fseek(file, 0, SEEK_END);
50 | size = ftell(file);
51 | fseek(file, 0, SEEK_SET);
52 |
53 | unsigned char *buffer = (unsigned char *)ddsMalloc(size);
54 | fread(buffer, 1, size, file);
55 | fclose(file);
56 | }
57 | ```
58 |
59 | ### 3. Create pixels with the RGBA byte order and mipmap parameter.
60 |
61 | ByteOrder|Java|C|Comments
62 | ---|---|---|---
63 | ARGB|DDSReader.ARGB|DDS_READER_ARGB|for java.awt.image.BufferedImage, android.graphics.Bitmap
64 | ABGR|DDSReader.ABGR|DDS_READER_ABGR|for OpenGL Texture(GL_RGBA), iOS UIImage
65 |
66 | **Java**
67 | ```java
68 | byte [] buffer = ...;
69 | int [] pixels = DDSReader.read(buffer, DDSReader.ARGB, 0);
70 | int width = DDSReader.getWidth(buffer);
71 | int height = DDSReader.getHeight(buffer);
72 | ```
73 |
74 | **C**
75 | ```c
76 | unsigned char *buffer = ...;
77 | int *pixels = ddsRead(buffer, DDS_READER_ABGR, 0);
78 | int width = ddsGetWidth(buffer);
79 | int height = ddsGetHeight(buffer);
80 | ```
81 |
82 | ### 4. Use created pixels in your application.
83 |
84 | #### 4.1. Java OpenGL Application
85 | Sample code to create Java OpenGL texture.
86 |
87 | **Java**
88 | ```java
89 | public int createDDSTexture() {
90 | int texture = 0;
91 |
92 | try {
93 | FileInputStream fis = new FileInputStream(path);
94 | byte [] buffer = new byte[fis.available()];
95 | fis.read(buffer);
96 | fis.close();
97 |
98 | int [] pixels = DDSReader.read(buffer, DDSReader.ABGR, 0);
99 | int width = DDSReader.getWidth(buffer);
100 | int height = DDSReader.getHeight(buffer);
101 | int mipmap = DDSReader.getMipmap(buffer);
102 |
103 | int [] textures = new int[1];
104 | gl.glGenTextures(1, textures, 0);
105 |
106 | gl.glEnable(GL.TEXTURE_2D);
107 | gl.glBindTexture(GL.TEXTURE_2D, textures[0]);
108 | gl.glPixelStorei(GL.UNPACK_ALIGNMENT, 4);
109 |
110 | if(mipmap > 0) {
111 | // mipmaps
112 | for(int i=0; (width > 0) || (height > 0); i++) {
113 | if(width <= 0) width = 1;
114 | if(height <= 0) height = 1;
115 | int [] pixels = DDSReader.read(buffer, DDSReader.ABGR, i);
116 |
117 | IntBuffer texBuffer = IntBuffer.wrap(pixels);
118 | gl.glTexImage2D(TEXTURE_2D, i, RGBA, width, height, 0, RGBA, UNSIGNED_BYTE, texBuffer);
119 |
120 | width /= 2;
121 | height /= 2;
122 | }
123 |
124 | gl.glTexParameteri(TEXTURE_2D, TEXTURE_WRAP_S, REPEAT);
125 | gl.glTexParameteri(TEXTURE_2D, TEXTURE_WRAP_T, REPEAT);
126 | gl.glTexParameteri(TEXTURE_2D, TEXTURE_MAG_FILTER, LINEAR);
127 | gl.glTexParameteri(TEXTURE_2D, TEXTURE_MIN_FILTER, LINEAR_MIPMAP_NEAREST);
128 | }
129 | else {
130 | // no mipmaps
131 | int [] pixels = DDSReader.read(buffer, DDSReader.ABGR, 0);
132 |
133 | IntBuffer texBuffer = IntBuffer.wrap(pixels);
134 | gl.glTexImage2D(TEXTURE_2D, 0, RGBA, width, height, 0, RGBA, UNSIGNED_BYTE, texBuffer);
135 |
136 | gl.glTexParameteri(TEXTURE_2D, TEXTURE_WRAP_S, REPEAT);
137 | gl.glTexParameteri(TEXTURE_2D, TEXTURE_WRAP_T, REPEAT);
138 | gl.glTexParameteri(TEXTURE_2D, TEXTURE_MAG_FILTER, LINEAR);
139 | gl.glTexParameteri(TEXTURE_2D, TEXTURE_MIN_FILTER, LINEAR);
140 |
141 | }
142 |
143 | texture = textures[0];
144 | }
145 | catch(Exception e) {
146 | e.printStackTrace();
147 | }
148 |
149 | return texture;
150 | }
151 | ```
152 |
153 | #### 4.2. Java Application
154 | Sample code to create java.awt.image.BufferedImage.
155 |
156 | **Java**
157 | ```java
158 | private static JLabel createDDSLabel(String path) throws IOException {
159 |
160 | FileInputStream fis = new FileInputStream(path);
161 | byte [] buffer = new byte[fis.available()];
162 | fis.read(buffer);
163 | fis.close();
164 |
165 | int [] pixels = DDSReader.read(buffer, DDSReader.ARGB, 0);
166 | int width = DDSReader.getWidth(buffer);
167 | int height = DDSReader.getHeight(buffer);
168 | BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
169 | image.setRGB(0, 0, width, height, pixels, 0, width);
170 |
171 | ImageIcon icon = new ImageIcon(image.getScaledInstance(128, 128, BufferedImage.SCALE_SMOOTH));
172 | return new JLabel(icon);
173 | }
174 | ```
175 |
176 | For more details, please refer to the sample project.
177 |
178 | https://github.com/npedotnet/DDSReader/tree/master/samples/DDSSwingBufferedImage
179 |
180 | #### 4.3. Android OpenGL Application
181 | Sample code to create Android OpenGL texture.
182 |
183 | **Java**
184 | ```java
185 | import static javax.microedition.khronos.opengles.GL10;
186 |
187 | public int createDDSTexture(GL10 gl, String path) {
188 | int texture = 0;
189 | try {
190 |
191 | InputStream is = getContext().getAssets().open(path);
192 | byte [] buffer = new byte[is.available()];
193 | is.read(buffer);
194 | is.close();
195 |
196 | int width = DDSReader.getWidth(buffer);
197 | int height = DDSReader.getHeight(buffer);
198 | int mipmap = DDSReader.getMipmap(buffer);
199 |
200 | int [] textures = new int[1];
201 | gl.glGenTextures(1, textures, 0);
202 |
203 | gl.glEnable(GL_TEXTURE_2D);
204 | gl.glBindTexture(GL_TEXTURE_2D, textures[0]);
205 | gl.glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
206 |
207 | if(mipmap > 0) {
208 | // mipmap
209 | for(int i=0; (width > 0) || (height > 0); i++) {
210 | if(width <= 0) width = 1;
211 | if(height <= 0) height = 1;
212 | int [] pixels = DDSReader.read(buffer, DDSReader.ABGR, i);
213 |
214 | IntBuffer texBuffer = IntBuffer.wrap(pixels);
215 | gl.glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texBuffer);
216 |
217 | width /= 2;
218 | height /= 2;
219 | }
220 |
221 | gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
222 | gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
223 | gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
224 | gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
225 | }
226 | else {
227 | // no mipmap
228 | int [] pixels = DDSReader.read(buffer, DDSReader.ABGR, 0);
229 |
230 | IntBuffer texBuffer = IntBuffer.wrap(pixels);
231 | gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texBuffer);
232 |
233 | gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
234 | gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
235 | gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
236 | gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
237 | }
238 |
239 | texture = textures[0];
240 |
241 | }
242 | catch (IOException e) {
243 | e.printStackTrace();
244 | }
245 |
246 | return texture;
247 | }
248 | ```
249 |
250 | For more details, please refer to the sample project.
251 |
252 | https://github.com/npedotnet/DDSReader/tree/master/samples/DDSGLViewer_Android
253 |
254 | #### 4.4. Android Application
255 | Sample code to create android.graphics.Bitmap.
256 |
257 | **Java**
258 | ```Java
259 | private Bitmap createDDSBitmap(String path) {
260 | Bitmap bitmap = null;
261 | try {
262 | InputStream is = getAssets().open(path);
263 | byte [] buffer = new byte[is.available()];
264 | is.read(buffer);
265 | is.close();
266 |
267 | int [] pixels = DDSReader.read(buffer, DDSReader.ARGB, 0);
268 | int width = DDSReader.getWidth(buffer);
269 | int height = DDSReader.getHeight(buffer);
270 |
271 | bitmap = Bitmap.createBitmap(pixels, 0, width, width, height, Config.ARGB_8888);
272 | }
273 | catch(Exception e) {
274 | e.printStackTrace();
275 | }
276 | return bitmap;
277 | }
278 | ```
279 | For more details, please refer to the sample project.
280 |
281 | https://github.com/npedotnet/DDSReader/tree/master/samples/DDSBitmapViewer_Android
282 |
283 | #### 4.5. iOS OpenGL Application
284 | Sample code to create iOS OpenGL texture.
285 |
286 | **Objective-C**
287 | ```objc
288 | - (GLuint)createDDSTexture:(NSString *)path {
289 |
290 | GLuint texture = 0;
291 |
292 | FILE *file = fopen([path UTF8String], "rb");
293 | if(file) {
294 | fseek(file, 0, SEEK_END);
295 | int size = ftell(file);
296 | fseek(file, 0, SEEK_SET);
297 |
298 | unsigned char *buffer = (unsigned char *)ddsMalloc(size);
299 | fread(buffer, 1, size, file);
300 | fclose(file);
301 |
302 | int width = ddsGetWidth(buffer);
303 | int height = ddsGetHeight(buffer);
304 | int mipmap = ddsGetMipmap(buffer);
305 |
306 | glGenTextures(1, &texture);
307 | glEnable(GL_TEXTURE_2D);
308 | glBindTexture(GL_TEXTURE_2D, texture);
309 | glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
310 |
311 | if(mipmap > 0) {
312 | // mipmap
313 | for(int i=0; (width > 0) || (height > 0); i++) {
314 | if(width <= 0) width = 1;
315 | if(height <= 0) height = 1;
316 | int *pixels = ddsRead(buffer, DDS_READER_ABGR, i);
317 |
318 | glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
319 |
320 | width /= 2;
321 | height /= 2;
322 |
323 | ddsFree(pixels);
324 | }
325 |
326 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
327 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
328 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
329 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
330 | }
331 | else {
332 | // no mipmap
333 | int *pixels = ddsRead(buffer, DDS_READER_ABGR, 0);
334 |
335 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
336 |
337 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
338 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
339 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
340 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
341 |
342 | ddsFree(pixels);
343 | }
344 |
345 | ddsFree(buffer);
346 | }
347 |
348 | return texture;
349 |
350 | }
351 | ```
352 |
353 | For more details, please refer to the sample project.
354 |
355 | https://github.com/npedotnet/DDSReader/tree/master/samples/DDSGLViewer_iOS
356 |
357 | #### 4.6. iOS Application
358 | Sample code to create iOS UIImage.
359 |
360 | **Objective-C**
361 | ```objc
362 | - (UIImage *)createDDSImage:(NSString *)path {
363 |
364 | FILE *file = fopen([path UTF8String], "rb");
365 | if(file) {
366 | fseek(file, 0, SEEK_END);
367 | int size = ftell(file);
368 | fseek(file, 0, SEEK_SET);
369 |
370 | unsigned char *buffer = (unsigned char *)ddsMalloc(size);
371 | fread(buffer, 1, size, file);
372 | fclose(file);
373 |
374 | int width = ddsGetWidth(buffer);
375 | int height = ddsGetHeight(buffer);
376 | int *pixels = ddsRead(buffer, DDS_READER_ABGR, 0);
377 |
378 | ddsFree(buffer);
379 |
380 | CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
381 | CGBitmapInfo bitmapInfo = (CGBitmapInfo)kCGImageAlphaLast;
382 | CGDataProviderRef providerRef = CGDataProviderCreateWithData(NULL, pixels, 4*width*height, releaseDataCallback);
383 |
384 | CGImageRef imageRef = CGImageCreate(width, height, 8, 32, 4*width, colorSpaceRef, bitmapInfo, providerRef, NULL, 0, kCGRenderingIntentDefault);
385 |
386 | UIImage *image = [[UIImage alloc] initWithCGImage:imageRef];
387 |
388 | CGColorSpaceRelease(colorSpaceRef);
389 |
390 | return image;
391 | }
392 |
393 | return nil;
394 |
395 | }
396 |
397 | static void releaseDataCallback(void *info, const void *data, size_t size) {
398 | ddsFree((void *)data);
399 | }
400 | ```
401 | For more details, please refer to the sample project.
402 |
403 | https://github.com/npedotnet/DDSReader/tree/master/samples/DDSImageViewer_iOS
404 |
405 | #### 4.7. GWT Web Application
406 |
407 | Sample code to create DDS HTML5 Canvas with GWT.
408 |
409 | **Java**
410 | ```java
411 | import com.google.gwt.canvas.client.Canvas;
412 | import com.google.gwt.canvas.dom.client.CanvasPixelArray;
413 | import com.google.gwt.canvas.dom.client.Context2d;
414 | import com.google.gwt.canvas.dom.client.ImageData;
415 | import com.google.gwt.typedarrays.client.Uint8ArrayNative;
416 | import com.google.gwt.typedarrays.shared.ArrayBuffer;
417 | import com.google.gwt.xhr.client.ReadyStateChangeHandler;
418 | import com.google.gwt.xhr.client.XMLHttpRequest;
419 | import com.google.gwt.xhr.client.XMLHttpRequest.ResponseType;
420 |
421 | private Canvas createImageCanvas(int [] pixels, int width, int height) {
422 |
423 | Canvas canvas = Canvas.createIfSupported();
424 | canvas.setCoordinateSpaceWidth(width);
425 | canvas.setCoordinateSpaceHeight(height);
426 |
427 | Context2d context = canvas.getContext2d();
428 | ImageData data = context.createImageData(width, height);
429 |
430 | CanvasPixelArray array = data.getData();
431 | for(int i=0; i> 8) & 0xFF);
434 | array.set(4*i+2, (pixels[i] >> 16) & 0xFF);
435 | array.set(4*i+3, (pixels[i] >> 24) & 0xFF);
436 | }
437 | context.putImageData(data, 0, 0);
438 |
439 | return canvas;
440 |
441 | }
442 |
443 | private void addDDSCanvas(String url) {
444 | XMLHttpRequest request = XMLHttpRequest.create();
445 | request.open("GET", url);
446 | request.setResponseType(ResponseType.ArrayBuffer);
447 | request.setOnReadyStateChange(new ReadyStateChangeHandler() {
448 | @Override
449 | public void onReadyStateChange(XMLHttpRequest xhr) {
450 | if(xhr.getReadyState() == XMLHttpRequest.DONE) {
451 | if(xhr.getStatus() >= 400) {
452 | // error
453 | System.out.println("Error");
454 | }
455 | else {
456 | try {
457 | ArrayBuffer arrayBuffer = xhr.getResponseArrayBuffer();
458 | Uint8ArrayNative u8array = Uint8ArrayNative.create(arrayBuffer);
459 | byte [] buffer = new byte[u8array.length()];
460 | for(int i=0; i 0) {
97 | // mipmap
98 | for(int i=0; (width > 0) || (height > 0); i++) {
99 | if(width <= 0) width = 1;
100 | if(height <= 0) height = 1;
101 | int [] pixels = DDSReader.read(buffer, DDSReader.ABGR, i);
102 |
103 | IntBuffer texBuffer = IntBuffer.wrap(pixels);
104 | gl.glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texBuffer);
105 |
106 | width /= 2;
107 | height /= 2;
108 | }
109 |
110 | gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
111 | gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
112 | gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
113 | gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
114 | }
115 | else {
116 | // no mipmap
117 | int [] pixels = DDSReader.read(buffer, DDSReader.ABGR, 0);
118 |
119 | IntBuffer texBuffer = IntBuffer.wrap(pixels);
120 | gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texBuffer);
121 |
122 | gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
123 | gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
124 | gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
125 | gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
126 | }
127 |
128 | texture = textures[0];
129 |
130 | }
131 | catch (IOException e) {
132 | e.printStackTrace();
133 | }
134 |
135 | return texture;
136 | }
137 |
138 | @Override
139 | public void onSurfaceCreated(GL10 gl, EGLConfig config) {
140 | ddsTextures[0] = createDDSTexture(gl, "images/dds_DXT1.dds");
141 | ddsTextures[1] = createDDSTexture(gl, "images/dds_DXT3.dds");
142 | ddsTextures[2] = createDDSTexture(gl, "images/dds_DXT5.dds");
143 | }
144 |
145 | @Override
146 | public void onSurfaceChanged(GL10 gl, int width, int height) {
147 | gl.glViewport(0, 0, width, height);
148 |
149 | gl.glMatrixMode(GL_PROJECTION);
150 | gl.glLoadIdentity();
151 | GLU.gluPerspective(gl, 45, (float)width/height, 1, 10);
152 | }
153 |
154 | @Override
155 | public void onDrawFrame(GL10 gl) {
156 | gl.glClearColor(0.5f, 0.5f, 0.5f, 1);
157 | gl.glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
158 |
159 | gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
160 | gl.glVertexPointer(3, GL10.GL_FLOAT, 0, positionBuffer);
161 |
162 | gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
163 | gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texcoordBuffer);
164 |
165 | gl.glEnable(GL_CULL_FACE);
166 | gl.glCullFace(GL_BACK);
167 |
168 | gl.glMatrixMode(GL10.GL_MODELVIEW);
169 | gl.glLoadIdentity();
170 | GLU.gluLookAt(gl, 3, 3, 3, 0, 0, 0, 0, 1, 0);
171 |
172 | // draw front and back
173 | draw(gl, ddsTextures[0]);
174 |
175 | // draw left and right
176 | gl.glPushMatrix();
177 | gl.glRotatef(90, 0, 1, 0);
178 | draw(gl, ddsTextures[1]);
179 | gl.glPopMatrix();
180 |
181 | // draw top and bottom
182 | gl.glPushMatrix();
183 | gl.glRotatef(-90, 1, 0, 0);
184 | draw(gl, ddsTextures[2]);
185 | gl.glPopMatrix();
186 | }
187 |
188 | private void draw(GL10 gl, int texture) {
189 |
190 | gl.glEnable(GL_TEXTURE_2D);
191 | gl.glActiveTexture(GL_TEXTURE0);
192 | gl.glBindTexture(GL_TEXTURE_2D, texture);
193 |
194 | // front
195 | gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
196 | // back
197 | gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4);
198 |
199 | gl.glDisable(GL_TEXTURE_2D);
200 | }
201 |
202 | private FloatBuffer positionBuffer;
203 | private FloatBuffer texcoordBuffer;
204 | private int [] ddsTextures = new int[3];
205 |
206 | }
207 |
--------------------------------------------------------------------------------
/samples/DDSGLViewer_Android/DDSGLViewerActivity.java:
--------------------------------------------------------------------------------
1 | /**
2 | * DDSGLViewerActivity.java
3 | *
4 | * Copyright (c) 2015 Kenji Sasaki
5 | * Released under the MIT license.
6 | * https://github.com/npedotnet/DDSReader/blob/master/LICENSE
7 | *
8 | * English document
9 | * https://github.com/npedotnet/DDSReader/blob/master/README.md
10 | *
11 | * Japanese document
12 | * http://3dtech.jp/wiki/index.php?DDSReader
13 | *
14 | */
15 |
16 | package com.example.ddsglviewer_android;
17 |
18 | import android.app.Activity;
19 | import android.os.Bundle;
20 |
21 | public class DDSGLViewerActivity extends Activity {
22 |
23 | @Override
24 | public void onCreate(Bundle savedInstanceState) {
25 | super.onCreate(savedInstanceState);
26 | view = new DDSGLSurfaceView(this);
27 | setContentView(view);
28 | }
29 |
30 | @Override
31 | public void onResume() {
32 | super.onResume();
33 | view.onResume();
34 | }
35 |
36 | @Override
37 | public void onPause() {
38 | super.onPause();
39 | view.onPause();
40 | }
41 |
42 | private DDSGLSurfaceView view;
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/samples/DDSGLViewer_Android/DDSGLViewer_Android.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/npedotnet/DDSReader/2a478378920ea13d8968ca967c68f5b257f55942/samples/DDSGLViewer_Android/DDSGLViewer_Android.png
--------------------------------------------------------------------------------
/samples/DDSGLViewer_iOS/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // DDSGLViewer_iOS
4 | //
5 | // Copyright (c) 2015 Kenji Sasaki
6 | // Released under the MIT license.
7 | // https://github.com/npedotnet/DDSReader/blob/master/LICENSE
8 | //
9 | // English document
10 | // https://github.com/npedotnet/DDSReader/blob/master/README.md
11 | //
12 | // Japanese document
13 | // http://3dtech.jp/wiki/index.php?DDSReader
14 | //
15 |
16 | #import
17 |
18 | @interface AppDelegate : UIResponder
19 |
20 | @property (strong, nonatomic) UIWindow *window;
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/samples/DDSGLViewer_iOS/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // DDSGLViewer_iOS
4 | //
5 | // Copyright (c) 2015 Kenji Sasaki
6 | // Released under the MIT license.
7 | // https://github.com/npedotnet/DDSReader/blob/master/LICENSE
8 | //
9 | // English document
10 | // https://github.com/npedotnet/DDSReader/blob/master/README.md
11 | //
12 | // Japanese document
13 | // http://3dtech.jp/wiki/index.php?DDSReader
14 | //
15 |
16 | #import "AppDelegate.h"
17 |
18 | @implementation AppDelegate
19 |
20 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
21 | {
22 | // Override point for customization after application launch.
23 | return YES;
24 | }
25 |
26 | - (void)applicationWillResignActive:(UIApplication *)application
27 | {
28 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
29 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
30 | }
31 |
32 | - (void)applicationDidEnterBackground:(UIApplication *)application
33 | {
34 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
35 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
36 | }
37 |
38 | - (void)applicationWillEnterForeground:(UIApplication *)application
39 | {
40 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
41 | }
42 |
43 | - (void)applicationDidBecomeActive:(UIApplication *)application
44 | {
45 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
46 | }
47 |
48 | - (void)applicationWillTerminate:(UIApplication *)application
49 | {
50 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
51 | }
52 |
53 | @end
54 |
--------------------------------------------------------------------------------
/samples/DDSGLViewer_iOS/DDSGLViewer_iOS.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/npedotnet/DDSReader/2a478378920ea13d8968ca967c68f5b257f55942/samples/DDSGLViewer_iOS/DDSGLViewer_iOS.png
--------------------------------------------------------------------------------
/samples/DDSGLViewer_iOS/Shader.fsh:
--------------------------------------------------------------------------------
1 | //
2 | // Shader.fsh
3 | // DDSGLViewer_iOS
4 | //
5 | // Copyright (c) 2015 Kenji Sasaki
6 | // Released under the MIT license.
7 | // https://github.com/npedotnet/DDSReader/blob/master/LICENSE
8 | //
9 | // English document
10 | // https://github.com/npedotnet/DDSReader/blob/master/README.md
11 | //
12 | // Japanese document
13 | // http://3dtech.jp/wiki/index.php?DDSReader
14 | //
15 |
16 | varying lowp vec2 vTexcoord;
17 |
18 | uniform sampler2D texture;
19 |
20 | void main()
21 | {
22 | gl_FragColor = texture2D(texture, vTexcoord);
23 | }
24 |
--------------------------------------------------------------------------------
/samples/DDSGLViewer_iOS/Shader.vsh:
--------------------------------------------------------------------------------
1 | //
2 | // Shader.vsh
3 | // DDSGLViewer_iOS
4 | //
5 | // Copyright (c) 2015 Kenji Sasaki
6 | // Released under the MIT license.
7 | // https://github.com/npedotnet/DDSReader/blob/master/LICENSE
8 | //
9 | // English document
10 | // https://github.com/npedotnet/DDSReader/blob/master/README.md
11 | //
12 | // Japanese document
13 | // http://3dtech.jp/wiki/index.php?DDSReader
14 | //
15 |
16 | attribute vec4 position;
17 | attribute vec2 texcoord;
18 |
19 | varying lowp vec2 vTexcoord;
20 |
21 | uniform mat4 modelViewProjectionMatrix;
22 |
23 | void main()
24 | {
25 | vTexcoord = texcoord;
26 | gl_Position = modelViewProjectionMatrix * position;
27 | }
28 |
--------------------------------------------------------------------------------
/samples/DDSGLViewer_iOS/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // DDSGLViewer_iOS
4 | //
5 | // Copyright (c) 2015 Kenji Sasaki
6 | // Released under the MIT license.
7 | // https://github.com/npedotnet/DDSReader/blob/master/LICENSE
8 | //
9 | // English document
10 | // https://github.com/npedotnet/DDSReader/blob/master/README.md
11 | //
12 | // Japanese document
13 | // http://3dtech.jp/wiki/index.php?DDSReader
14 | //
15 |
16 | #import
17 | #import
18 |
19 | @interface ViewController : GLKViewController
20 |
21 | @end
22 |
--------------------------------------------------------------------------------
/samples/DDSGLViewer_iOS/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // DDSGLViewer_iOS
4 | //
5 | // Copyright (c) 2015 Kenji Sasaki
6 | // Released under the MIT license.
7 | // https://github.com/npedotnet/DDSReader/blob/master/LICENSE
8 | //
9 | // English document
10 | // https://github.com/npedotnet/DDSReader/blob/master/README.md
11 | //
12 | // Japanese document
13 | // http://3dtech.jp/wiki/index.php?DDSReader
14 | //
15 |
16 | #import "ViewController.h"
17 | #include "dds_reader.h"
18 |
19 | #define BUFFER_OFFSET(i) ((char *)NULL + (i))
20 |
21 | static float POSITIONS[] = {
22 | // front
23 | -0.5f, +0.5f, +0.5f,
24 | -0.5f, -0.5f, +0.5f,
25 | +0.5f, +0.5f, +0.5f,
26 | +0.5f, -0.5f, +0.5f,
27 | // back
28 | +0.5f, +0.5f, -0.5f,
29 | +0.5f, -0.5f, -0.5f,
30 | -0.5f, +0.5f, -0.5f,
31 | -0.5f, -0.5f, -0.5f,
32 | };
33 |
34 | static float TEXCOORDS[] = {
35 | // front
36 | 0.f, 0.f,
37 | 0.f, 1.f,
38 | 1.f, 0.f,
39 | 1.f, 1.f,
40 | // back
41 | 0.f, 0.f,
42 | 0.f, 1.f,
43 | 1.f, 0.f,
44 | 1.f, 1.f,
45 | };
46 |
47 | @interface ViewController () {
48 | GLuint _program;
49 |
50 | GLKMatrix4 _mvpMatrices[3];
51 | GLint _textures[3];
52 |
53 | GLuint _vertexBuffer;
54 | }
55 | @property (strong, nonatomic) EAGLContext *context;
56 |
57 | - (void)setupGL;
58 | - (void)tearDownGL;
59 |
60 | - (GLuint)createDDSTexture:(NSString *)path;
61 | - (BOOL)loadShaders;
62 | - (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file;
63 | - (BOOL)linkProgram:(GLuint)prog;
64 | - (BOOL)validateProgram:(GLuint)prog;
65 | @end
66 |
67 | @implementation ViewController
68 |
69 | - (void)viewDidLoad
70 | {
71 | [super viewDidLoad];
72 |
73 | self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
74 |
75 | if (!self.context) {
76 | NSLog(@"Failed to create ES context");
77 | }
78 |
79 | GLKView *view = (GLKView *)self.view;
80 | view.context = self.context;
81 | view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
82 |
83 | [self setupGL];
84 | }
85 |
86 | - (void)dealloc
87 | {
88 | [self tearDownGL];
89 |
90 | if ([EAGLContext currentContext] == self.context) {
91 | [EAGLContext setCurrentContext:nil];
92 | }
93 | }
94 |
95 | - (void)didReceiveMemoryWarning
96 | {
97 | [super didReceiveMemoryWarning];
98 |
99 | if ([self isViewLoaded] && ([[self view] window] == nil)) {
100 | self.view = nil;
101 |
102 | [self tearDownGL];
103 |
104 | if ([EAGLContext currentContext] == self.context) {
105 | [EAGLContext setCurrentContext:nil];
106 | }
107 | self.context = nil;
108 | }
109 |
110 | // Dispose of any resources that can be recreated.
111 | }
112 |
113 | - (void)setupGL
114 | {
115 | [EAGLContext setCurrentContext:self.context];
116 |
117 | [self loadShaders];
118 |
119 | glEnable(GL_DEPTH_TEST);
120 |
121 | int positionSize = sizeof(POSITIONS);
122 | int texcoordSize = sizeof(TEXCOORDS);
123 | int vertexBufferSize = positionSize + texcoordSize;
124 | int positionOffset = 0;
125 | int texcoordOffset = positionOffset + positionSize;
126 |
127 | glGenBuffers(1, &_vertexBuffer);
128 | glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
129 | glBufferData(GL_ARRAY_BUFFER, vertexBufferSize, NULL, GL_STATIC_DRAW);
130 | glBufferSubData(GL_ARRAY_BUFFER, positionOffset, positionSize, POSITIONS);
131 | glBufferSubData(GL_ARRAY_BUFFER, texcoordOffset, texcoordSize, TEXCOORDS);
132 |
133 | _textures[0] = [self createDDSTexture:[[NSBundle mainBundle] pathForResource:@"dds_DXT1" ofType:@"dds"]];
134 | _textures[1] = [self createDDSTexture:[[NSBundle mainBundle] pathForResource:@"dds_DXT3" ofType:@"dds"]];
135 | _textures[2] = [self createDDSTexture:[[NSBundle mainBundle] pathForResource:@"dds_DXT5" ofType:@"dds"]];
136 |
137 | }
138 |
139 | - (void)tearDownGL
140 | {
141 | [EAGLContext setCurrentContext:self.context];
142 |
143 | glDeleteBuffers(1, &_vertexBuffer);
144 |
145 | glDeleteTextures(3, (const GLuint *)_textures);
146 |
147 | if (_program) {
148 | glDeleteProgram(_program);
149 | _program = 0;
150 | }
151 | }
152 |
153 | - (GLuint)createDDSTexture:(NSString *)path {
154 |
155 | GLuint texture = 0;
156 |
157 | FILE *file = fopen([path UTF8String], "rb");
158 | if(file) {
159 | fseek(file, 0, SEEK_END);
160 | int size = ftell(file);
161 | fseek(file, 0, SEEK_SET);
162 |
163 | unsigned char *buffer = (unsigned char *)ddsMalloc(size);
164 | fread(buffer, 1, size, file);
165 | fclose(file);
166 |
167 | int width = ddsGetWidth(buffer);
168 | int height = ddsGetHeight(buffer);
169 | int mipmap = ddsGetMipmap(buffer);
170 |
171 | glGenTextures(1, &texture);
172 | glEnable(GL_TEXTURE_2D);
173 | glBindTexture(GL_TEXTURE_2D, texture);
174 | glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
175 |
176 | if(mipmap > 0) {
177 | // mipmap
178 | for(int i=0; (width > 0) || (height > 0); i++) {
179 | if(width <= 0) width = 1;
180 | if(height <= 0) height = 1;
181 | int *pixels = ddsRead(buffer, DDS_READER_ABGR, i);
182 |
183 | glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
184 |
185 | width /= 2;
186 | height /= 2;
187 |
188 | ddsFree(pixels);
189 | }
190 |
191 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
192 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
193 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
194 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
195 | }
196 | else {
197 | // no mipmap
198 | int *pixels = ddsRead(buffer, DDS_READER_ABGR, 0);
199 |
200 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
201 |
202 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
203 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
204 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
205 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
206 |
207 | ddsFree(pixels);
208 | }
209 |
210 | ddsFree(buffer);
211 | }
212 |
213 | return texture;
214 |
215 | }
216 |
217 | #pragma mark - GLKView and GLKViewController delegate methods
218 |
219 | - (void)update
220 | {
221 | float aspect = fabsf(self.view.bounds.size.width / self.view.bounds.size.height);
222 |
223 | GLKMatrix4 projection = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(45.0f), aspect, 1.f, 10.0f);
224 | GLKMatrix4 view = GLKMatrix4MakeLookAt(3, 3, 3, 0, 0, 0, 0, 1, 0);
225 | GLKMatrix4 vp = GLKMatrix4Multiply(projection, view);
226 |
227 | // front/back
228 | _mvpMatrices[0] = vp;
229 |
230 | // left/right
231 | GLKMatrix4 m = GLKMatrix4MakeRotation(M_PI*0.5f, 0, 1, 0);
232 | _mvpMatrices[1] = GLKMatrix4Multiply(vp, m);
233 |
234 | // top/bottom
235 | m = GLKMatrix4MakeRotation(M_PI*0.5f, -1, 0, 0);
236 | _mvpMatrices[2] = GLKMatrix4Multiply(vp, m);
237 |
238 | }
239 |
240 | - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
241 | {
242 | glClearColor(0.65f, 0.65f, 0.65f, 1.0f);
243 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
244 | glEnable(GL_CULL_FACE);
245 | glCullFace(GL_BACK);
246 |
247 | // Render the object again with ES2
248 | glUseProgram(_program);
249 |
250 | glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
251 |
252 | // vertexattrib
253 | int posAttr = glGetAttribLocation(_program, "position");
254 | glEnableVertexAttribArray(posAttr);
255 | int positionOffset = 0;
256 | glVertexAttribPointer(posAttr, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(positionOffset));
257 |
258 | int texAttr = glGetAttribLocation(_program, "texcoord");
259 | glEnableVertexAttribArray(texAttr);
260 | int texcoordOffset = sizeof(POSITIONS);
261 | glVertexAttribPointer(texAttr, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(texcoordOffset));
262 |
263 | // uniform
264 | GLint mvpUniform = glGetUniformLocation(_program, "modelViewProjectionMatrix");
265 |
266 | GLint texUniform = glGetUniformLocation(_program, "texturea");
267 | glUniform1i(texUniform, 0);
268 |
269 | glEnable(GL_TEXTURE_2D);
270 | glActiveTexture(GL_TEXTURE0);
271 |
272 | // draw front/back
273 | glUniformMatrix4fv(mvpUniform, 1, 0, _mvpMatrices[0].m);
274 | glBindTexture(GL_TEXTURE_2D, _textures[0]);
275 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
276 | glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
277 |
278 | // draw left/right
279 | glUniformMatrix4fv(mvpUniform, 1, 0, _mvpMatrices[1].m);
280 | glBindTexture(GL_TEXTURE_2D, _textures[1]);
281 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
282 | glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
283 |
284 | // draw top/bottom
285 | glUniformMatrix4fv(mvpUniform, 1, 0, _mvpMatrices[2].m);
286 | glBindTexture(GL_TEXTURE_2D, _textures[2]);
287 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
288 | glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
289 |
290 | }
291 |
292 | #pragma mark - OpenGL ES 2 shader compilation
293 |
294 | - (BOOL)loadShaders
295 | {
296 | GLuint vertShader, fragShader;
297 | NSString *vertShaderPathname, *fragShaderPathname;
298 |
299 | // Create shader program.
300 | _program = glCreateProgram();
301 |
302 | // Create and compile vertex shader.
303 | vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"];
304 | if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) {
305 | NSLog(@"Failed to compile vertex shader");
306 | return NO;
307 | }
308 |
309 | // Create and compile fragment shader.
310 | fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"];
311 | if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) {
312 | NSLog(@"Failed to compile fragment shader");
313 | return NO;
314 | }
315 |
316 | // Attach vertex shader to program.
317 | glAttachShader(_program, vertShader);
318 |
319 | // Attach fragment shader to program.
320 | glAttachShader(_program, fragShader);
321 |
322 | // Link program.
323 | if (![self linkProgram:_program]) {
324 | NSLog(@"Failed to link program: %d", _program);
325 |
326 | if (vertShader) {
327 | glDeleteShader(vertShader);
328 | vertShader = 0;
329 | }
330 | if (fragShader) {
331 | glDeleteShader(fragShader);
332 | fragShader = 0;
333 | }
334 | if (_program) {
335 | glDeleteProgram(_program);
336 | _program = 0;
337 | }
338 |
339 | return NO;
340 | }
341 |
342 | // Release vertex and fragment shaders.
343 | if (vertShader) {
344 | glDetachShader(_program, vertShader);
345 | glDeleteShader(vertShader);
346 | }
347 | if (fragShader) {
348 | glDetachShader(_program, fragShader);
349 | glDeleteShader(fragShader);
350 | }
351 |
352 | return YES;
353 | }
354 |
355 | - (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file
356 | {
357 | GLint status;
358 | const GLchar *source;
359 |
360 | source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String];
361 | if (!source) {
362 | NSLog(@"Failed to load vertex shader");
363 | return NO;
364 | }
365 |
366 | *shader = glCreateShader(type);
367 | glShaderSource(*shader, 1, &source, NULL);
368 | glCompileShader(*shader);
369 |
370 | #if defined(DEBUG)
371 | GLint logLength;
372 | glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);
373 | if (logLength > 0) {
374 | GLchar *log = (GLchar *)malloc(logLength);
375 | glGetShaderInfoLog(*shader, logLength, &logLength, log);
376 | NSLog(@"Shader compile log:\n%s", log);
377 | free(log);
378 | }
379 | #endif
380 |
381 | glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
382 | if (status == 0) {
383 | glDeleteShader(*shader);
384 | return NO;
385 | }
386 |
387 | return YES;
388 | }
389 |
390 | - (BOOL)linkProgram:(GLuint)prog
391 | {
392 | GLint status;
393 | glLinkProgram(prog);
394 |
395 | #if defined(DEBUG)
396 | GLint logLength;
397 | glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
398 | if (logLength > 0) {
399 | GLchar *log = (GLchar *)malloc(logLength);
400 | glGetProgramInfoLog(prog, logLength, &logLength, log);
401 | NSLog(@"Program link log:\n%s", log);
402 | free(log);
403 | }
404 | #endif
405 |
406 | glGetProgramiv(prog, GL_LINK_STATUS, &status);
407 | if (status == 0) {
408 | return NO;
409 | }
410 |
411 | return YES;
412 | }
413 |
414 | - (BOOL)validateProgram:(GLuint)prog
415 | {
416 | GLint logLength, status;
417 |
418 | glValidateProgram(prog);
419 | glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
420 | if (logLength > 0) {
421 | GLchar *log = (GLchar *)malloc(logLength);
422 | glGetProgramInfoLog(prog, logLength, &logLength, log);
423 | NSLog(@"Program validate log:\n%s", log);
424 | free(log);
425 | }
426 |
427 | glGetProgramiv(prog, GL_VALIDATE_STATUS, &status);
428 | if (status == 0) {
429 | return NO;
430 | }
431 |
432 | return YES;
433 | }
434 |
435 | @end
436 |
--------------------------------------------------------------------------------
/samples/DDSGLViewer_iOS/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // DDSGLViewer_iOS
4 | //
5 | // Copyright (c) 2015 Kenji Sasaki
6 | // Released under the MIT license.
7 | // https://github.com/npedotnet/DDSReader/blob/master/LICENSE
8 | //
9 | // English document
10 | // https://github.com/npedotnet/DDSReader/blob/master/README.md
11 | //
12 | // Japanese document
13 | // http://3dtech.jp/wiki/index.php?DDSReader
14 | //
15 |
16 | #import
17 |
18 | #import "AppDelegate.h"
19 |
20 | int main(int argc, char * argv[])
21 | {
22 | @autoreleasepool {
23 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/samples/DDSImageViewer_iOS/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // DDSImageViewer_iOS
4 | //
5 | // Copyright (c) 2015 Kenji Sasaki
6 | // Released under the MIT license.
7 | // https://github.com/npedotnet/DDSReader/blob/master/LICENSE
8 | //
9 | // English document
10 | // https://github.com/npedotnet/DDSReader/blob/master/README.md
11 | //
12 | // Japanese document
13 | // http://3dtech.jp/wiki/index.php?DDSReader
14 | //
15 |
16 | #import
17 |
18 | @interface AppDelegate : UIResponder
19 |
20 | @property (strong, nonatomic) UIWindow *window;
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/samples/DDSImageViewer_iOS/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // DDSImageViewer_iOS
4 | //
5 | // Copyright (c) 2015 Kenji Sasaki
6 | // Released under the MIT license.
7 | // https://github.com/npedotnet/DDSReader/blob/master/LICENSE
8 | //
9 | // English document
10 | // https://github.com/npedotnet/DDSReader/blob/master/README.md
11 | //
12 | // Japanese document
13 | // http://3dtech.jp/wiki/index.php?DDSReader
14 | //
15 |
16 | #import "AppDelegate.h"
17 |
18 | @implementation AppDelegate
19 |
20 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
21 | {
22 | // Override point for customization after application launch.
23 | return YES;
24 | }
25 |
26 | - (void)applicationWillResignActive:(UIApplication *)application
27 | {
28 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
29 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
30 | }
31 |
32 | - (void)applicationDidEnterBackground:(UIApplication *)application
33 | {
34 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
35 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
36 | }
37 |
38 | - (void)applicationWillEnterForeground:(UIApplication *)application
39 | {
40 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
41 | }
42 |
43 | - (void)applicationDidBecomeActive:(UIApplication *)application
44 | {
45 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
46 | }
47 |
48 | - (void)applicationWillTerminate:(UIApplication *)application
49 | {
50 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
51 | }
52 |
53 | @end
54 |
--------------------------------------------------------------------------------
/samples/DDSImageViewer_iOS/DDSCollectionViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // DDSCollectionViewController.h
3 | // DDSImageViewer_iOS
4 | //
5 | // Copyright (c) 2015 Kenji Sasaki
6 | // Released under the MIT license.
7 | // https://github.com/npedotnet/DDSReader/blob/master/LICENSE
8 | //
9 | // English document
10 | // https://github.com/npedotnet/DDSReader/blob/master/README.md
11 | //
12 | // Japanese document
13 | // http://3dtech.jp/wiki/index.php?DDSReader
14 | //
15 |
16 | #import
17 |
18 | @interface DDSCollectionViewController : UICollectionViewController
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/samples/DDSImageViewer_iOS/DDSCollectionViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // DDSCollectionViewController.m
3 | // DDSImageViewer_iOS
4 | //
5 | // Copyright (c) 2015 Kenji Sasaki
6 | // Released under the MIT license.
7 | // https://github.com/npedotnet/DDSReader/blob/master/LICENSE
8 | //
9 | // English document
10 | // https://github.com/npedotnet/DDSReader/blob/master/README.md
11 | //
12 | // Japanese document
13 | // http://3dtech.jp/wiki/index.php?DDSReader
14 | //
15 |
16 | #import "DDSCollectionViewController.h"
17 | #include "dds_reader.h"
18 |
19 | @interface DDSCollectionViewController () {
20 | NSArray *images;
21 | }
22 | @end
23 |
24 | @implementation DDSCollectionViewController
25 |
26 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
27 | {
28 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
29 | if (self) {
30 | // Custom initialization
31 | }
32 | return self;
33 | }
34 |
35 | - (void)viewDidLoad
36 | {
37 | [super viewDidLoad];
38 | // Do any additional setup after loading the view.
39 | images = [NSArray arrayWithObjects:
40 | @"dds_DXT1",
41 | @"dds_DXT2",
42 | @"dds_DXT3",
43 | @"dds_DXT4",
44 | @"dds_DXT5",
45 | @"dds_A1R5G5B5",
46 | @"dds_X1R5G5B5",
47 | @"dds_A4R4G4B4",
48 | @"dds_X4R4G4B4",
49 | @"dds_R5G6B5",
50 | @"dds_A8B8G8R8",
51 | @"dds_X8B8G8R8",
52 | @"dds_A8R8G8B8",
53 | @"dds_X8R8G8B8",
54 | nil];
55 |
56 | }
57 |
58 | - (void)didReceiveMemoryWarning
59 | {
60 | [super didReceiveMemoryWarning];
61 | // Dispose of any resources that can be recreated.
62 | }
63 |
64 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
65 | return images.count;
66 | }
67 |
68 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
69 |
70 | UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
71 |
72 | UIImageView *imageView = (UIImageView *)[cell viewWithTag:100];
73 | NSString *path = [[NSBundle mainBundle] pathForResource:[images objectAtIndex:indexPath.row] ofType:@"dds"];
74 | imageView.image = [self createDDSImage:path];
75 |
76 | return cell;
77 |
78 | }
79 |
80 | - (UIImage *)createDDSImage:(NSString *)path {
81 |
82 | FILE *file = fopen([path UTF8String], "rb");
83 | if(file) {
84 | fseek(file, 0, SEEK_END);
85 | int size = ftell(file);
86 | fseek(file, 0, SEEK_SET);
87 |
88 | unsigned char *buffer = (unsigned char *)ddsMalloc(size);
89 | fread(buffer, 1, size, file);
90 | fclose(file);
91 |
92 | int width = ddsGetWidth(buffer);
93 | int height = ddsGetHeight(buffer);
94 | int *pixels = ddsRead(buffer, DDS_READER_ABGR, 0);
95 |
96 | ddsFree(buffer);
97 |
98 | CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
99 | CGBitmapInfo bitmapInfo = (CGBitmapInfo)kCGImageAlphaLast;
100 | CGDataProviderRef providerRef = CGDataProviderCreateWithData(NULL, pixels, 4*width*height, releaseDataCallback);
101 |
102 | CGImageRef imageRef = CGImageCreate(width, height, 8, 32, 4*width, colorSpaceRef, bitmapInfo, providerRef, NULL, 0, kCGRenderingIntentDefault);
103 |
104 | UIImage *image = [[UIImage alloc] initWithCGImage:imageRef];
105 |
106 | CGColorSpaceRelease(colorSpaceRef);
107 |
108 | return image;
109 | }
110 |
111 | return nil;
112 |
113 | }
114 |
115 | static void releaseDataCallback(void *info, const void *data, size_t size) {
116 | ddsFree((void *)data);
117 | }
118 |
119 | /*
120 | #pragma mark - Navigation
121 |
122 | // In a storyboard-based application, you will often want to do a little preparation before navigation
123 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
124 | {
125 | // Get the new view controller using [segue destinationViewController].
126 | // Pass the selected object to the new view controller.
127 | }
128 | */
129 |
130 | @end
131 |
--------------------------------------------------------------------------------
/samples/DDSImageViewer_iOS/DDSImageViewer_iOS.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/npedotnet/DDSReader/2a478378920ea13d8968ca967c68f5b257f55942/samples/DDSImageViewer_iOS/DDSImageViewer_iOS.png
--------------------------------------------------------------------------------
/samples/DDSImageViewer_iOS/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // DDSImageViewer_iOS
4 | //
5 | // Copyright (c) 2015 Kenji Sasaki
6 | // Released under the MIT license.
7 | // https://github.com/npedotnet/DDSReader/blob/master/LICENSE
8 | //
9 | // English document
10 | // https://github.com/npedotnet/DDSReader/blob/master/README.md
11 | //
12 | // Japanese document
13 | // http://3dtech.jp/wiki/index.php?DDSReader
14 | //
15 |
16 | #import
17 |
18 | @interface ViewController : UIViewController
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/samples/DDSImageViewer_iOS/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // DDSImageViewer_iOS
4 | //
5 | // Copyright (c) 2015 Kenji Sasaki
6 | // Released under the MIT license.
7 | // https://github.com/npedotnet/DDSReader/blob/master/LICENSE
8 | //
9 | // English document
10 | // https://github.com/npedotnet/DDSReader/blob/master/README.md
11 | //
12 | // Japanese document
13 | // http://3dtech.jp/wiki/index.php?DDSReader
14 | //
15 |
16 | #import "ViewController.h"
17 |
18 | @interface ViewController ()
19 |
20 | @end
21 |
22 | @implementation ViewController
23 |
24 | - (void)viewDidLoad
25 | {
26 | [super viewDidLoad];
27 | // Do any additional setup after loading the view, typically from a nib.
28 | }
29 |
30 | - (void)didReceiveMemoryWarning
31 | {
32 | [super didReceiveMemoryWarning];
33 | // Dispose of any resources that can be recreated.
34 | }
35 |
36 | @end
37 |
--------------------------------------------------------------------------------
/samples/DDSImageViewer_iOS/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // DDSImageViewer_iOS
4 | //
5 | // Copyright (c) 2015 Kenji Sasaki
6 | // Released under the MIT license.
7 | // https://github.com/npedotnet/DDSReader/blob/master/LICENSE
8 | //
9 | // English document
10 | // https://github.com/npedotnet/DDSReader/blob/master/README.md
11 | //
12 | // Japanese document
13 | // http://3dtech.jp/wiki/index.php?DDSReader
14 | //
15 |
16 | #import
17 |
18 | #import "AppDelegate.h"
19 |
20 | int main(int argc, char * argv[])
21 | {
22 | @autoreleasepool {
23 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/samples/DDSSwingBufferedImage/DDSSwingBufferedImage.java:
--------------------------------------------------------------------------------
1 | /**
2 | * DDSSwingBufferedImage.java
3 | *
4 | * Copyright (c) 2015 Kenji Sasaki
5 | * Released under the MIT license.
6 | * https://github.com/npedotnet/DDSReader/blob/master/LICENSE
7 | *
8 | * English document
9 | * https://github.com/npedotnet/DDSReader/blob/master/README.md
10 | *
11 | * Japanese document
12 | * http://3dtech.jp/wiki/index.php?DDSReader
13 | *
14 | */
15 |
16 | import java.awt.Color;
17 | import java.awt.image.BufferedImage;
18 | import java.io.FileInputStream;
19 | import java.io.IOException;
20 |
21 | import javax.swing.ImageIcon;
22 | import javax.swing.JFrame;
23 | import javax.swing.JLabel;
24 | import javax.swing.JPanel;
25 |
26 | public class DDSSwingBufferedImage {
27 |
28 | private static final String [] DDS_PATHS = {
29 | "images/dds_DXT1.dds",
30 | "images/dds_DXT3.dds",
31 | "images/dds_DXT5.dds",
32 | "images/dds_A4R4G4B4.dds",
33 | "images/dds_R5G6B5.dds",
34 | "images/dds_A8B8G8R8.dds",
35 | };
36 |
37 | public static void main(String [] args) {
38 | try {
39 | JPanel panel = new JPanel();
40 | panel.setBackground(Color.ORANGE);
41 | for(int i=0; ionModuleLoad().
26 | */
27 | public class TexturedCube implements EntryPoint {
28 |
29 | private float [] VERTICES = {
30 | // position.xyz, texcoord.xy
31 | // front
32 | -0.5f, +0.5f, +0.5f, 0.f, 0.f,
33 | -0.5f, -0.5f, +0.5f, 0.f, 1.f,
34 | +0.5f, +0.5f, +0.5f, 1.f, 0.f,
35 | +0.5f, -0.5f, +0.5f, 1.f, 1.f,
36 | // back
37 | +0.5f, +0.5f, -0.5f, 0.f, 0.f,
38 | +0.5f, -0.5f, -0.5f, 0.f, 1.f,
39 | -0.5f, +0.5f, -0.5f, 1.f, 0.f,
40 | -0.5f, -0.5f, -0.5f, 1.f, 1.f,
41 | };
42 |
43 | private String VERTEX_SHADER_SOURCE =
44 | "attribute vec3 position;"+
45 | "attribute vec2 texcoord;"+
46 | "varying vec2 vTexcoord;"+
47 | "uniform mat4 MVP;"+
48 | "void main() { gl_Position = MVP * vec4(position, 1.0); vTexcoord = texcoord; }";
49 |
50 | private String FRAGMENT_SHADER_SOURCE =
51 | "precision highp float;"+
52 | "varying vec2 vTexcoord;"+
53 | "uniform sampler2D texture;"+
54 | "void main() { gl_FragColor = texture2D(texture, vTexcoord); }";
55 |
56 | private float [][] MODELMATRICES = {
57 | { // none
58 | 1, 0, 0, 0,
59 | 0, 1, 0, 0,
60 | 0, 0, 1, 0,
61 | 0, 0, 0, 1,
62 | },
63 | { // rotY90
64 | 0, 0, -1, 0,
65 | 0, 1, 0, 0,
66 | 1, 0, 0, 0,
67 | 0, 0, 0, 1,
68 | },
69 | { // rotX-90
70 | 1, 0, 0, 0,
71 | 0, 0, -1, 0,
72 | 0, 1, 0, 0,
73 | 0, 0, 0, 1,
74 | },
75 | };
76 |
77 | public static final String [] TEXTURE_URLS = {
78 | "images/dds_DXT1.dds",
79 | "images/dds_DXT3.dds",
80 | "images/dds_DXT5.dds",
81 | };
82 |
83 | public void onModuleLoad() {
84 |
85 | Canvas canvas = Canvas.createIfSupported();
86 | canvas.setStyleName("MyCanvas");
87 | canvas.setCoordinateSpaceWidth(400);
88 | canvas.setCoordinateSpaceHeight(400);
89 | RootLayoutPanel.get().add(canvas);
90 |
91 | gl = (WebGLRenderingContext)canvas.getContext("experimental-webgl");
92 | gl.viewport(0, 0, 400, 400);
93 |
94 | WebGLBuffer vertexBuffer = gl.createBuffer();
95 | gl.bindBuffer(ARRAY_BUFFER, vertexBuffer);
96 | gl.bufferData(ARRAY_BUFFER, Float32Array.create(VERTICES), STATIC_DRAW);
97 |
98 | WebGLShader vertexShader = gl.createShader(VERTEX_SHADER);
99 | gl.shaderSource(vertexShader, VERTEX_SHADER_SOURCE);
100 | gl.compileShader(vertexShader);
101 |
102 | WebGLShader fragmentShader = gl.createShader(FRAGMENT_SHADER);
103 | gl.shaderSource(fragmentShader, FRAGMENT_SHADER_SOURCE);
104 | gl.compileShader(fragmentShader);
105 |
106 | program = gl.createProgram();
107 | gl.attachShader(program, vertexShader);
108 | gl.attachShader(program, fragmentShader);
109 | gl.linkProgram(program);
110 |
111 | gl.useProgram(program);
112 | gl.bindBuffer(ARRAY_BUFFER, vertexBuffer);
113 |
114 | WebGLUniformLocation texture = gl.getUniformLocation(program, "texture");
115 | gl.uniform1i(texture, 0);
116 |
117 | int posAttr = gl.getAttribLocation(program, "position");
118 | gl.vertexAttribPointer(posAttr, 3, FLOAT, false, 5*4, 0);
119 | gl.enableVertexAttribArray(posAttr);
120 |
121 | int texAttr = gl.getAttribLocation(program, "texcoord");
122 | gl.vertexAttribPointer(texAttr, 2, FLOAT, false, 5*4, 3*4);
123 | gl.enableVertexAttribArray(texAttr);
124 |
125 | for(int i=0; i> 8) & 0xFF);
183 | array.set(4*i+2, (pixels[i] >> 16) & 0xFF);
184 | array.set(4*i+3, (pixels[i] >> 24) & 0xFF);
185 | }
186 | context.putImageData(data, 0, 0);
187 |
188 | return canvas;
189 |
190 | }
191 |
192 | void loadTexture(String url, int index) {
193 | final int i = index;
194 | XMLHttpRequest request = XMLHttpRequest.create();
195 | request.open("GET", url);
196 | request.setResponseType(ResponseType.ArrayBuffer);
197 | request.setOnReadyStateChange(new ReadyStateChangeHandler() {
198 | @Override
199 | public void onReadyStateChange(XMLHttpRequest xhr) {
200 | if(xhr.getReadyState() == XMLHttpRequest.DONE) {
201 | if(xhr.getStatus() >= 400) {
202 | // error
203 | System.out.println("Error");
204 | }
205 | else {
206 | try {
207 | ArrayBuffer arrayBuffer = xhr.getResponseArrayBuffer();
208 | Uint8ArrayNative u8array = Uint8ArrayNative.create(arrayBuffer);
209 | byte [] buffer = new byte[u8array.length()];
210 | for(int i=0; ionModuleLoad().
20 | */
21 | public class ImageCanvasTest implements EntryPoint {
22 |
23 | private static String [] DDS_FILES = {
24 | "dds_A1R5G5B5.dds",
25 | "dds_A4R4G4B4.dds",
26 | "dds_A8B8G8R8.dds",
27 | "dds_A8R8G8B8.dds",
28 | "dds_DXT1.dds",
29 | "dds_DXT2.dds",
30 | "dds_DXT3.dds",
31 | "dds_DXT4.dds",
32 | "dds_DXT5.dds",
33 | "dds_R5G6B5.dds",
34 | "dds_R8G8B8.dds",
35 | "dds_X1R5G5B5.dds",
36 | "dds_X4R4G4B4.dds",
37 | "dds_X8B8G8R8.dds",
38 | "dds_X8R8G8B8.dds",
39 | };
40 |
41 | public void onModuleLoad() {
42 |
43 | panel = new FlowPanel();
44 | panel.getElement().getStyle().setBackgroundColor("orange");
45 |
46 | for(int i=0; i= 400) {
65 | // error
66 | System.out.println("Error");
67 | }
68 | else {
69 | try {
70 | ArrayBuffer arrayBuffer = xhr.getResponseArrayBuffer();
71 | Uint8ArrayNative u8array = Uint8ArrayNative.create(arrayBuffer);
72 | byte [] buffer = new byte[u8array.length()];
73 | for(int i=0; i> 8) & 0xFF);
106 | array.set(4*i+2, (pixels[i] >> 16) & 0xFF);
107 | array.set(4*i+3, (pixels[i] >> 24) & 0xFF);
108 | }
109 | context.putImageData(data, 0, 0);
110 |
111 | canvas.getElement().getStyle().setMargin(4, Unit.PX);
112 |
113 | return canvas;
114 |
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/src/c/dds_reader.c:
--------------------------------------------------------------------------------
1 | /**
2 | * dds_reader.c
3 | *
4 | * Copyright (c) 2015 Kenji Sasaki
5 | * Released under the MIT license.
6 | * https://github.com/npedotnet/DDSReader/blob/master/LICENSE
7 | *
8 | * English document
9 | * https://github.com/npedotnet/DDSReader/blob/master/README.md
10 | *
11 | * Japanese document
12 | * http://3dtech.jp/wiki/index.php?DDSReader
13 | *
14 | */
15 |
16 | #include "dds_reader.h"
17 |
18 | static const DDS_ORDER _DDS_READER_ARGB = { 16, 8, 0, 24 };
19 | const DDS_ORDER *DDS_READER_ARGB = &_DDS_READER_ARGB;
20 |
21 | static const DDS_ORDER _DDS_READER_ABGR = { 0, 8, 16, 24 };
22 | const DDS_ORDER *DDS_READER_ABGR = &_DDS_READER_ABGR;
23 |
24 | void *ddsMalloc(size_t size) {
25 | return malloc(size);
26 | }
27 |
28 | void ddsFree(void *memory) {
29 | free(memory);
30 | }
31 |
32 | int ddsGetHeight(unsigned const char * buffer) {
33 | return (buffer[12] & 0xFF) | (buffer[13] & 0xFF) << 8 | (buffer[14] & 0xFF) << 16 | (buffer[15] & 0xFF) << 24;
34 | }
35 |
36 | int ddsGetWidth(unsigned const char * buffer) {
37 | return (buffer[16] & 0xFF) | (buffer[17] & 0xFF) << 8 | (buffer[18] & 0xFF) << 16 | (buffer[19] & 0xFF) << 24;
38 | }
39 |
40 | int ddsGetMipmap(unsigned const char * buffer) {
41 | return (buffer[28] & 0xFF) | (buffer[29] & 0xFF) << 8 | (buffer[30] & 0xFF) << 16 | (buffer[31] & 0xFF) << 24;
42 | }
43 |
44 | int ddsGetPixelFormatFlags(unsigned const char * buffer) {
45 | return (buffer[80] & 0xFF) | (buffer[81] & 0xFF) << 8 | (buffer[82] & 0xFF) << 16 | (buffer[83] & 0xFF) << 24;
46 | }
47 |
48 | int ddsGetFourCC(unsigned const char * buffer) {
49 | return (buffer[84] & 0xFF) << 24 | (buffer[85] & 0xFF) << 16 | (buffer[86] & 0xFF) << 8 | (buffer[87] & 0xFF);
50 | }
51 |
52 | int ddsGetBitCount(unsigned const char * buffer) {
53 | return (buffer[88] & 0xFF) | (buffer[89] & 0xFF) << 8 | (buffer[90] & 0xFF) << 16 | (buffer[91] & 0xFF) << 24;
54 | }
55 |
56 | int ddsGetRedMask(unsigned const char * buffer) {
57 | return (buffer[92] & 0xFF) | (buffer[93] & 0xFF) << 8 | (buffer[94] & 0xFF) << 16 | (buffer[95] & 0xFF) << 24;
58 | }
59 |
60 | int ddsGetGreenMask(unsigned const char * buffer) {
61 | return (buffer[96] & 0xFF) | (buffer[97] & 0xFF) << 8 | (buffer[98] & 0xFF) << 16 | (buffer[99] & 0xFF) << 24;
62 | }
63 |
64 | int ddsGetBlueMask(unsigned const char * buffer) {
65 | return (buffer[100] & 0xFF) | (buffer[101] & 0xFF) << 8 | (buffer[102] & 0xFF) << 16 | (buffer[103] & 0xFF) << 24;
66 | }
67 |
68 | int ddsGetAlphaMask(unsigned const char * buffer) {
69 | return (buffer[104] & 0xFF) | (buffer[105] & 0xFF) << 8 | (buffer[106] & 0xFF) << 16 | (buffer[107] & 0xFF) << 24;
70 | }
71 |
72 | // Image Type
73 | #define DXT1 (0x44585431)
74 | #define DXT2 (0x44585432)
75 | #define DXT3 (0x44585433)
76 | #define DXT4 (0x44585434)
77 | #define DXT5 (0x44585435)
78 | #define A1R5G5B5 ((1 << 16) | 2)
79 | #define X1R5G5B5 ((2 << 16) | 2)
80 | #define A4R4G4B4 ((3 << 16) | 2)
81 | #define X4R4G4B4 ((4 << 16) | 2)
82 | #define R5G6B5 ((5 << 16) | 2)
83 | #define R8G8B8 ((1 << 16) | 3)
84 | #define A8B8G8R8 ((1 << 16) | 4)
85 | #define X8B8G8R8 ((2 << 16) | 4)
86 | #define A8R8G8B8 ((3 << 16) | 4)
87 | #define X8R8G8B8 ((4 << 16) | 4)
88 |
89 | // RGBA Masks
90 | static const int A1R5G5B5_MASKS[] = { 0x7C00, 0x03E0, 0x001F, 0x8000 };
91 | static const int X1R5G5B5_MASKS[] = { 0x7C00, 0x03E0, 0x001F, 0x0000 };
92 | static const int A4R4G4B4_MASKS[] = { 0x0F00, 0x00F0, 0x000F, 0xF000 };
93 | static const int X4R4G4B4_MASKS[] = { 0x0F00, 0x00F0, 0x000F, 0x0000 };
94 | static const int R5G6B5_MASKS[] = { 0xF800, 0x07E0, 0x001F, 0x0000 };
95 | static const int R8G8B8_MASKS[] = { 0xFF0000, 0x00FF00, 0x0000FF, 0x000000 };
96 | static const int A8B8G8R8_MASKS[] = { 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 };
97 | static const int X8B8G8R8_MASKS[] = { 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 };
98 | static const int A8R8G8B8_MASKS[] = { 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 };
99 | static const int X8R8G8B8_MASKS[] = { 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 };
100 |
101 | // BIT4 = 17 * index;
102 | static const int BIT5[] = { 0, 8, 16, 25, 33, 41, 49, 58, 66, 74, 82, 90, 99, 107, 115, 123, 132, 140, 148, 156, 165, 173, 181, 189, 197, 206, 214, 222, 230, 239, 247, 255 };
103 | static const int BIT6[] = { 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 130, 134, 138, 142, 146, 150, 154, 158, 162, 166, 170, 174, 178, 182, 186, 190, 194, 198, 202, 206, 210, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251, 255 };
104 |
105 | // Prototypes
106 | static int ddsGetType(const unsigned char *buffer);
107 | static int *ddsDecodeDXT1(int width, int height, int offset, unsigned const char *buffer, const DDS_ORDER *order);
108 | static int *ddsDecodeDXT2(int width, int height, int offset, unsigned const char *buffer, const DDS_ORDER *order);
109 | static int *ddsDecodeDXT3(int width, int height, int offset, unsigned const char *buffer, const DDS_ORDER *order);
110 | static int *ddsDecodeDXT4(int width, int height, int offset, unsigned const char *buffer, const DDS_ORDER *order);
111 | static int *ddsDecodeDXT5(int width, int height, int offset, unsigned const char *buffer, const DDS_ORDER *order);
112 | static int *ddsReadA1R5G5B5(int width, int height, int offset, unsigned const char *buffer, const DDS_ORDER *order);
113 | static int *ddsReadX1R5G5B5(int width, int height, int offset, unsigned const char *buffer, const DDS_ORDER *order);
114 | static int *ddsReadA4R4G4B4(int width, int height, int offset, unsigned const char *buffer, const DDS_ORDER *order);
115 | static int *ddsReadX4R4G4B4(int width, int height, int offset, unsigned const char *buffer, const DDS_ORDER *order);
116 | static int *ddsReadR5G6B5(int width, int height, int offset, unsigned const char *buffer, const DDS_ORDER *order);
117 | static int *ddsReadR8G8B8(int width, int height, int offset, unsigned const char *buffer, const DDS_ORDER *order);
118 | static int *ddsReadA8B8G8R8(int width, int height, int offset, unsigned const char *buffer, const DDS_ORDER *order);
119 | static int *ddsReadX8B8G8R8(int width, int height, int offset, unsigned const char *buffer, const DDS_ORDER *order);
120 | static int *ddsReadA8R8G8B8(int width, int height, int offset, unsigned const char *buffer, const DDS_ORDER *order);
121 | static int *ddsReadX8R8G8B8(int width, int height, int offset, unsigned const char *buffer, const DDS_ORDER *order);
122 | static int ddsGetDXTColor(int c0, int c1, int a, int t, const DDS_ORDER *order);
123 | static int ddsGetDXTColor2_1(int c0, int c1, int a, const DDS_ORDER *order);
124 | static int ddsGetDXTColor1_1(int c0, int c1, int a, const DDS_ORDER *order);
125 | static int ddsGetDXTColor1(int c, int a, const DDS_ORDER *order);
126 | static int ddsGetDXT5Alpha(int a0, int a1, int t);
127 |
128 | int *ddsRead(const unsigned char *buffer, const DDS_ORDER *order, int mipmapLevel) {
129 |
130 | // header
131 | int width = ddsGetWidth(buffer);
132 | int height = ddsGetHeight(buffer);
133 | int mipmap = ddsGetMipmap(buffer);
134 | int offset;
135 |
136 | // type
137 | int type = ddsGetType(buffer);
138 | if (type == 0) return NULL;
139 |
140 | // offset
141 | offset = 128; // header size
142 | if (mipmapLevel > 0 && mipmapLevel < mipmap) {
143 | for (int i = 0; i= height) break;
288 | int t0 = (buffer[index] & 0x03);
289 | int t1 = (buffer[index] & 0x0C) >> 2;
290 | int t2 = (buffer[index] & 0x30) >> 4;
291 | int t3 = (buffer[index++] & 0xC0) >> 6;
292 | pixels[4 * width*i + 4 * j + width*k + 0] = ddsGetDXTColor(c0, c1, 0xFF, t0, order);
293 | if (4 * j + 1 >= width) continue;
294 | pixels[4 * width*i + 4 * j + width*k + 1] = ddsGetDXTColor(c0, c1, 0xFF, t1, order);
295 | if (4 * j + 2 >= width) continue;
296 | pixels[4 * width*i + 4 * j + width*k + 2] = ddsGetDXTColor(c0, c1, 0xFF, t2, order);
297 | if (4 * j + 3 >= width) continue;
298 | pixels[4 * width*i + 4 * j + width*k + 3] = ddsGetDXTColor(c0, c1, 0xFF, t3, order);
299 | }
300 | }
301 | }
302 | return pixels;
303 | }
304 |
305 | int *ddsDecodeDXT2(int width, int height, int offset, const unsigned char *buffer, const DDS_ORDER *order) {
306 | return ddsDecodeDXT3(width, height, offset, buffer, order);
307 | }
308 |
309 | int *ddsDecodeDXT3(int width, int height, int offset, const unsigned char *buffer, const DDS_ORDER *order) {
310 | int *pixels = (int *)ddsMalloc(4 * width*height);
311 | int index = offset;
312 | int w = (width + 3) / 4;
313 | int h = (height + 3) / 4;
314 | int alphaTable[16];
315 | for (int i = 0; i> 4);
323 | alphaTable[4 * k + 1] = 17 * (a0 & 0x0F);
324 | alphaTable[4 * k + 2] = 17 * ((a1 & 0xF0) >> 4);
325 | alphaTable[4 * k + 3] = 17 * (a1 & 0x0F);
326 | }
327 | int c0 = (buffer[index] & 0xFF) | (buffer[index + 1] & 0xFF) << 8; index += 2;
328 | int c1 = (buffer[index] & 0xFF) | (buffer[index + 1] & 0xFF) << 8; index += 2;
329 | for (int k = 0; k<4; k++) {
330 | if (4 * i + k >= height) break;
331 | int t0 = (buffer[index] & 0x03);
332 | int t1 = (buffer[index] & 0x0C) >> 2;
333 | int t2 = (buffer[index] & 0x30) >> 4;
334 | int t3 = (buffer[index++] & 0xC0) >> 6;
335 | pixels[4 * width*i + 4 * j + width*k + 0] = ddsGetDXTColor(c0, c1, alphaTable[4 * k + 0], t0, order);
336 | if (4 * j + 1 >= width) continue;
337 | pixels[4 * width*i + 4 * j + width*k + 1] = ddsGetDXTColor(c0, c1, alphaTable[4 * k + 1], t1, order);
338 | if (4 * j + 2 >= width) continue;
339 | pixels[4 * width*i + 4 * j + width*k + 2] = ddsGetDXTColor(c0, c1, alphaTable[4 * k + 2], t2, order);
340 | if (4 * j + 3 >= width) continue;
341 | pixels[4 * width*i + 4 * j + width*k + 3] = ddsGetDXTColor(c0, c1, alphaTable[4 * k + 3], t3, order);
342 | }
343 | }
344 | }
345 | return pixels;
346 | }
347 |
348 | int *ddsDecodeDXT4(int width, int height, int offset, const unsigned char *buffer, const DDS_ORDER *order) {
349 | return ddsDecodeDXT5(width, height, offset, buffer, order);
350 | }
351 |
352 | int *ddsDecodeDXT5(int width, int height, int offset, const unsigned char *buffer, const DDS_ORDER *order) {
353 | int *pixels = (int *)ddsMalloc(4 * width*height);
354 | int index = offset;
355 | int w = (width + 3) / 4;
356 | int h = (height + 3) / 4;
357 | int alphaTable[16];
358 | for (int i = 0; i> 3) & 0x07;
367 | alphaTable[2] = (b0 >> 6) & 0x07;
368 | alphaTable[3] = (b0 >> 9) & 0x07;
369 | alphaTable[4] = (b0 >> 12) & 0x07;
370 | alphaTable[5] = (b0 >> 15) & 0x07;
371 | alphaTable[6] = (b0 >> 18) & 0x07;
372 | alphaTable[7] = (b0 >> 21) & 0x07;
373 | alphaTable[8] = b1 & 0x07;
374 | alphaTable[9] = (b1 >> 3) & 0x07;
375 | alphaTable[10] = (b1 >> 6) & 0x07;
376 | alphaTable[11] = (b1 >> 9) & 0x07;
377 | alphaTable[12] = (b1 >> 12) & 0x07;
378 | alphaTable[13] = (b1 >> 15) & 0x07;
379 | alphaTable[14] = (b1 >> 18) & 0x07;
380 | alphaTable[15] = (b1 >> 21) & 0x07;
381 | int c0 = (buffer[index] & 0xFF) | (buffer[index + 1] & 0xFF) << 8; index += 2;
382 | int c1 = (buffer[index] & 0xFF) | (buffer[index + 1] & 0xFF) << 8; index += 2;
383 | for (int k = 0; k<4; k++) {
384 | if (4 * i + k >= height) break;
385 | int t0 = (buffer[index] & 0x03);
386 | int t1 = (buffer[index] & 0x0C) >> 2;
387 | int t2 = (buffer[index] & 0x30) >> 4;
388 | int t3 = (buffer[index++] & 0xC0) >> 6;
389 | pixels[4 * width*i + 4 * j + width*k + 0] = ddsGetDXTColor(c0, c1, ddsGetDXT5Alpha(a0, a1, alphaTable[4 * k + 0]), t0, order);
390 | if (4 * j + 1 >= width) continue;
391 | pixels[4 * width*i + 4 * j + width*k + 1] = ddsGetDXTColor(c0, c1, ddsGetDXT5Alpha(a0, a1, alphaTable[4 * k + 1]), t1, order);
392 | if (4 * j + 2 >= width) continue;
393 | pixels[4 * width*i + 4 * j + width*k + 2] = ddsGetDXTColor(c0, c1, ddsGetDXT5Alpha(a0, a1, alphaTable[4 * k + 2]), t2, order);
394 | if (4 * j + 3 >= width) continue;
395 | pixels[4 * width*i + 4 * j + width*k + 3] = ddsGetDXTColor(c0, c1, ddsGetDXT5Alpha(a0, a1, alphaTable[4 * k + 3]), t3, order);
396 | }
397 | }
398 | }
399 | return pixels;
400 | }
401 |
402 | int *ddsReadA1R5G5B5(int width, int height, int offset, const unsigned char *buffer, const DDS_ORDER *order) {
403 | int index = offset;
404 | int *pixels = (int *)ddsMalloc(4*width*height);
405 | for (int i = 0; i> 10];
408 | int g = BIT5[(rgba & A1R5G5B5_MASKS[1]) >> 5];
409 | int b = BIT5[(rgba & A1R5G5B5_MASKS[2])];
410 | int a = 255 * ((rgba & A1R5G5B5_MASKS[3]) >> 15);
411 | pixels[i] = (a << order->alphaShift) | (r << order->redShift) | (g << order->greenShift) | (b << order->blueShift);
412 | }
413 | return pixels;
414 | }
415 |
416 | int *ddsReadX1R5G5B5(int width, int height, int offset, const unsigned char *buffer, const DDS_ORDER *order) {
417 | int index = offset;
418 | int *pixels = (int *)ddsMalloc(4 * width*height);
419 | for (int i = 0; i> 10];
422 | int g = BIT5[(rgba & X1R5G5B5_MASKS[1]) >> 5];
423 | int b = BIT5[(rgba & X1R5G5B5_MASKS[2])];
424 | int a = 255;
425 | pixels[i] = (a << order->alphaShift) | (r << order->redShift) | (g << order->greenShift) | (b << order->blueShift);
426 | }
427 | return pixels;
428 | }
429 |
430 | int *ddsReadA4R4G4B4(int width, int height, int offset, const unsigned char *buffer, const DDS_ORDER *order) {
431 | int index = offset;
432 | int *pixels = (int *)ddsMalloc(4 * width*height);
433 | for (int i = 0; i> 8);
436 | int g = 17 * ((rgba & A4R4G4B4_MASKS[1]) >> 4);
437 | int b = 17 * ((rgba & A4R4G4B4_MASKS[2]));
438 | int a = 17 * ((rgba & A4R4G4B4_MASKS[3]) >> 12);
439 | pixels[i] = (a << order->alphaShift) | (r << order->redShift) | (g << order->greenShift) | (b << order->blueShift);
440 | }
441 | return pixels;
442 | }
443 |
444 | int *ddsReadX4R4G4B4(int width, int height, int offset, const unsigned char *buffer, const DDS_ORDER *order) {
445 | int index = offset;
446 | int *pixels = (int *)ddsMalloc(4 * width*height);
447 | for (int i = 0; i> 8);
450 | int g = 17 * ((rgba & A4R4G4B4_MASKS[1]) >> 4);
451 | int b = 17 * ((rgba & A4R4G4B4_MASKS[2]));
452 | int a = 255;
453 | pixels[i] = (a << order->alphaShift) | (r << order->redShift) | (g << order->greenShift) | (b << order->blueShift);
454 | }
455 | return pixels;
456 | }
457 |
458 | int *ddsReadR5G6B5(int width, int height, int offset, const unsigned char *buffer, const DDS_ORDER *order) {
459 | int index = offset;
460 | int *pixels = (int *)ddsMalloc(4 * width*height);
461 | for (int i = 0; i> 11)];
464 | int g = BIT6[((rgba & R5G6B5_MASKS[1]) >> 5)];
465 | int b = BIT5[((rgba & R5G6B5_MASKS[2]))];
466 | int a = 255;
467 | pixels[i] = (a << order->alphaShift) | (r << order->redShift) | (g << order->greenShift) | (b << order->blueShift);
468 | }
469 | return pixels;
470 | }
471 |
472 | int *ddsReadR8G8B8(int width, int height, int offset, const unsigned char *buffer, const DDS_ORDER *order) {
473 | int index = offset;
474 | int *pixels = (int *)ddsMalloc(4 * width*height);
475 | for (int i = 0; ialphaShift) | (r << order->redShift) | (g << order->greenShift) | (b << order->blueShift);
481 | }
482 | return pixels;
483 | }
484 |
485 | int *ddsReadA8B8G8R8(int width, int height, int offset, const unsigned char *buffer, const DDS_ORDER *order) {
486 | int index = offset;
487 | int *pixels = (int *)ddsMalloc(4 * width*height);
488 | for (int i = 0; ialphaShift) | (r << order->redShift) | (g << order->greenShift) | (b << order->blueShift);
494 | }
495 | return pixels;
496 | }
497 |
498 | int *ddsReadX8B8G8R8(int width, int height, int offset, const unsigned char *buffer, const DDS_ORDER *order) {
499 | int index = offset;
500 | int *pixels = (int *)ddsMalloc(4 * width*height);
501 | for (int i = 0; ialphaShift) | (r << order->redShift) | (g << order->greenShift) | (b << order->blueShift);
507 | }
508 | return pixels;
509 | }
510 |
511 | int *ddsReadA8R8G8B8(int width, int height, int offset, const unsigned char *buffer, const DDS_ORDER *order) {
512 | int index = offset;
513 | int *pixels = (int *)ddsMalloc(4 * width*height);
514 | for (int i = 0; ialphaShift) | (r << order->redShift) | (g << order->greenShift) | (b << order->blueShift);
520 | }
521 | return pixels;
522 | }
523 |
524 | int *ddsReadX8R8G8B8(int width, int height, int offset, const unsigned char *buffer, const DDS_ORDER *order) {
525 | int index = offset;
526 | int *pixels = (int *)ddsMalloc(4 * width*height);
527 | for (int i = 0; ialphaShift) | (r << order->redShift) | (g << order->greenShift) | (b << order->blueShift);
533 | }
534 | return pixels;
535 | }
536 |
537 | int ddsGetDXTColor(int c0, int c1, int a, int t, const DDS_ORDER *order) {
538 | switch (t) {
539 | case 0: return ddsGetDXTColor1(c0, a, order);
540 | case 1: return ddsGetDXTColor1(c1, a, order);
541 | case 2: return (c0 > c1) ? ddsGetDXTColor2_1(c0, c1, a, order) : ddsGetDXTColor1_1(c0, c1, a, order);
542 | case 3: return (c0 > c1) ? ddsGetDXTColor2_1(c1, c0, a, order) : 0;
543 | }
544 | return 0;
545 | }
546 |
547 | int ddsGetDXTColor2_1(int c0, int c1, int a, const DDS_ORDER *order) {
548 | // 2*c0/3 + c1/3
549 | int r = (2 * BIT5[(c0 & 0xFC00) >> 11] + BIT5[(c1 & 0xFC00) >> 11]) / 3;
550 | int g = (2 * BIT6[(c0 & 0x07E0) >> 5] + BIT6[(c1 & 0x07E0) >> 5]) / 3;
551 | int b = (2 * BIT5[c0 & 0x001F] + BIT5[c1 & 0x001F]) / 3;
552 | return (a << order->alphaShift) | (r << order->redShift) | (g << order->greenShift) | (b << order->blueShift);
553 | }
554 |
555 | int ddsGetDXTColor1_1(int c0, int c1, int a, const DDS_ORDER *order) {
556 | // (c0+c1) / 2
557 | int r = (BIT5[(c0 & 0xFC00) >> 11] + BIT5[(c1 & 0xFC00) >> 11]) / 2;
558 | int g = (BIT6[(c0 & 0x07E0) >> 5] + BIT6[(c1 & 0x07E0) >> 5]) / 2;
559 | int b = (BIT5[c0 & 0x001F] + BIT5[c1 & 0x001F]) / 2;
560 | return (a << order->alphaShift) | (r << order->redShift) | (g << order->greenShift) | (b << order->blueShift);
561 | }
562 |
563 | int ddsGetDXTColor1(int c, int a, const DDS_ORDER *order) {
564 | int r = BIT5[(c & 0xFC00) >> 11];
565 | int g = BIT6[(c & 0x07E0) >> 5];
566 | int b = BIT5[(c & 0x001F)];
567 | return (a << order->alphaShift) | (r << order->redShift) | (g << order->greenShift) | (b << order->blueShift);
568 | }
569 |
570 | int ddsGetDXT5Alpha(int a0, int a1, int t) {
571 | if (a0 > a1) switch (t) {
572 | case 0: return a0;
573 | case 1: return a1;
574 | case 2: return (6 * a0 + a1) / 7;
575 | case 3: return (5 * a0 + 2 * a1) / 7;
576 | case 4: return (4 * a0 + 3 * a1) / 7;
577 | case 5: return (3 * a0 + 4 * a1) / 7;
578 | case 6: return (2 * a0 + 5 * a1) / 7;
579 | case 7: return (a0 + 6 * a1) / 7;
580 | }
581 | else switch (t) {
582 | case 0: return a0;
583 | case 1: return a1;
584 | case 2: return (4 * a0 + a1) / 5;
585 | case 3: return (3 * a0 + 2 * a1) / 5;
586 | case 4: return (2 * a0 + 3 * a1) / 5;
587 | case 5: return (a0 + 4 * a1) / 5;
588 | case 6: return 0;
589 | case 7: return 255;
590 | }
591 | return 0;
592 | }
593 |
594 | /* EOF */
595 |
--------------------------------------------------------------------------------
/src/c/dds_reader.h:
--------------------------------------------------------------------------------
1 | /**
2 | * dds_reader.h
3 | *
4 | * Copyright (c) 2015 Kenji Sasaki
5 | * Released under the MIT license.
6 | * https://github.com/npedotnet/DDSReader/blob/master/LICENSE
7 | *
8 | * English document
9 | * https://github.com/npedotnet/DDSReader/blob/master/README.md
10 | *
11 | * Japanese document
12 | * http://3dtech.jp/wiki/index.php?DDSReader
13 | *
14 | */
15 |
16 | #ifndef __DDS_READER_H__
17 | #define __DDS_READER_H__
18 |
19 | #include
20 | #include
21 |
22 | #ifdef __cplusplus
23 | extern "C" {
24 | #endif
25 |
26 | typedef struct _DDS_ORDER {
27 | int redShift;
28 | int greenShift;
29 | int blueShift;
30 | int alphaShift;
31 | } DDS_ORDER;
32 |
33 | const DDS_ORDER *DDS_READER_ARGB;
34 | const DDS_ORDER *DDS_READER_ABGR;
35 |
36 | void *ddsMalloc(size_t size);
37 | void ddsFree(void *memory);
38 |
39 | int ddsGetHeight(const unsigned char *buffer);
40 | int ddsGetWidth(const unsigned char *buffer);
41 | int ddsGetMipmap(const unsigned char *buffer);
42 | int *ddsRead(const unsigned char *buffer, const DDS_ORDER *order, int mipmapLevel);
43 |
44 | #ifdef __cplusplus
45 | }
46 | #endif
47 |
48 | #endif /* __DDS_READER_H__ */
49 |
--------------------------------------------------------------------------------
/src/java/DDSReader.java:
--------------------------------------------------------------------------------
1 | /**
2 | * DDSReader.java
3 | *
4 | * Copyright (c) 2015 Kenji Sasaki
5 | * Released under the MIT license.
6 | * https://github.com/npedotnet/DDSReader/blob/master/LICENSE
7 | *
8 | * English document
9 | * https://github.com/npedotnet/DDSReader/blob/master/README.md
10 | *
11 | * Japanese document
12 | * http://3dtech.jp/wiki/index.php?DDSReader
13 | *
14 | */
15 |
16 | package net.npe.dds;
17 |
18 | public final class DDSReader {
19 |
20 | public static final Order ARGB = new Order(16, 8, 0, 24);
21 | public static final Order ABGR = new Order(0, 8, 16, 24);
22 |
23 | public static int getHeight(byte [] buffer) {
24 | return (buffer[12] & 0xFF) | (buffer[13] & 0xFF) << 8 | (buffer[14] & 0xFF) << 16 | (buffer[15] & 0xFF) << 24;
25 | }
26 |
27 | public static int getWidth(byte [] buffer) {
28 | return (buffer[16] & 0xFF) | (buffer[17] & 0xFF) << 8 | (buffer[18] & 0xFF) << 16 | (buffer[19] & 0xFF) << 24;
29 | }
30 |
31 | public static int getMipmap(byte [] buffer) {
32 | return (buffer[28] & 0xFF) | (buffer[29] & 0xFF) << 8 | (buffer[30] & 0xFF) << 16 | (buffer[31] & 0xFF) << 24;
33 | }
34 |
35 | public static int getPixelFormatFlags(byte [] buffer) {
36 | return (buffer[80] & 0xFF) | (buffer[81] & 0xFF) << 8 | (buffer[82] & 0xFF) << 16 | (buffer[83] & 0xFF) << 24;
37 | }
38 |
39 | public static int getFourCC(byte [] buffer) {
40 | return (buffer[84] & 0xFF) << 24 | (buffer[85] & 0xFF) << 16 | (buffer[86] & 0xFF) << 8 | (buffer[87] & 0xFF);
41 | }
42 |
43 | public static int getBitCount(byte [] buffer) {
44 | return (buffer[88] & 0xFF) | (buffer[89] & 0xFF) << 8 | (buffer[90] & 0xFF) << 16 | (buffer[91] & 0xFF) << 24;
45 | }
46 |
47 | public static int getRedMask(byte [] buffer) {
48 | return (buffer[92] & 0xFF) | (buffer[93] & 0xFF) << 8 | (buffer[94] & 0xFF) << 16 | (buffer[95] & 0xFF) << 24;
49 | }
50 |
51 | public static int getGreenMask(byte [] buffer) {
52 | return (buffer[96] & 0xFF) | (buffer[97] & 0xFF) << 8 | (buffer[98] & 0xFF) << 16 | (buffer[99] & 0xFF) << 24;
53 | }
54 |
55 | public static int getBlueMask(byte [] buffer) {
56 | return (buffer[100] & 0xFF) | (buffer[101] & 0xFF) << 8 | (buffer[102] & 0xFF) << 16 | (buffer[103] & 0xFF) << 24;
57 | }
58 |
59 | public static int getAlphaMask(byte [] buffer) {
60 | return (buffer[104] & 0xFF) | (buffer[105] & 0xFF) << 8 | (buffer[106] & 0xFF) << 16 | (buffer[107] & 0xFF) << 24;
61 | }
62 |
63 | public static int [] read(byte [] buffer, Order order, int mipmapLevel) {
64 |
65 | // header
66 | int width = getWidth(buffer);
67 | int height = getHeight(buffer);
68 | int mipmap = getMipmap(buffer);
69 |
70 | // type
71 | int type = getType(buffer);
72 | if(type == 0) return null;
73 |
74 | // offset
75 | int offset = 128; // header size
76 | if(mipmapLevel > 0 && mipmapLevel < mipmap) {
77 | for(int i=0; i= height) break;
216 | int t0 = (buffer[index] & 0x03);
217 | int t1 = (buffer[index] & 0x0C) >> 2;
218 | int t2 = (buffer[index] & 0x30) >> 4;
219 | int t3 = (buffer[index++] & 0xC0) >> 6;
220 | pixels[4*width*i+4*j+width*k+0] = getDXTColor(c0, c1, 0xFF, t0, order);
221 | if(4*j+1 >= width) continue;
222 | pixels[4*width*i+4*j+width*k+1] = getDXTColor(c0, c1, 0xFF, t1, order);
223 | if(4*j+2 >= width) continue;
224 | pixels[4*width*i+4*j+width*k+2] = getDXTColor(c0, c1, 0xFF, t2, order);
225 | if(4*j+3 >= width) continue;
226 | pixels[4*width*i+4*j+width*k+3] = getDXTColor(c0, c1, 0xFF, t3, order);
227 | }
228 | }
229 | }
230 | return pixels;
231 | }
232 |
233 | private static int [] decodeDXT2(int width, int height, int offset, byte [] buffer, Order order) {
234 | return decodeDXT3(width, height, offset, buffer, order);
235 | }
236 |
237 | private static int [] decodeDXT3(int width, int height, int offset, byte [] buffer, Order order) {
238 | int index = offset;
239 | int w = (width+3)/4;
240 | int h = (height+3)/4;
241 | int [] pixels = new int[width*height];
242 | int [] alphaTable = new int[16];
243 | for(int i=0; i>4);
251 | alphaTable[4*k+1] = 17 * (a0 & 0x0F);
252 | alphaTable[4*k+2] = 17 * ((a1 & 0xF0)>>4);
253 | alphaTable[4*k+3] = 17 * (a1 & 0x0F);
254 | }
255 | int c0 = (buffer[index] & 0xFF) | (buffer[index+1] & 0xFF) << 8; index += 2;
256 | int c1 = (buffer[index] & 0xFF) | (buffer[index+1] & 0xFF) << 8; index += 2;
257 | for(int k=0; k<4; k++) {
258 | if(4*i+k >= height) break;
259 | int t0 = (buffer[index] & 0x03);
260 | int t1 = (buffer[index] & 0x0C) >> 2;
261 | int t2 = (buffer[index] & 0x30) >> 4;
262 | int t3 = (buffer[index++] & 0xC0) >> 6;
263 | pixels[4*width*i+4*j+width*k+0] = getDXTColor(c0, c1, alphaTable[4*k+0], t0, order);
264 | if(4*j+1 >= width) continue;
265 | pixels[4*width*i+4*j+width*k+1] = getDXTColor(c0, c1, alphaTable[4*k+1], t1, order);
266 | if(4*j+2 >= width) continue;
267 | pixels[4*width*i+4*j+width*k+2] = getDXTColor(c0, c1, alphaTable[4*k+2], t2, order);
268 | if(4*j+3 >= width) continue;
269 | pixels[4*width*i+4*j+width*k+3] = getDXTColor(c0, c1, alphaTable[4*k+3], t3, order);
270 | }
271 | }
272 | }
273 | return pixels;
274 | }
275 |
276 | private static int [] decodeDXT4(int width, int height, int offset, byte [] buffer, Order order) {
277 | return decodeDXT5(width, height, offset, buffer, order);
278 | }
279 |
280 | private static int [] decodeDXT5(int width, int height, int offset, byte [] buffer, Order order) {
281 | int index = offset;
282 | int w = (width+3)/4;
283 | int h = (height+3)/4;
284 | int [] pixels = new int[width*height];
285 | int [] alphaTable = new int[16];
286 | for(int i=0; i> 3) & 0x07;
295 | alphaTable[2] = (b0 >> 6) & 0x07;
296 | alphaTable[3] = (b0 >> 9) & 0x07;
297 | alphaTable[4] = (b0 >> 12) & 0x07;
298 | alphaTable[5] = (b0 >> 15) & 0x07;
299 | alphaTable[6] = (b0 >> 18) & 0x07;
300 | alphaTable[7] = (b0 >> 21) & 0x07;
301 | alphaTable[8] = b1 & 0x07;
302 | alphaTable[9] = (b1 >> 3) & 0x07;
303 | alphaTable[10] = (b1 >> 6) & 0x07;
304 | alphaTable[11] = (b1 >> 9) & 0x07;
305 | alphaTable[12] = (b1 >> 12) & 0x07;
306 | alphaTable[13] = (b1 >> 15) & 0x07;
307 | alphaTable[14] = (b1 >> 18) & 0x07;
308 | alphaTable[15] = (b1 >> 21) & 0x07;
309 | int c0 = (buffer[index] & 0xFF) | (buffer[index+1] & 0xFF) << 8; index += 2;
310 | int c1 = (buffer[index] & 0xFF) | (buffer[index+1] & 0xFF) << 8; index += 2;
311 | for(int k=0; k<4; k++) {
312 | if(4*i+k >= height) break;
313 | int t0 = (buffer[index] & 0x03);
314 | int t1 = (buffer[index] & 0x0C) >> 2;
315 | int t2 = (buffer[index] & 0x30) >> 4;
316 | int t3 = (buffer[index++] & 0xC0) >> 6;
317 | pixels[4*width*i+4*j+width*k+0] = getDXTColor(c0, c1, getDXT5Alpha(a0, a1, alphaTable[4*k+0]), t0, order);
318 | if(4*j+1 >= width) continue;
319 | pixels[4*width*i+4*j+width*k+1] = getDXTColor(c0, c1, getDXT5Alpha(a0, a1, alphaTable[4*k+1]), t1, order);
320 | if(4*j+2 >= width) continue;
321 | pixels[4*width*i+4*j+width*k+2] = getDXTColor(c0, c1, getDXT5Alpha(a0, a1, alphaTable[4*k+2]), t2, order);
322 | if(4*j+3 >= width) continue;
323 | pixels[4*width*i+4*j+width*k+3] = getDXTColor(c0, c1, getDXT5Alpha(a0, a1, alphaTable[4*k+3]), t3, order);
324 | }
325 | }
326 | }
327 | return pixels;
328 | }
329 |
330 | private static int [] readA1R5G5B5(int width, int height, int offset, byte [] buffer, Order order) {
331 | int index = offset;
332 | int [] pixels = new int[width*height];
333 | for(int i=0; i> 10];
336 | int g = BIT5[(rgba & A1R5G5B5_MASKS[1]) >> 5];
337 | int b = BIT5[(rgba & A1R5G5B5_MASKS[2])];
338 | int a = 255 * ((rgba & A1R5G5B5_MASKS[3]) >> 15);
339 | pixels[i] = (a<> 10];
350 | int g = BIT5[(rgba & X1R5G5B5_MASKS[1]) >> 5];
351 | int b = BIT5[(rgba & X1R5G5B5_MASKS[2])];
352 | int a = 255;
353 | pixels[i] = (a<> 8);
364 | int g = 17 * ((rgba & A4R4G4B4_MASKS[1]) >> 4);
365 | int b = 17 * ((rgba & A4R4G4B4_MASKS[2]));
366 | int a = 17 * ((rgba & A4R4G4B4_MASKS[3]) >> 12);
367 | pixels[i] = (a<> 8);
378 | int g = 17 * ((rgba & A4R4G4B4_MASKS[1]) >> 4);
379 | int b = 17 * ((rgba & A4R4G4B4_MASKS[2]));
380 | int a = 255;
381 | pixels[i] = (a<> 11)];
392 | int g = BIT6[((rgba & R5G6B5_MASKS[1]) >> 5)];
393 | int b = BIT5[((rgba & R5G6B5_MASKS[2]))];
394 | int a = 255;
395 | pixels[i] = (a< c1) ? getDXTColor2_1(c0, c1, a, order) : getDXTColor1_1(c0, c1, a, order);
470 | case 3: return (c0 > c1) ? getDXTColor2_1(c1, c0, a, order) : 0;
471 | }
472 | return 0;
473 | }
474 |
475 | private static int getDXTColor2_1(int c0, int c1, int a, Order order) {
476 | // 2*c0/3 + c1/3
477 | int r = (2*BIT5[(c0 & 0xFC00) >> 11] + BIT5[(c1 & 0xFC00) >> 11]) / 3;
478 | int g = (2*BIT6[(c0 & 0x07E0) >> 5] + BIT6[(c1 & 0x07E0) >> 5]) / 3;
479 | int b = (2*BIT5[c0 & 0x001F] + BIT5[c1 & 0x001F]) / 3;
480 | return (a<> 11] + BIT5[(c1 & 0xFC00) >> 11]) / 2;
486 | int g = (BIT6[(c0 & 0x07E0) >> 5] + BIT6[(c1 & 0x07E0) >> 5]) / 2;
487 | int b = (BIT5[c0 & 0x001F] + BIT5[c1 & 0x001F]) / 2;
488 | return (a<> 11];
493 | int g = BIT6[(c & 0x07E0) >> 5];
494 | int b = BIT5[(c & 0x001F)];
495 | return (a< a1) switch(t) {
500 | case 0: return a0;
501 | case 1: return a1;
502 | case 2: return (6*a0+a1)/7;
503 | case 3: return (5*a0+2*a1)/7;
504 | case 4: return (4*a0+3*a1)/7;
505 | case 5: return (3*a0+4*a1)/7;
506 | case 6: return (2*a0+5*a1)/7;
507 | case 7: return (a0+6*a1)/7;
508 | }
509 | else switch(t) {
510 | case 0: return a0;
511 | case 1: return a1;
512 | case 2: return (4*a0+a1)/5;
513 | case 3: return (3*a0+2*a1)/5;
514 | case 4: return (2*a0+3*a1)/5;
515 | case 5: return (a0+4*a1)/5;
516 | case 6: return 0;
517 | case 7: return 255;
518 | }
519 | return 0;
520 | }
521 |
522 | // Image Type
523 | private static final int DXT1 = (0x44585431);
524 | private static final int DXT2 = (0x44585432);
525 | private static final int DXT3 = (0x44585433);
526 | private static final int DXT4 = (0x44585434);
527 | private static final int DXT5 = (0x44585435);
528 | private static final int A1R5G5B5 = ((1<<16)|2);
529 | private static final int X1R5G5B5 = ((2<<16)|2);
530 | private static final int A4R4G4B4 = ((3<<16)|2);
531 | private static final int X4R4G4B4 = ((4<<16)|2);
532 | private static final int R5G6B5 = ((5<<16)|2);
533 | private static final int R8G8B8 = ((1<<16)|3);
534 | private static final int A8B8G8R8 = ((1<<16)|4);
535 | private static final int X8B8G8R8 = ((2<<16)|4);
536 | private static final int A8R8G8B8 = ((3<<16)|4);
537 | private static final int X8R8G8B8 = ((4<<16)|4);
538 |
539 | // RGBA Masks
540 | private static final int [] A1R5G5B5_MASKS = {0x7C00, 0x03E0, 0x001F, 0x8000};
541 | private static final int [] X1R5G5B5_MASKS = {0x7C00, 0x03E0, 0x001F, 0x0000};
542 | private static final int [] A4R4G4B4_MASKS = {0x0F00, 0x00F0, 0x000F, 0xF000};
543 | private static final int [] X4R4G4B4_MASKS = {0x0F00, 0x00F0, 0x000F, 0x0000};
544 | private static final int [] R5G6B5_MASKS = {0xF800, 0x07E0, 0x001F, 0x0000};
545 | private static final int [] R8G8B8_MASKS = {0xFF0000, 0x00FF00, 0x0000FF, 0x000000};
546 | private static final int [] A8B8G8R8_MASKS = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
547 | private static final int [] X8B8G8R8_MASKS = {0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000};
548 | private static final int [] A8R8G8B8_MASKS = {0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000};
549 | private static final int [] X8R8G8B8_MASKS = {0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000};
550 |
551 | // BIT4 = 17 * index;
552 | private static final int [] BIT5 = {0,8,16,25,33,41,49,58,66,74,82,90,99,107,115,123,132,140,148,156,165,173,181,189,197,206,214,222,230,239,247,255};
553 | private static final int [] BIT6 = {0,4,8,12,16,20,24,28,32,36,40,45,49,53,57,61,65,69,73,77,81,85,89,93,97,101,105,109,113,117,121,125,130,134,138,142,146,150,154,158,162,166,170,174,178,182,186,190,194,198,202,206,210,215,219,223,227,231,235,239,243,247,251,255};
554 |
555 | private DDSReader() {}
556 |
557 | private static final class Order {
558 | Order(int redShift, int greenShift, int blueShift, int alphaShift) {
559 | this.redShift = redShift;
560 | this.greenShift = greenShift;
561 | this.blueShift = blueShift;
562 | this.alphaShift = alphaShift;
563 | }
564 | public int redShift;
565 | public int greenShift;
566 | public int blueShift;
567 | public int alphaShift;
568 | }
569 |
570 | }
571 |
--------------------------------------------------------------------------------