diff options
author | Kent Mein <mein@cs.umn.edu> | 2007-10-12 20:09:59 +0400 |
---|---|---|
committer | Kent Mein <mein@cs.umn.edu> | 2007-10-12 20:09:59 +0400 |
commit | 6fe98f19a95117633684b85073b4d90654e159fd (patch) | |
tree | 50d54508e6e4395442fb486d96cb7202a871ee5e | |
parent | 3697e0852467a29223a59d2ad6a31a00cfbde529 (diff) |
This is patch [#7483] imbuf support for uncompressed DDS images
provided by Amorilia
NVIDIA updated the dds stuff so we get a nice new patch.
Kent
-rw-r--r-- | source/blender/imbuf/intern/dds/DirectDrawSurface.cpp | 112 | ||||
-rw-r--r-- | source/blender/imbuf/intern/dds/Stream.cpp | 11 | ||||
-rw-r--r-- | source/blender/imbuf/intern/dds/Stream.h | 1 | ||||
-rw-r--r-- | source/blender/imbuf/intern/dds/dds_api.cpp | 30 |
4 files changed, 137 insertions, 17 deletions
diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp index 6937840334d..c28f8b5b72d 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp @@ -434,16 +434,15 @@ bool DirectDrawSurface::isSupported() const return false; } } - /* else if (header.pf.flags & DDPF_RGB) { if (header.pf.bitcount == 24) { - return false; + return true; } else if (header.pf.bitcount == 32) { - return false; + return true; } else { @@ -451,7 +450,6 @@ bool DirectDrawSurface::isSupported() const return false; } } - */ else { return false; @@ -500,8 +498,18 @@ unsigned int DirectDrawSurface::depth() const bool DirectDrawSurface::hasAlpha() const { - if (header.pf.fourcc == FOURCC_DXT1) return false; - else return true; + if ((header.pf.flags & DDPF_RGB) && (header.pf.amask == 0)) + { + return false; + } + else if (header.pf.fourcc == FOURCC_DXT1) + { + return false; + } + else + { + return true; + } } bool DirectDrawSurface::isTexture2D() const @@ -545,10 +553,98 @@ void DirectDrawSurface::mipmap(Image * img, unsigned int face, unsigned int mipm } } +/* helper function for readLinearImage */ +void maskShiftAndSize(unsigned int mask, unsigned int * shift, unsigned int * size) +{ + if (!mask) + { + *shift = 0; + *size = 0; + return; + } + + *shift = 0; + while((mask & 1) == 0) { + ++(*shift); + mask >>= 1; + } + + *size = 0; + while((mask & 1) == 1) { + ++(*size); + mask >>= 1; + } +} + +/* helper function for readLinearImage */ +unsigned int convert(unsigned int c, unsigned int inbits, unsigned int outbits) +{ + if (inbits == 0) { + return 0; + } + else if (inbits == outbits) + { + return c; + } + else if (inbits > outbits) + { + // truncate + return c >> (inbits - outbits); + } + else + { + // bitexpand + return (c << (outbits - inbits)) | convert(c, inbits, outbits - inbits); + } +} + void DirectDrawSurface::readLinearImage(Image * img) { - // @@ Read linear RGB images. - printf("DDS: linear RGB images not supported\n"); + const unsigned int w = img->width(); + const unsigned int h = img->height(); + + unsigned int rshift, rsize; + maskShiftAndSize(header.pf.rmask, &rshift, &rsize); + + unsigned int gshift, gsize; + maskShiftAndSize(header.pf.gmask, &gshift, &gsize); + + unsigned int bshift, bsize; + maskShiftAndSize(header.pf.bmask, &bshift, &bsize); + + unsigned int ashift, asize; + maskShiftAndSize(header.pf.amask, &ashift, &asize); + + unsigned int byteCount = (header.pf.bitcount + 7) / 8; + if (byteCount > 4) + { + /* just in case... we could have segfaults later on if byteCount > 4 */ + printf("DDS: bitcount too large (file corrupt?)"); + return; + } + + if (header.pf.amask != 0) + { + img->setFormat(Image::Format_ARGB); + } + + // Read linear RGB images. + for (unsigned int y = 0; y < h; y++) + { + for (unsigned int x = 0; x < w; x++) + { + unsigned int c = 0; + mem_read(stream, (unsigned char *)(&c), byteCount); + + Color32 pixel(0, 0, 0, 0xFF); + pixel.r = convert(c >> rshift, rsize, 8); + pixel.g = convert(c >> gshift, gsize, 8); + pixel.b = convert(c >> bshift, bsize, 8); + pixel.a = convert(c >> ashift, asize, 8); + + img->pixel(x, y) = pixel; + } + } } void DirectDrawSurface::readBlockImage(Image * img) diff --git a/source/blender/imbuf/intern/dds/Stream.cpp b/source/blender/imbuf/intern/dds/Stream.cpp index a181ec74476..2340598b4fa 100644 --- a/source/blender/imbuf/intern/dds/Stream.cpp +++ b/source/blender/imbuf/intern/dds/Stream.cpp @@ -86,3 +86,14 @@ unsigned int mem_read(Stream & mem, unsigned char & i) return(1); } +unsigned int mem_read(Stream & mem, unsigned char *i, unsigned int cnt) +{ + if (mem.pos + cnt > mem.size) { + printf("DDS: trying to read beyond end of stream (corrupt file?)"); + return(0); + }; + memcpy(i, mem.mem + mem.pos, cnt); + mem.pos += cnt; + return(cnt); +} + diff --git a/source/blender/imbuf/intern/dds/Stream.h b/source/blender/imbuf/intern/dds/Stream.h index 1e7d3c6b536..373e68db44e 100644 --- a/source/blender/imbuf/intern/dds/Stream.h +++ b/source/blender/imbuf/intern/dds/Stream.h @@ -43,6 +43,7 @@ unsigned int mem_read(Stream & mem, unsigned long long & i); unsigned int mem_read(Stream & mem, unsigned int & i); unsigned int mem_read(Stream & mem, unsigned short & i); unsigned int mem_read(Stream & mem, unsigned char & i); +unsigned int mem_read(Stream & mem, unsigned char *i, unsigned int cnt); #endif // _STREAM_H diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp index 0e06fd3e50b..3de30b9f183 100644 --- a/source/blender/imbuf/intern/dds/dds_api.cpp +++ b/source/blender/imbuf/intern/dds/dds_api.cpp @@ -28,8 +28,8 @@ #include <dds_api.h> #include <Stream.h> #include <DirectDrawSurface.h> - #include <stdio.h> // printf +#include <fstream> extern "C" { @@ -39,12 +39,24 @@ extern "C" { #include "IMB_imbuf.h" #include "IMB_allocimbuf.h" -/* not supported yet + short imb_save_dds(struct ImBuf * ibuf, char *name, int flags) { - return(0); + return(0); /* todo: finish this function */ + + /* check image buffer */ + if (ibuf == 0) return (0); + if (ibuf->rect == 0) return (0); + + /* open file for writing */ + std::ofstream fildes(name); + + /* write header */ + fildes << "DDS "; + fildes.close(); + + return(1); } -*/ int imb_is_a_dds(unsigned char *mem) // note: use at most first 32 bytes { @@ -60,7 +72,7 @@ struct ImBuf *imb_load_dds(unsigned char *mem, int size, int flags) { struct ImBuf * ibuf = 0; DirectDrawSurface dds(mem, size); /* reads header */ - unsigned char bytes_per_pixel; + unsigned char bits_per_pixel; unsigned int *rect; Image img; unsigned int numpixels = 0; @@ -85,9 +97,9 @@ struct ImBuf *imb_load_dds(unsigned char *mem, int size, int flags) } /* convert DDS into ImBuf */ - if (dds.hasAlpha()) bytes_per_pixel = 32; - else bytes_per_pixel = 24; - ibuf = IMB_allocImBuf(dds.width(), dds.height(), bytes_per_pixel, 0, 0); + if (dds.hasAlpha()) bits_per_pixel = 32; + else bits_per_pixel = 24; + ibuf = IMB_allocImBuf(dds.width(), dds.height(), bits_per_pixel, 0, 0); if (ibuf == 0) return(0); /* memory allocation failed */ ibuf->ftype = DDS; @@ -107,7 +119,7 @@ struct ImBuf *imb_load_dds(unsigned char *mem, int size, int flags) cp[0] = pixel.r; /* set R component of col */ cp[1] = pixel.g; /* set G component of col */ cp[2] = pixel.b; /* set B component of col */ - if (bytes_per_pixel == 32) + if (bits_per_pixel == 32) cp[3] = pixel.a; /* set A component of col */ rect[i] = col; } |