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
This commit is contained in:
2007-10-12 16:09:59 +00:00
parent 3697e08524
commit 6fe98f19a9
4 changed files with 137 additions and 17 deletions

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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;
}