summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--native/fb/mip_cube.c52
-rw-r--r--native/lib/dds.c122
-rw-r--r--native/lib/dds.h7
-rw-r--r--native/resources/attribution.txt4
-rw-r--r--native/resources/wall1_a8.ddsbin0 -> 87509 bytes
-rw-r--r--native/resources/wall1_l8.ddsbin0 -> 87509 bytes
-rwxr-xr-xtools/genmipmaps_l8.py109
7 files changed, 228 insertions, 66 deletions
diff --git a/native/fb/mip_cube.c b/native/fb/mip_cube.c
index 42f0f95..b1e6adb 100644
--- a/native/fb/mip_cube.c
+++ b/native/fb/mip_cube.c
@@ -149,7 +149,7 @@ float vNormals[] = {
#define COMPONENTS_PER_VERTEX (3)
#define NUM_VERTICES (6*4)
-static const char mip_cube_vert[] =
+static const char mip_cube_vert[] =
"VERT\n"
"DCL IN[0]\n"
"DCL IN[1]\n"
@@ -187,7 +187,7 @@ static const char mip_cube_vert[] =
" 24: MOV OUT[2], TEMP[1]\n"
" 25: END\n";
-static const char mip_cube_frag[] =
+static const char mip_cube_frag[] =
"FRAG\n"
"PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n"
"DCL IN[0], GENERIC[0], PERSPECTIVE\n"
@@ -226,16 +226,19 @@ int main(int argc, char **argv)
case FMT_DXT3: tex_format = PIPE_FORMAT_DXT3_RGBA; break;
case FMT_DXT5: tex_format = PIPE_FORMAT_DXT5_RGBA; break;
case FMT_ETC1: tex_format = PIPE_FORMAT_ETC1_RGB8; break;
+ case FMT_A8: tex_format = PIPE_FORMAT_A8_UNORM; break;
+ case FMT_L8: tex_format = PIPE_FORMAT_L8_UNORM; break;
+ case FMT_A8L8: tex_format = PIPE_FORMAT_L8A8_UNORM; break;
default:
printf("Unknown texture format\n");
exit(1);
}
-
- struct pipe_resource *tex_resource = fbdemo_create_2d(fbs->screen, PIPE_BIND_SAMPLER_VIEW, tex_format, tex_base_width, tex_base_height,
+
+ struct pipe_resource *tex_resource = fbdemo_create_2d(fbs->screen, PIPE_BIND_SAMPLER_VIEW, tex_format, tex_base_width, tex_base_height,
dds->num_mipmaps - 1);
-
+
printf("Loading compressed texture (format %i, %ix%i)\n", dds->fmt, tex_base_width, tex_base_height);
-
+
for(int ix=0; ix<dds->num_mipmaps; ++ix)
{
printf("%08x: Uploading mipmap %i (%ix%i)\n", dds->slices[0][ix].offset, ix, dds->slices[0][ix].width, dds->slices[0][ix].height);
@@ -271,7 +274,23 @@ int main(int argc, char **argv)
pipe_buffer_unmap(pipe, vtx_transfer);
/* compile gallium3d states */
- void *blend = pipe->create_blend_state(pipe, &(struct pipe_blend_state) {
+ void *blend = NULL;
+ if(tex_format == PIPE_FORMAT_A8_UNORM || tex_format == PIPE_FORMAT_L8A8_UNORM) /* if alpha texture, enable blending */
+ {
+ blend = pipe->create_blend_state(pipe, &(struct pipe_blend_state) {
+ .rt[0] = {
+ .blend_enable = 1,
+ .rgb_func = PIPE_BLEND_ADD,
+ .rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA,
+ .rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA,
+ .alpha_func = PIPE_BLEND_ADD,
+ .alpha_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA,
+ .alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA,
+ .colormask = 0xf
+ }
+ });
+ } else {
+ blend = pipe->create_blend_state(pipe, &(struct pipe_blend_state) {
.rt[0] = {
.blend_enable = 0,
.rgb_func = PIPE_BLEND_ADD,
@@ -283,6 +302,7 @@ int main(int argc, char **argv)
.colormask = 0xf
}
});
+ }
void *sampler = pipe->create_sampler_state(pipe, &(struct pipe_sampler_state) {
.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE,
@@ -356,13 +376,13 @@ int main(int argc, char **argv)
.src_offset = 0,
.instance_divisor = 0,
.vertex_buffer_index = 0,
- .src_format = PIPE_FORMAT_R32G32B32_FLOAT
+ .src_format = PIPE_FORMAT_R32G32B32_FLOAT
},
{ /* normals */
.src_offset = 0xc,
.instance_divisor = 0,
.vertex_buffer_index = 0,
- .src_format = PIPE_FORMAT_R32G32B32_FLOAT
+ .src_format = PIPE_FORMAT_R32G32B32_FLOAT
},
{ /* texture coord */
.src_offset = 0x18,
@@ -371,7 +391,7 @@ int main(int argc, char **argv)
.src_format = PIPE_FORMAT_R32G32_FLOAT
}
};
- void *vertex_elements = pipe->create_vertex_elements_state(pipe,
+ void *vertex_elements = pipe->create_vertex_elements_state(pipe,
sizeof(pipe_vertex_elements)/sizeof(pipe_vertex_elements[0]), pipe_vertex_elements);
struct pipe_sampler_view *sampler_view = pipe->create_sampler_view(pipe, tex_resource, &(struct pipe_sampler_view){
.format = tex_format,
@@ -392,7 +412,7 @@ int main(int argc, char **argv)
.format = z_resource->format,
.u.tex.level = 0
});
-
+
/* bind */
pipe->bind_blend_state(pipe, blend);
pipe->bind_fragment_sampler_states(pipe, 1, &sampler);
@@ -438,7 +458,7 @@ int main(int argc, char **argv)
.buffer = 0,
.user_buffer = 0
});*/ /* non-indexed rendering */
-
+
void *vtx_shader = graw_parse_vertex_shader(pipe, mip_cube_vert);
void *frag_shader = graw_parse_fragment_shader(pipe, mip_cube_frag);
pipe->bind_vs_state(pipe, vtx_shader);
@@ -449,9 +469,9 @@ int main(int argc, char **argv)
float vs_const[11*4];
if(frame%50 == 0)
printf("*** FRAME %i ****\n", frame);
- /* Compute transform matrices in the same way as cube egl demo */
+ /* Compute transform matrices in the same way as cube egl demo */
ESMatrix modelview, projection, modelviewprojection;
- ESMatrix inverse, normal;
+ ESMatrix inverse, normal;
esMatrixLoadIdentity(&modelview);
esTranslate(&modelview, 0.0f, 0.0f, -8.0f);
esRotate(&modelview, 45.0f, 1.0f, 0.0f, 0.0f);
@@ -464,12 +484,12 @@ int main(int argc, char **argv)
esMatrixMultiply(&modelviewprojection, &modelview, &projection);
esMatrixInverse3x3(&inverse, &modelview);
esMatrixTranspose(&normal, &inverse);
-
+
/* Clear render target */
pipe->clear(pipe, PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL, &(const union pipe_color_union) {
.f = {0.2, 0.2, 0.2, 1.0}
}, 1.0, 0xff);
-
+
memcpy(&vs_const[0*4], &normal.m[0][0], 3*4); /* CONST[0] */
memcpy(&vs_const[1*4], &normal.m[1][0], 3*4); /* CONST[1] */
memcpy(&vs_const[2*4], &normal.m[2][0], 3*4); /* CONST[2] */
diff --git a/native/lib/dds.c b/native/lib/dds.c
index 0afba5e..5ae4c26 100644
--- a/native/lib/dds.c
+++ b/native/lib/dds.c
@@ -42,35 +42,37 @@
#define DDS_MAGIC 0x20534444
// DDS_header.dwFlags
-#define DDSD_CAPS 0x00000001
-#define DDSD_HEIGHT 0x00000002
-#define DDSD_WIDTH 0x00000004
-#define DDSD_PITCH 0x00000008
-#define DDSD_PIXELFORMAT 0x00001000
-#define DDSD_MIPMAPCOUNT 0x00020000
-#define DDSD_LINEARSIZE 0x00080000
-#define DDSD_DEPTH 0x00800000
+#define DDSD_CAPS 0x00000001
+#define DDSD_HEIGHT 0x00000002
+#define DDSD_WIDTH 0x00000004
+#define DDSD_PITCH 0x00000008
+#define DDSD_PIXELFORMAT 0x00001000
+#define DDSD_MIPMAPCOUNT 0x00020000
+#define DDSD_LINEARSIZE 0x00080000
+#define DDSD_DEPTH 0x00800000
// DDS_header.sPixelFormat.dwFlags
-#define DDPF_ALPHAPIXELS 0x00000001
-#define DDPF_FOURCC 0x00000004
-#define DDPF_INDEXED 0x00000020
-#define DDPF_RGB 0x00000040
+#define DDPF_ALPHAPIXELS 0x00000001
+#define DDPF_ALPHA 0x00000002
+#define DDPF_FOURCC 0x00000004
+#define DDPF_INDEXED 0x00000020
+#define DDPF_RGB 0x00000040
+#define DDPF_LUMINANCE 0x00020000
// DDS_header.sCaps.dwCaps1
-#define DDSCAPS_COMPLEX 0x00000008
-#define DDSCAPS_TEXTURE 0x00001000
-#define DDSCAPS_MIPMAP 0x00400000
+#define DDSCAPS_COMPLEX 0x00000008
+#define DDSCAPS_TEXTURE 0x00001000
+#define DDSCAPS_MIPMAP 0x00400000
// DDS_header.sCaps.dwCaps2
-#define DDSCAPS2_CUBEMAP 0x00000200
-#define DDSCAPS2_CUBEMAP_POSITIVEX 0x00000400
-#define DDSCAPS2_CUBEMAP_NEGATIVEX 0x00000800
-#define DDSCAPS2_CUBEMAP_POSITIVEY 0x00001000
-#define DDSCAPS2_CUBEMAP_NEGATIVEY 0x00002000
-#define DDSCAPS2_CUBEMAP_POSITIVEZ 0x00004000
-#define DDSCAPS2_CUBEMAP_NEGATIVEZ 0x00008000
-#define DDSCAPS2_VOLUME 0x00200000
+#define DDSCAPS2_CUBEMAP 0x00000200
+#define DDSCAPS2_CUBEMAP_POSITIVEX 0x00000400
+#define DDSCAPS2_CUBEMAP_NEGATIVEX 0x00000800
+#define DDSCAPS2_CUBEMAP_POSITIVEY 0x00001000
+#define DDSCAPS2_CUBEMAP_NEGATIVEY 0x00002000
+#define DDSCAPS2_CUBEMAP_POSITIVEZ 0x00004000
+#define DDSCAPS2_CUBEMAP_NEGATIVEZ 0x00008000
+#define DDSCAPS2_VOLUME 0x00200000
#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
(uint32_t)( \
@@ -79,11 +81,11 @@
(((uint32_t)(uint8_t)(ch1) << 8) & 0x0000FF00) | \
((uint32_t)(uint8_t)(ch0) & 0x000000FF) )
-#define D3DFMT_DXT1 MAKEFOURCC('D','X','T','1') // DXT1 compression texture format
-#define D3DFMT_DXT2 MAKEFOURCC('D','X','T','2') // DXT2 compression texture format
-#define D3DFMT_DXT3 MAKEFOURCC('D','X','T','3') // DXT3 compression texture format
-#define D3DFMT_DXT4 MAKEFOURCC('D','X','T','4') // DXT4 compression texture format
-#define D3DFMT_DXT5 MAKEFOURCC('D','X','T','5') // DXT5 compression texture format
+#define D3DFMT_DXT1 MAKEFOURCC('D','X','T','1') // DXT1 compression texture format
+#define D3DFMT_DXT2 MAKEFOURCC('D','X','T','2') // DXT2 compression texture format
+#define D3DFMT_DXT3 MAKEFOURCC('D','X','T','3') // DXT3 compression texture format
+#define D3DFMT_DXT4 MAKEFOURCC('D','X','T','4') // DXT4 compression texture format
+#define D3DFMT_DXT5 MAKEFOURCC('D','X','T','5') // DXT5 compression texture format
#define D3DFMT_ETC1 MAKEFOURCC('E','T','C','1') // Custom (Ericcson Texture Compression)
struct _DDS_pixelformat {
@@ -128,6 +130,7 @@ typedef struct _DdsLoadInfo {
bool compressed;
unsigned int divSize;
unsigned int blockBytes;
+ uint32_t flags;
int bitcount;
uint32_t rmask;
uint32_t gmask;
@@ -136,16 +139,19 @@ typedef struct _DdsLoadInfo {
} DdsLoadInfo;
static DdsLoadInfo loadInfo[] = {
- [FMT_A8R8G8B8] = {false, 1, 4, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000},
- [FMT_X8R8G8B8] = {false, 1, 4, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000},
- [FMT_R8G8B8] = {false, 1, 3, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000},
- [FMT_A1R5G5B5] = {false, 1, 2, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000},
- [FMT_X1R5G5B5] = {false, 1, 2, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00000000},
- [FMT_R5G6B5] = {false, 1, 2, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000},
- [FMT_DXT1] = {true, 4, 8, 0, D3DFMT_DXT1},
- [FMT_DXT3] = {true, 4, 16, 0, D3DFMT_DXT3},
- [FMT_DXT5] = {true, 4, 16, 0, D3DFMT_DXT5},
- [FMT_ETC1] = {true, 4, 8, 0, D3DFMT_ETC1}
+ [FMT_A8R8G8B8] = {false, 1, 4, DDPF_RGB, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000},
+ [FMT_X8R8G8B8] = {false, 1, 4, DDPF_RGB, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000},
+ [FMT_R8G8B8] = {false, 1, 3, DDPF_RGB, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000},
+ [FMT_A1R5G5B5] = {false, 1, 2, DDPF_RGB, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000},
+ [FMT_X1R5G5B5] = {false, 1, 2, DDPF_RGB, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00000000},
+ [FMT_R5G6B5] = {false, 1, 2, DDPF_RGB, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000},
+ [FMT_A8] = {false, 1, 1, DDPF_ALPHA, 8, 0x00000000, 0, 0, 0x000000ff},
+ [FMT_L8] = {false, 1, 1, DDPF_LUMINANCE, 8, 0x000000ff, 0, 0, 0x00000000},
+ [FMT_A8L8] = {false, 1, 2, DDPF_LUMINANCE, 16, 0x000000ff, 0, 0, 0x0000ff00},
+ [FMT_DXT1] = {true, 4, 8, DDPF_FOURCC, 0, D3DFMT_DXT1},
+ [FMT_DXT3] = {true, 4, 16, DDPF_FOURCC, 0, D3DFMT_DXT3},
+ [FMT_DXT5] = {true, 4, 16, DDPF_FOURCC, 0, D3DFMT_DXT5},
+ [FMT_ETC1] = {true, 4, 8, DDPF_FOURCC, 0, D3DFMT_ETC1}
};
#define NUM_FORMATS (sizeof(loadInfo) / sizeof(DdsLoadInfo))
@@ -160,20 +166,40 @@ static int find_fmt(struct _DDS_pixelformat *pf)
DdsLoadInfo *li = &loadInfo[fmt];
if(pf->dwFlags & DDPF_FOURCC)
{
- if(li->bitcount == 0 && li->rmask == pf->dwFourCC)
+ if(li->flags == DDPF_FOURCC && li->bitcount == 0 && li->rmask == pf->dwFourCC)
{
return fmt;
}
}
else if(pf->dwFlags & DDPF_RGB)
{
- if((li->bitcount == pf->dwRGBBitCount) &&
- (li->rmask == pf->dwRBitMask) && (li->gmask == pf->dwGBitMask) &&
+ if((li->flags == DDPF_RGB) &&
+ (li->bitcount == pf->dwRGBBitCount) &&
+ (li->rmask == pf->dwRBitMask) && (li->gmask == pf->dwGBitMask) &&
(li->bmask == pf->dwBBitMask) && (li->amask == ((pf->dwFlags & DDPF_ALPHAPIXELS)?pf->dwAlphaBitMask:0)))
{
return fmt;
}
}
+ else if(pf->dwFlags & DDPF_LUMINANCE)
+ {
+ bool formatHasAlpha = pf->dwAlphaBitMask != 0;
+ bool ddsHasAlpha = (pf->dwFlags & DDPF_ALPHAPIXELS) != 0;
+ if(li->flags == DDPF_LUMINANCE &&
+ li->bitcount == pf->dwRGBBitCount &&
+ formatHasAlpha == ddsHasAlpha)
+ {
+ return fmt;
+ }
+ }
+ else if(pf->dwFlags & DDPF_ALPHA)
+ {
+ if(li->flags == DDPF_ALPHA &&
+ li->bitcount == pf->dwRGBBitCount)
+ {
+ return fmt;
+ }
+ }
}
return -1;
}
@@ -209,7 +235,7 @@ bool dds_load_file(FILE *f, dds_texture **out)
}
DdsLoadInfo *li = &loadInfo[fmt];
dds_texture *rv = (dds_texture*)malloc(sizeof(dds_texture));
- if(!rv)
+ if(!rv)
goto failure;
//fixme: do cube maps later
@@ -232,7 +258,7 @@ bool dds_load_file(FILE *f, dds_texture **out)
}
if((hdr.dwFlags & DDSD_PITCH) && (hdr.dwPitchOrLinearSize != x*li->blockBytes))
goto failure;
-
+
rv->fmt = fmt;
rv->num_slices = 1;
rv->num_mipmaps = mipMapCount;
@@ -246,7 +272,7 @@ bool dds_load_file(FILE *f, dds_texture **out)
/* compute offsets */
size_t offset = 0;
- for(unsigned int ix = 0; ix < mipMapCount; ++ix)
+ for(unsigned int ix = 0; ix < mipMapCount; ++ix)
{
dds_mipmap *mip = &rv->slices[0][ix];
mip->width = x;
@@ -255,7 +281,7 @@ bool dds_load_file(FILE *f, dds_texture **out)
mip->offset = offset;
mip->size = size;
#ifdef DEBUG
- printf("%08x Loading mipmap %i: %ix%i (%i) stride=%i\n",
+ printf("%08x Loading mipmap %i: %ix%i (%i) stride=%i\n",
(int)mip->offset, ix, (int)mip->width, (int)mip->height, (int)mip->size,
(int)mip->stride);
#endif
@@ -266,10 +292,10 @@ bool dds_load_file(FILE *f, dds_texture **out)
}
rv->data = malloc(offset);
rv->size = offset;
- if(!rv->data)
+ if(!rv->data)
goto failure;
fread(rv->data, rv->size, 1, f);
- for(unsigned int ix = 0; ix < mipMapCount; ++ix)
+ for(unsigned int ix = 0; ix < mipMapCount; ++ix)
{
rv->slices[0][ix].data = (void*)((size_t)rv->data + rv->slices[0][ix].offset);
}
@@ -283,7 +309,7 @@ failure:
bool dds_load(const char *filename, dds_texture **out)
{
FILE *f = fopen(filename, "rb");
- if(f == NULL)
+ if(f == NULL)
{
#ifdef DEBUG
printf("Cannot open texture file\n");
diff --git a/native/lib/dds.h b/native/lib/dds.h
index 4db48fa..851ec60 100644
--- a/native/lib/dds.h
+++ b/native/lib/dds.h
@@ -38,6 +38,9 @@
#define FMT_DXT3 7
#define FMT_DXT5 8
#define FMT_ETC1 9
+#define FMT_A8 10
+#define FMT_L8 11
+#define FMT_A8L8 12
typedef struct _dds_mipmap
{
@@ -46,7 +49,7 @@ typedef struct _dds_mipmap
size_t offset;
} dds_mipmap;
-typedef struct _dds_texture
+typedef struct _dds_texture
{
int fmt;
unsigned int div_size;
@@ -62,5 +65,5 @@ bool dds_load(const char *filename, dds_texture **out);
bool dds_load_file(FILE *f, dds_texture **out);
void dds_free(dds_texture *tex);
-#endif
+#endif
diff --git a/native/resources/attribution.txt b/native/resources/attribution.txt
new file mode 100644
index 0000000..9efcc92
--- /dev/null
+++ b/native/resources/attribution.txt
@@ -0,0 +1,4 @@
+wall1_l8.dds / wall1_a8.dds
+CC-BY: brightretro
+http://opengameart.org/node/17576
+
diff --git a/native/resources/wall1_a8.dds b/native/resources/wall1_a8.dds
new file mode 100644
index 0000000..8eaf1f7
--- /dev/null
+++ b/native/resources/wall1_a8.dds
Binary files differ
diff --git a/native/resources/wall1_l8.dds b/native/resources/wall1_l8.dds
new file mode 100644
index 0000000..a00aa2a
--- /dev/null
+++ b/native/resources/wall1_l8.dds
Binary files differ
diff --git a/tools/genmipmaps_l8.py b/tools/genmipmaps_l8.py
new file mode 100755
index 0000000..d810d05
--- /dev/null
+++ b/tools/genmipmaps_l8.py
@@ -0,0 +1,109 @@
+#!/usr/bin/python
+'''
+Generate 'ETC1' texture with mipmaps in dds format from an image file.
+'''
+# Copyright (c) 2012-2013 Wladimir J. van der Laan
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sub license,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the
+# next paragraph) shall be included in all copies or substantial portions
+# of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+from __future__ import print_function, division, unicode_literals
+import struct, sys, PIL, os
+from PIL import Image
+import argparse, tempfile
+from subprocess import call
+
+DDS_MAGIC = 0x20534444
+DDS_UINT32 = b'<I'
+FOURCC_ETC1 = struct.unpack(DDS_UINT32, b'ETC1')[0] # custom FOURCC
+ETC1TOOL = 'etc1tool' # Android ETC1 tool, needs to be in PATH
+
+def main():
+ parser = argparse.ArgumentParser(description='Generate mipmaps from image and compress to ETC1 dds.')
+ parser.add_argument('input', metavar='INFILE', type=str,
+ help='Input file (usually .png or .jpg)')
+ parser.add_argument('output', metavar='OUTFILE', type=str,
+ help='Output file (.dds)')
+ parser.add_argument('--a8', default=False, action='store_const', const=True,
+ help='Use A8 instead of L8 output')
+ args = parser.parse_args()
+
+ img = Image.open(args.input)
+ orig_width = width = img.size[0]
+ orig_height = height = img.size[1]
+ img = img.convert('L')
+ assert(width > 0 and height > 0)
+
+ (fd, tmpout) = tempfile.mkstemp(suffix='.png')
+ os.close(fd) # won't be using the already-opened fd
+ (fd, tmpout2) = tempfile.mkstemp(suffix='.pkm')
+ os.close(fd)
+ mip = 0
+ mips = []
+ while True:
+ print('Generating mip %i: %ix%i' % (mip, width, height))
+
+ data = img.tostring()
+ print(' size: %i' % len(data))
+ mips.append(data)
+
+ # Go to next mip level
+ if width == 1 and height == 1: # 1x1 reached
+ break
+ width = (width+1) >> 1
+ height = (height+1) >> 1
+ mip += 1
+ img = img.resize((width, height), PIL.Image.ANTIALIAS)
+
+ with open(args.output, 'wb') as f:
+ # Write dds header
+ hdrdata = [0] * (128//4)
+ hdrdata[0] = DDS_MAGIC # dwMagic
+ hdrdata[1] = 124 # dwSize
+ hdrdata[2] = 0x000A1007 # dwFlags (CAPS, WIDTH, HEIGHT, PIXELFORMAT, MIPMAPCOUNT, LINEARSIZE)
+ #hdrdata[2] = 0x0002100F # dwFlags gimp (CAPS, WIDTH, HEIGHT, PITCH, PIXELFORMAT, MIPMAPCOUNT)
+ hdrdata[3] = orig_height # dwHeight
+ hdrdata[4] = orig_width # dwWidth
+ hdrdata[5] = len(mips[0]) # dwPitchOrLinearSize
+ hdrdata[6] = 0 # dwDepth
+ hdrdata[7] = len(mips) # dwMipMapCount
+ hdrdata[19] = 32 # sPixelFormat.dwSize
+ if args.a8:
+ hdrdata[20] = 0x00000002 # sPixelFormat.dwFlags = DDPF_ALPHA
+ else:
+ hdrdata[20] = 0x00020000 # sPixelFormat.dwFlags = DDPF_LUMINANCE
+ hdrdata[21] = 0 # sPixelFormat.dwFourCC
+ hdrdata[22] = 8 # sPixelFormat.dwRGBBitCount
+ if args.a8:
+ hdrdata[23] = 0x00000000 # sPixelFormat.dwRBitMask
+ hdrdata[24] = 0 # sPixelFormat.dwGBitMask
+ hdrdata[25] = 0 # sPixelFormat.dwBBitMask
+ hdrdata[26] = 0x000000ff # sPixelFormat.dwAlphaBitMask
+ else:
+ hdrdata[23] = 0x000000ff # sPixelFormat.dwRBitMask
+ hdrdata[24] = 0 # sPixelFormat.dwGBitMask
+ hdrdata[25] = 0 # sPixelFormat.dwBBitMask
+ hdrdata[26] = 0x00000000 # sPixelFormat.dwAlphaBitMask
+ hdrdata[27] = 0x00401008 # sCaps.dwCaps1 (COMPLEX, TEXTURE, MIPMAP)
+ f.write(struct.pack(b'<32I', *hdrdata))
+ for mip in mips:
+ f.write(mip)
+
+if __name__ == '__main__':
+ main()
+