mirror of https://github.com/adamdruppe/arsd.git
apng starting code
This commit is contained in:
parent
68e67279f2
commit
6e55085a10
201
png.d
201
png.d
|
@ -138,88 +138,9 @@ MemoryImage imageFromPng(PNG* png) {
|
|||
foreach(line; file.rawDatastreamByChunk()) {
|
||||
auto filter = line[0];
|
||||
auto data = unfilter(filter, line[1 .. $], previousLine, bpp);
|
||||
ubyte consumeOne() {
|
||||
ubyte ret = data[0];
|
||||
data = data[1 .. $];
|
||||
return ret;
|
||||
}
|
||||
previousLine = data;
|
||||
import std.conv;
|
||||
|
||||
loop: for(int pixel = 0; pixel < h.width; pixel++)
|
||||
switch(h.type) {
|
||||
case 0: // greyscale
|
||||
case 4: // greyscale with alpha
|
||||
auto value = consumeOne();
|
||||
idata[idataIdx++] = value;
|
||||
idata[idataIdx++] = value;
|
||||
idata[idataIdx++] = value;
|
||||
idata[idataIdx++] = (h.type == 4) ? consumeOne() : 255;
|
||||
break;
|
||||
case 3: // indexed
|
||||
auto b = consumeOne();
|
||||
switch(h.depth) {
|
||||
case 1:
|
||||
idata[idataIdx++] = (b >> 7) & 0x01;
|
||||
pixel++; if(pixel == h.width) break loop;
|
||||
idata[idataIdx++] = (b >> 6) & 0x01;
|
||||
pixel++; if(pixel == h.width) break loop;
|
||||
idata[idataIdx++] = (b >> 5) & 0x01;
|
||||
pixel++; if(pixel == h.width) break loop;
|
||||
idata[idataIdx++] = (b >> 4) & 0x01;
|
||||
pixel++; if(pixel == h.width) break loop;
|
||||
idata[idataIdx++] = (b >> 3) & 0x01;
|
||||
pixel++; if(pixel == h.width) break loop;
|
||||
idata[idataIdx++] = (b >> 2) & 0x01;
|
||||
pixel++; if(pixel == h.width) break loop;
|
||||
idata[idataIdx++] = (b >> 1) & 0x01;
|
||||
pixel++; if(pixel == h.width) break loop;
|
||||
idata[idataIdx++] = b & 0x01;
|
||||
break;
|
||||
case 2:
|
||||
idata[idataIdx++] = (b >> 6) & 0x03;
|
||||
pixel++; if(pixel == h.width) break loop;
|
||||
idata[idataIdx++] = (b >> 4) & 0x03;
|
||||
pixel++; if(pixel == h.width) break loop;
|
||||
idata[idataIdx++] = (b >> 2) & 0x03;
|
||||
pixel++; if(pixel == h.width) break loop;
|
||||
idata[idataIdx++] = b & 0x03;
|
||||
break;
|
||||
case 4:
|
||||
idata[idataIdx++] = (b >> 4) & 0x0f;
|
||||
pixel++; if(pixel == h.width) break loop;
|
||||
idata[idataIdx++] = b & 0x0f;
|
||||
break;
|
||||
case 8:
|
||||
idata[idataIdx++] = b;
|
||||
break;
|
||||
default:
|
||||
assert(0, "bit depth not implemented");
|
||||
}
|
||||
break;
|
||||
case 2: // truecolor
|
||||
case 6: // true with alpha
|
||||
if(h.depth == 8) {
|
||||
idata[idataIdx++] = consumeOne();
|
||||
idata[idataIdx++] = consumeOne();
|
||||
idata[idataIdx++] = consumeOne();
|
||||
idata[idataIdx++] = (h.type == 6) ? consumeOne() : 255;
|
||||
} else if(h.depth == 16) {
|
||||
idata[idataIdx++] = consumeOne();
|
||||
consumeOne();
|
||||
idata[idataIdx++] = consumeOne();
|
||||
consumeOne();
|
||||
idata[idataIdx++] = consumeOne();
|
||||
consumeOne();
|
||||
idata[idataIdx++] = (h.type == 6) ? consumeOne() : 255;
|
||||
if(h.type == 6)
|
||||
consumeOne();
|
||||
|
||||
} else assert(0, "unsupported truecolor bit depth " ~ to!string(h.depth));
|
||||
break;
|
||||
default: assert(0);
|
||||
}
|
||||
assert(data.length == 0, "not all consumed, wtf " ~ to!string(h));
|
||||
convertPngData(h.type, h.depth, data, h.width, idata, idataIdx);
|
||||
}
|
||||
assert(idataIdx == idata.length, "not all filled, wtf");
|
||||
|
||||
|
@ -228,6 +149,91 @@ MemoryImage imageFromPng(PNG* png) {
|
|||
return i;
|
||||
}
|
||||
|
||||
// idata needs to be already sized for the image! width * height if indexed, width*height*4 if not.
|
||||
void convertPngData(ubyte type, ubyte depth, const(ubyte)[] data, int width, ubyte[] idata, ref int idataIdx) {
|
||||
ubyte consumeOne() {
|
||||
ubyte ret = data[0];
|
||||
data = data[1 .. $];
|
||||
return ret;
|
||||
}
|
||||
import std.conv;
|
||||
|
||||
loop: for(int pixel = 0; pixel < width; pixel++)
|
||||
switch(type) {
|
||||
case 0: // greyscale
|
||||
case 4: // greyscale with alpha
|
||||
auto value = consumeOne();
|
||||
idata[idataIdx++] = value;
|
||||
idata[idataIdx++] = value;
|
||||
idata[idataIdx++] = value;
|
||||
idata[idataIdx++] = (type == 4) ? consumeOne() : 255;
|
||||
break;
|
||||
case 3: // indexed
|
||||
auto b = consumeOne();
|
||||
switch(depth) {
|
||||
case 1:
|
||||
idata[idataIdx++] = (b >> 7) & 0x01;
|
||||
pixel++; if(pixel == width) break loop;
|
||||
idata[idataIdx++] = (b >> 6) & 0x01;
|
||||
pixel++; if(pixel == width) break loop;
|
||||
idata[idataIdx++] = (b >> 5) & 0x01;
|
||||
pixel++; if(pixel == width) break loop;
|
||||
idata[idataIdx++] = (b >> 4) & 0x01;
|
||||
pixel++; if(pixel == width) break loop;
|
||||
idata[idataIdx++] = (b >> 3) & 0x01;
|
||||
pixel++; if(pixel == width) break loop;
|
||||
idata[idataIdx++] = (b >> 2) & 0x01;
|
||||
pixel++; if(pixel == width) break loop;
|
||||
idata[idataIdx++] = (b >> 1) & 0x01;
|
||||
pixel++; if(pixel == width) break loop;
|
||||
idata[idataIdx++] = b & 0x01;
|
||||
break;
|
||||
case 2:
|
||||
idata[idataIdx++] = (b >> 6) & 0x03;
|
||||
pixel++; if(pixel == width) break loop;
|
||||
idata[idataIdx++] = (b >> 4) & 0x03;
|
||||
pixel++; if(pixel == width) break loop;
|
||||
idata[idataIdx++] = (b >> 2) & 0x03;
|
||||
pixel++; if(pixel == width) break loop;
|
||||
idata[idataIdx++] = b & 0x03;
|
||||
break;
|
||||
case 4:
|
||||
idata[idataIdx++] = (b >> 4) & 0x0f;
|
||||
pixel++; if(pixel == width) break loop;
|
||||
idata[idataIdx++] = b & 0x0f;
|
||||
break;
|
||||
case 8:
|
||||
idata[idataIdx++] = b;
|
||||
break;
|
||||
default:
|
||||
assert(0, "bit depth not implemented");
|
||||
}
|
||||
break;
|
||||
case 2: // truecolor
|
||||
case 6: // true with alpha
|
||||
if(depth == 8) {
|
||||
idata[idataIdx++] = consumeOne();
|
||||
idata[idataIdx++] = consumeOne();
|
||||
idata[idataIdx++] = consumeOne();
|
||||
idata[idataIdx++] = (type == 6) ? consumeOne() : 255;
|
||||
} else if(depth == 16) {
|
||||
idata[idataIdx++] = consumeOne();
|
||||
consumeOne();
|
||||
idata[idataIdx++] = consumeOne();
|
||||
consumeOne();
|
||||
idata[idataIdx++] = consumeOne();
|
||||
consumeOne();
|
||||
idata[idataIdx++] = (type == 6) ? consumeOne() : 255;
|
||||
if(type == 6)
|
||||
consumeOne();
|
||||
|
||||
} else assert(0, "unsupported truecolor bit depth " ~ to!string(depth));
|
||||
break;
|
||||
default: assert(0);
|
||||
}
|
||||
assert(data.length == 0, "not all consumed, wtf ");// ~ to!string(h));
|
||||
}
|
||||
|
||||
/*
|
||||
struct PngHeader {
|
||||
uint width;
|
||||
|
@ -1467,29 +1473,32 @@ struct LazyPngFile(LazyPngChunksProvider)
|
|||
return .bytesPerPixel(header);
|
||||
}
|
||||
|
||||
// FIXME: doesn't handle interlacing... I think
|
||||
int bytesPerLine() {
|
||||
immutable bitsPerChannel = header.depth;
|
||||
|
||||
int bitsPerPixel = bitsPerChannel;
|
||||
if(header.type & 2 && !(header.type & 1)) // in color, but no palette
|
||||
bitsPerPixel *= 3;
|
||||
if(header.type & 4) // has alpha channel
|
||||
bitsPerPixel += bitsPerChannel;
|
||||
|
||||
|
||||
immutable int sizeInBits = header.width * bitsPerPixel;
|
||||
|
||||
// need to round up to the nearest byte
|
||||
int sizeInBytes = (sizeInBits + 7) / 8;
|
||||
|
||||
return sizeInBytes + 1; // the +1 is for the filter byte that precedes all lines
|
||||
return .bytesPerLineOfPng(header.depth, header.type, header.width);
|
||||
}
|
||||
|
||||
PngHeader header;
|
||||
Color[] palette;
|
||||
}
|
||||
|
||||
// FIXME: doesn't handle interlacing... I think
|
||||
@nogc @safe pure nothrow
|
||||
int bytesPerLineOfPng(ubyte depth, ubyte type, uint width) {
|
||||
immutable bitsPerChannel = depth;
|
||||
|
||||
int bitsPerPixel = bitsPerChannel;
|
||||
if(type & 2 && !(type & 1)) // in color, but no palette
|
||||
bitsPerPixel *= 3;
|
||||
if(type & 4) // has alpha channel
|
||||
bitsPerPixel += bitsPerChannel;
|
||||
|
||||
immutable int sizeInBits = width * bitsPerPixel;
|
||||
|
||||
// need to round up to the nearest byte
|
||||
int sizeInBytes = (sizeInBits + 7) / 8;
|
||||
|
||||
return sizeInBytes + 1; // the +1 is for the filter byte that precedes all lines
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Buffered input range - generic, non-image code
|
||||
|
|
|
@ -45,7 +45,7 @@ module arsd.simpleaudio;
|
|||
enum BUFFER_SIZE_FRAMES = 1024;//512;//2048;
|
||||
enum BUFFER_SIZE_SHORT = BUFFER_SIZE_FRAMES * 2;
|
||||
|
||||
///
|
||||
/// A reasonable default volume for an individual sample. It doesn't need to be large; in fact it needs to not be large so mixing doesn't clip too much.
|
||||
enum DEFAULT_VOLUME = 20;
|
||||
|
||||
version(Demo)
|
||||
|
|
Loading…
Reference in New Issue