mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-16 19:15:14 -04:00
Fix png decoding issues finally
This commit is contained in:
parent
e7bd09b8b0
commit
a2536acf2f
@ -101,7 +101,10 @@ void Png_Reconstruct(UInt8 type, UInt8 bytesPerPixel, UInt8* line, UInt8* prior,
|
||||
|
||||
case PNG_FILTER_PAETH:
|
||||
/* TODO: verify this is right */
|
||||
for (i = bytesPerPixel, j = 0; i < lineLen; i++, j++) {
|
||||
for (i = 0; i < bytesPerPixel; i++) {
|
||||
line[i] += prior[i];
|
||||
}
|
||||
for (j = 0; i < lineLen; i++, j++) {
|
||||
UInt8 a = line[j], b = prior[i], c = prior[j];
|
||||
Int32 p = a + b - c;
|
||||
Int32 pa = Math_AbsI(p - a);
|
||||
@ -311,8 +314,7 @@ void Bitmap_DecodePng(Bitmap* bmp, Stream* stream) {
|
||||
|
||||
UInt32 scanlineSize, scanlineBytes, curY = 0;
|
||||
UInt8 buffer[PNG_BUFFER_SIZE];
|
||||
UInt32 bufferIdx, bufferLen, bufferCur;
|
||||
UInt32 scanlineIndices[2];
|
||||
UInt32 bufferIdx, bufferRows;
|
||||
|
||||
while (readingChunks) {
|
||||
UInt32 dataSize = Stream_ReadU32_BE(stream);
|
||||
@ -344,16 +346,13 @@ void Bitmap_DecodePng(Bitmap* bmp, Stream* stream) {
|
||||
if (Stream_ReadU8(stream) != 0) ErrorHandler_Fail("PNG interlacing not supported");
|
||||
|
||||
static UInt32 samplesPerPixel[7] = { 1,0,3,1,2,0,4 };
|
||||
scanlineSize = ((samplesPerPixel[col] * bitsPerSample * bmp->Width) + 7) >> 3;
|
||||
scanlineBytes = scanlineSize + 1;
|
||||
bytesPerPixel = ((samplesPerPixel[col] * bitsPerSample) + 7) >> 3;
|
||||
bufferLen = (PNG_BUFFER_SIZE / scanlineBytes) * scanlineBytes;
|
||||
scanlineSize = ((samplesPerPixel[col] * bitsPerSample * bmp->Width) + 7) >> 3;
|
||||
scanlineBytes = scanlineSize + 1; /* Add 1 byte for filter byte of each scanline */
|
||||
|
||||
scanlineIndices[0] = 0;
|
||||
scanlineIndices[1] = scanlineBytes;
|
||||
Platform_MemSet(buffer, 0, scanlineBytes); /* Prior row should be 0 per PNG spec */
|
||||
bufferIdx = scanlineBytes;
|
||||
bufferCur = scanlineBytes;
|
||||
bufferRows = PNG_BUFFER_SIZE / scanlineBytes;
|
||||
|
||||
switch (col) {
|
||||
case PNG_COL_GRAYSCALE: rowExpander = Png_Expand_GRAYSCALE; break;
|
||||
@ -404,42 +403,41 @@ void Bitmap_DecodePng(Bitmap* bmp, Stream* stream) {
|
||||
Stream datStream;
|
||||
Stream_ReadonlyPortion(&datStream, stream, dataSize);
|
||||
inflate.Source = &datStream;
|
||||
|
||||
/* TODO: This assumes zlib header will be in 1 IDAT chunk */
|
||||
while (!zlibHeader.Done) { ZLibHeader_Read(&datStream, &zlibHeader); }
|
||||
|
||||
UInt32 scanlineBytes = (scanlineSize + 1); /* Add 1 byte for filter byte of each scanline*/
|
||||
UInt32 bufferLen = bufferRows * scanlineBytes, bufferMax = bufferLen - scanlineBytes;
|
||||
while (curY < bmp->Height) {
|
||||
UInt32 bufferRemaining = bufferLen - bufferIdx, read;
|
||||
ReturnCode code = compStream.Read(&compStream, &buffer[bufferIdx], bufferRemaining, &read);
|
||||
/* Need to leave one row in buffer untouched for storing prior scanline. Illustrated example of process:
|
||||
* |=====| #-----| |-----| #-----| |-----|
|
||||
* initial #-----| read 3 |-----| read 3 |-----| read 1 |-----| read 3 |-----| etc
|
||||
* state |-----| -----> |-----| -----> |=====| -----> |-----| -----> |=====|
|
||||
* |-----| |=====| #-----| |=====| #-----|
|
||||
*
|
||||
* (==== is prior scanline, # is current index in buffer)
|
||||
* Having initial state this way allows doing two 'read 3' first time (assuming large idat chunks)
|
||||
*/
|
||||
UInt32 bufferLeft = bufferLen - bufferIdx, read;
|
||||
if (bufferLeft > bufferMax) bufferLeft = bufferMax;
|
||||
|
||||
ReturnCode code = compStream.Read(&compStream, &buffer[bufferIdx], bufferLeft, &read);
|
||||
ErrorHandler_CheckOrFail(code, "PNG - reading image bulk data");
|
||||
if (read == 0) break;
|
||||
|
||||
/* buffer is arranged like this */
|
||||
/* scanline 0 | A
|
||||
1 | B <-- bufferCur
|
||||
2 | X
|
||||
3 | X <-- bufferIdx (for example)
|
||||
4 | X
|
||||
*/
|
||||
/* When reading, we need to handle the case of when the buffer cycles over back to start */
|
||||
|
||||
UInt32 startY = bufferIdx / scanlineBytes, rowY;
|
||||
bufferIdx += read;
|
||||
while (bufferIdx >= bufferCur + scanlineBytes && curY < bmp->Height) {
|
||||
UInt8* prior = &buffer[scanlineIndices[0]];
|
||||
UInt8* scanline = &buffer[scanlineIndices[1]];
|
||||
UInt32 endY = bufferIdx / scanlineBytes;
|
||||
/* reached end of buffer, cycle back to start */
|
||||
if (bufferIdx == bufferLen) bufferIdx = 0;
|
||||
|
||||
for (rowY = startY; rowY < endY; rowY++, curY++) {
|
||||
UInt32 priorY = rowY == 0 ? bufferRows : rowY;
|
||||
UInt8* prior = &buffer[(priorY - 1) * scanlineBytes];
|
||||
UInt8* scanline = &buffer[rowY * scanlineBytes];
|
||||
|
||||
Png_Reconstruct(scanline[0], bytesPerPixel, &scanline[1], &prior[1], scanlineSize);
|
||||
rowExpander(bitsPerSample, bmp->Width, palette, &scanline[1], Bitmap_GetRow(bmp, curY));
|
||||
curY++;
|
||||
|
||||
/* Advance scanlines, with wraparound behaviour */
|
||||
scanlineIndices[0] = (scanlineIndices[0] + scanlineBytes) % bufferLen;
|
||||
scanlineIndices[1] = (scanlineIndices[1] + scanlineBytes) % bufferLen;
|
||||
bufferCur += scanlineBytes;
|
||||
if (bufferCur == bufferLen) { bufferCur = 0; break; }
|
||||
}
|
||||
if (bufferIdx == bufferLen) bufferIdx = 0;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
|
@ -459,8 +459,10 @@ void Inflate_Process(InflateState* state) {
|
||||
case INFLATE_STATE_UNCOMPRESSED_DATA: {
|
||||
while (state->NumBits > 0 && state->AvailOut > 0 && state->Index > 0) {
|
||||
*state->Output = Inflate_ReadBits(state, 8);
|
||||
state->AvailOut--;
|
||||
state->Index--;
|
||||
state->Window[state->WindowIndex] = *state->Output;
|
||||
|
||||
state->WindowIndex = (state->WindowIndex + 1) & INFLATE_WINDOW_MASK;
|
||||
state->Output++; state->AvailOut--; state->Index--;
|
||||
}
|
||||
if (state->AvailIn == 0 || state->AvailOut == 0) return;
|
||||
|
||||
@ -468,11 +470,18 @@ void Inflate_Process(InflateState* state) {
|
||||
copyLen = min(copyLen, state->Index);
|
||||
if (copyLen > 0) {
|
||||
Platform_MemCpy(state->Output, state->NextIn, copyLen);
|
||||
/* TODO: Copy output to window!!! */
|
||||
state->Output += copyLen; state->AvailOut -= copyLen;
|
||||
state->NextIn += copyLen;
|
||||
state->AvailIn -= copyLen;
|
||||
state->Index -= copyLen;
|
||||
UInt32 windowCopyLen = INFLATE_WINDOW_SIZE - state->WindowIndex;
|
||||
windowCopyLen = min(windowCopyLen, copyLen);
|
||||
|
||||
Platform_MemCpy(&state->Window[state->WindowIndex], state->Output, windowCopyLen);
|
||||
/* Wrap around remainder of copy to start from beginning of window */
|
||||
if (windowCopyLen < copyLen) {
|
||||
Platform_MemCpy(state->Window, &state->Output[windowCopyLen], copyLen - windowCopyLen);
|
||||
}
|
||||
|
||||
state->WindowIndex = (state->WindowIndex + copyLen) & INFLATE_WINDOW_MASK;
|
||||
state->Output += copyLen; state->AvailOut -= copyLen; state->Index -= copyLen;
|
||||
state->NextIn += copyLen; state->AvailIn -= copyLen;
|
||||
}
|
||||
|
||||
if (state->Index == 0) {
|
||||
|
@ -228,15 +228,6 @@ bool Game_UpdateTexture(GfxResourceID* texId, Stream* src, bool setSkinType) {
|
||||
Bitmap bmp; Bitmap_DecodePng(&bmp, src);
|
||||
bool success = Game_ValidateBitmap(&src->Name, &bmp);
|
||||
|
||||
if (String_CaselessEqualsConst(&src->Name, "cloud.png") || String_CaselessEqualsConst(&src->Name, "clouds.png")) {
|
||||
Stream abcd;
|
||||
String abcdF = String_FromConst("screenshots/cloud_dump2.png");
|
||||
void* abcdFile; Platform_FileCreate(&abcdFile, &abcdF);
|
||||
Stream_FromFile(&abcd, abcdFile, &abcdF);
|
||||
Bitmap_EncodePng(&bmp, &abcd);
|
||||
abcd.Close(&abcd);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
Gfx_DeleteTexture(texId);
|
||||
if (setSkinType) Game_SetDefaultSkinType(&bmp);
|
||||
|
@ -49,7 +49,7 @@ void Platform_Init(void) {
|
||||
deviceNum++;
|
||||
if ((device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) == 0) continue;
|
||||
bool devPrimary = false;
|
||||
DisplayResolution resolution = DisplayResolution_Make(0, 0, 0, 0.0f);
|
||||
DisplayResolution resolution = { 0 };
|
||||
DEVMODEA mode = { 0 };
|
||||
mode.dmSize = sizeof(DEVMODEA);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user