├── 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 | ![alt text](http://3dtech.jp/wiki/index.php?plugin=attach&refer=DDSReader&openfile=DDSReader.png "DDSReader") 5 | 6 | Online DDS Canvas Demo page is http://npe-net.appspot.com/npesdk/gwt/ddsimagedemo/index.html 7 | 8 | ![alt text](http://3dtech.jp/wiki/index.php?plugin=attach&refer=DDSReader&openfile=ddsimagedemo.png "DDSWebCanvas") 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 | --------------------------------------------------------------------------------