summaryrefslogtreecommitdiff
path: root/convtexture.c
diff options
context:
space:
mode:
Diffstat (limited to 'convtexture.c')
-rw-r--r--convtexture.c128
1 files changed, 105 insertions, 23 deletions
diff --git a/convtexture.c b/convtexture.c
index e5ec996..5ad4735 100644
--- a/convtexture.c
+++ b/convtexture.c
@@ -35,6 +35,73 @@ const char* format_names[] = {
#undef x
};
+void gen_mip(Image* src, Image* dst, int w, int h) {
+ const float weight = 1.0f / 4.0f;
+ int i, x, y, sw = src->w;
+ dst->pixels = malloc(w * h * sizeof *dst->pixels);
+ dst->w = w;
+ dst->h = h;
+ assert(w == src->w / 2);
+ assert(h == src->h / 2);
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ int sx = x << 1;
+ int sy = y << 1;
+ int ind[] = {
+ sx + (sy) * sw,
+ sx + 1 + (sy) * sw,
+ sx + (sy + 1) * sw,
+ sx + 1 + (sy + 1) * sw
+ };
+ float avg[4] = { 0 };
+ Colour* d = &dst->pixels[x + y * w];
+ for (i = 0; i < 4; i++) {
+ int j;
+ for (j = 0; j < 4; j++)
+ avg[j] +=
+ (float)((uint8_t*)&src->pixels[ind[i]])[j] *
+ weight;
+ }
+ d->r = (uint8_t)avg[0];
+ d->g = (uint8_t)avg[1];
+ d->b = (uint8_t)avg[2];
+ d->a = (uint8_t)avg[3];
+ }
+ }
+}
+
+int auto_count(int w, int h) {
+ int i;
+ for (i = 0; w > 1 || h > 1; i++, w >>= 1, h >>= 1);
+ return i;
+}
+
+int po2(int x) {
+ return x && (!(x & (x - 1)));
+}
+
+Image* gen_mips(Image* src, int count, int* gen_count) {
+ int i, w, h;
+ Image* imgs;
+ if (!count)
+ count = auto_count(src->w, src->h);
+ imgs = malloc(count * sizeof *imgs);
+ imgs[0] = *src;
+ w = src->w >> 1;
+ h = src->h >> 1;
+ if (count && (!po2(src->w) || !po2(src->h))) {
+ print_war("Image size not a power of 2 (no mips for you >:(\n");
+ count = 1;
+ }
+ for (i = 1; i < count; i++) {
+ gen_mip(&imgs[i - 1], &imgs[i], w, h);
+ w >>= 1;
+ h >>= 1;
+ }
+ *gen_count = i;
+ return imgs;
+}
+
unsigned encode_endpoint(const vec3* v) {
return
((unsigned)(v->r * 31.9999f) << 11) |
@@ -264,28 +331,33 @@ void compress_bc5(Colour* pixels, int w, int h, FILE* f) {
}
}
-void write_header(FILE* f, int w, int h, Texture_Format fmt) {
+void write_header(FILE* f, int w, int h, int mips, Texture_Format fmt) {
fwrite("TXTR", 1, 4, f);
fwrite(&w, 1, 4, f);
fwrite(&h, 1, 4, f);
- fwrite(&fmt, 1, 4, f);
+ fwrite(&fmt, 1, 2, f);
+ fwrite(&mips, 1, 2, f);
}
-void convert(Image* image, Texture_Format target, FILE* f) {
- write_header(f, image->w, image->h, target);
- switch (target) {
- case texture_format_bc1:
- compress_bc1(image->pixels, image->w, image->h, f);
- break;
- case texture_format_bc4:
- compress_bc4(image->pixels, image->w, image->h, f);
- break;
- case texture_format_bc5:
- compress_bc5(image->pixels, image->w, image->h, f);
- break;
- default:
- print_err("Unsupported target format.\n");
- pbreak(40);
+void convert(Image* images, int count, Texture_Format target, FILE* f) {
+ int i;
+ write_header(f, images->w, images->h, count, target);
+ for (i = 0; i < count; i++) {
+ Image* image = &images[i];
+ switch (target) {
+ case texture_format_bc1:
+ compress_bc1(image->pixels, image->w, image->h, f);
+ break;
+ case texture_format_bc4:
+ compress_bc4(image->pixels, image->w, image->h, f);
+ break;
+ case texture_format_bc5:
+ compress_bc5(image->pixels, image->w, image->h, f);
+ break;
+ default:
+ print_err("Unsupported target format.\n");
+ pbreak(40);
+ }
}
}
@@ -299,12 +371,17 @@ Texture_Format texture_format_from_string(const char* s) {
return (Texture_Format)0;
}
-int proc_bitmap(FILE* infile, FILE* outfile, Texture_Format target) {
+int proc_bitmap(
+ FILE* infile,
+ FILE* outfile,
+ Texture_Format target,
+ int mc
+) {
unsigned bmp_offset;
int bmp_w, bmp_h, s, x, y;
unsigned short bmp_bits;
Colour* buffer;
- Image img;
+ Image img, * imgs;
Colour pixel;
fseek(infile, 10, SEEK_SET);
@@ -347,7 +424,8 @@ int proc_bitmap(FILE* infile, FILE* outfile, Texture_Format target) {
img.pixels = buffer;
img.w = bmp_w;
img.h = bmp_h;
- convert(&img, target, outfile);
+ imgs = gen_mips(&img, mc, &mc);
+ convert(imgs, mc, target, outfile);
fclose(outfile);
return 0;
}
@@ -519,12 +597,13 @@ int proc_hdr(FILE* infile, FILE* outfile, int half) {
}
}
if (half) {
- write_header(outfile, w, h, texture_format_rgba16f);
+ write_header(outfile, w, h, 1, texture_format_rgba16f);
write_halves(outfile, w * h * 4, (float*)pixels);
} else {
- write_header(outfile, w, h, texture_format_rgba32f);
+ write_header(outfile, w, h, 1, texture_format_rgba32f);
fwrite(pixels, sizeof *pixels, w * h, outfile);
}
+ /* todo mipgen for hdr */
fclose(outfile);
return 0;
}
@@ -532,6 +611,7 @@ int proc_hdr(FILE* infile, FILE* outfile, int half) {
int main(int argc, const char** argv) {
FILE* outfile, * infile;
char magic[11];
+ int mips = 0;
Texture_Format target;
if (argc < 4) {
@@ -545,6 +625,8 @@ int main(int argc, const char** argv) {
return 2;
}
target = texture_format_from_string(argv[3]);
+ if (argc > 4)
+ mips = (int)strtol(argv[4], 0, 10);
outfile = fopen(argv[2], "wb");
if (!outfile) {
@@ -554,7 +636,7 @@ int main(int argc, const char** argv) {
fread(magic, 1, 10, infile); magic[10] = 0;
if (magic[0] == 'B' && magic[1] == 'M') {
- return proc_bitmap(infile, outfile, target);
+ return proc_bitmap(infile, outfile, target, mips);
}
if (string_equal(magic, "#?RADIANCE")) {
int half = target == texture_format_rgba16f;