Fix 1/2/4 bit grayscale pngs being incorrectly decoded

This commit is contained in:
UnknownShadow200 2018-11-16 17:54:47 +11:00
parent e7738b50fa
commit 02c114db35
7 changed files with 73 additions and 67 deletions

View File

@ -125,9 +125,9 @@ static void Png_Reconstruct(uint8_t type, uint8_t bytesPerPixel, uint8_t* line,
#define Bitmap_Set(dst, r,g,b,a) dst.B = b; dst.G = g; dst.R = r; dst.A = a; #define Bitmap_Set(dst, r,g,b,a) dst.B = b; dst.G = g; dst.R = r; dst.A = a;
#define PNG_Do_Grayscale(dstI, srcI, scale) rgb = src[srcI] * scale; Bitmap_Set(dst[dstI], rgb, rgb, rgb, 255); #define PNG_Do_Grayscale(dstI, src, scale) rgb = (src) * scale; Bitmap_Set(dst[dstI], rgb, rgb, rgb, 255);
#define PNG_Do_Grayscale_8(dstI, srcI) rgb = src[srcI]; Bitmap_Set(dst[dstI], rgb, rgb, rgb, 255); #define PNG_Do_Grayscale_8(dstI, srcI) rgb = src[srcI]; Bitmap_Set(dst[dstI], rgb, rgb, rgb, 255);
#define PNG_Do_Grayscale_A__8(dstI, srcI) rgb = src[srcI]; Bitmap_Set(dst[dstI], rgb, rgb, rgb, src[srcI + 1]); #define PNG_Do_Grayscale_A__8(dstI, srcI) rgb = src[srcI]; Bitmap_Set(dst[dstI], rgb, rgb, rgb, src[srcI + 1]);
#define PNG_Do_RGB__8(dstI, srcI) Bitmap_Set(dst[dstI], src[srcI], src[srcI + 1], src[srcI + 2], 255); #define PNG_Do_RGB__8(dstI, srcI) Bitmap_Set(dst[dstI], src[srcI], src[srcI + 1], src[srcI + 2], 255);
#define PNG_Do_RGB_A__8(dstI, srcI) Bitmap_Set(dst[dstI], src[srcI], src[srcI + 1], src[srcI + 2], src[srcI + 3]); #define PNG_Do_RGB_A__8(dstI, srcI) Bitmap_Set(dst[dstI], src[srcI], src[srcI + 1], src[srcI + 2], src[srcI + 3]);
@ -326,6 +326,7 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
ReturnCode res; ReturnCode res;
/* header variables */ /* header variables */
static uint32_t samplesPerPixel[7] = { 1, 0, 3, 1, 2, 0, 4 };
uint8_t col, bitsPerSample, bytesPerPixel; uint8_t col, bitsPerSample, bytesPerPixel;
Png_RowExpander rowExpander; Png_RowExpander rowExpander;
uint32_t scanlineSize, scanlineBytes; uint32_t scanlineSize, scanlineBytes;
@ -384,7 +385,6 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
if (tmp[11] != 0) return PNG_ERR_FILTER; if (tmp[11] != 0) return PNG_ERR_FILTER;
if (tmp[12] != 0) return PNG_ERR_INTERLACED; if (tmp[12] != 0) return PNG_ERR_INTERLACED;
static uint32_t samplesPerPixel[7] = { 1, 0, 3, 1, 2, 0, 4 };
bytesPerPixel = ((samplesPerPixel[col] * bitsPerSample) + 7) >> 3; bytesPerPixel = ((samplesPerPixel[col] * bitsPerSample) + 7) >> 3;
scanlineSize = ((samplesPerPixel[col] * bitsPerSample * bmp->Width) + 7) >> 3; scanlineSize = ((samplesPerPixel[col] * bitsPerSample * bmp->Width) + 7) >> 3;
scanlineBytes = scanlineSize + 1; /* Add 1 byte for filter byte of each scanline */ scanlineBytes = scanlineSize + 1; /* Add 1 byte for filter byte of each scanline */
@ -415,8 +415,8 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
if (res) return res; if (res) return res;
/* RGB is 16 bits big endian, ignore least significant 8 bits */ /* RGB is 16 bits big endian, ignore least significant 8 bits */
transparentCol.B = tmp[0]; transparentCol.G = tmp[0]; transparentCol.R = tmp[0]; transparentCol.G = tmp[0];
transparentCol.R = tmp[0]; transparentCol.A = 0; transparentCol.B = tmp[0]; transparentCol.A = 0;
} else if (col == PNG_COL_INDEXED) { } else if (col == PNG_COL_INDEXED) {
if (dataSize > PNG_PALETTE) return PNG_ERR_TRANS_COUNT; if (dataSize > PNG_PALETTE) return PNG_ERR_TRANS_COUNT;
res = Stream_Read(stream, tmp, dataSize); res = Stream_Read(stream, tmp, dataSize);
@ -432,8 +432,8 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
if (res) return res; if (res) return res;
/* R,G,B is 16 bits big endian, ignore least significant 8 bits */ /* R,G,B is 16 bits big endian, ignore least significant 8 bits */
transparentCol.B = tmp[4]; transparentCol.G = tmp[2]; transparentCol.R = tmp[0]; transparentCol.G = tmp[2];
transparentCol.R = tmp[0]; transparentCol.A = 0; transparentCol.B = tmp[4]; transparentCol.A = 0;
} else { } else {
return PNG_ERR_TRANS_INVALID; return PNG_ERR_TRANS_INVALID;
} }

View File

@ -22,20 +22,20 @@ static uint32_t Block_DefinedCustomBlocks[BLOCK_COUNT >> 5];
static char Block_NamesBuffer[STRING_SIZE * BLOCK_COUNT]; static char Block_NamesBuffer[STRING_SIZE * BLOCK_COUNT];
#define Block_NamePtr(i) &Block_NamesBuffer[STRING_SIZE * i] #define Block_NamePtr(i) &Block_NamesBuffer[STRING_SIZE * i]
uint8_t Block_TopTex[BLOCK_CPE_COUNT] = { 0, 1, 0, 2, 16, 4, 15, 17, 14, 14, static uint8_t Block_TopTex[BLOCK_CPE_COUNT] = { 0, 1, 0, 2, 16, 4, 15,
30, 30, 18, 19, 32, 33, 34, 21, 22, 48, 49, 64, 65, 66, 67, 68, 69, 70, 71, 17, 14, 14, 30, 30, 18, 19, 32, 33, 34, 21, 22, 48, 49, 64, 65, 66, 67, 68, 69,
72, 73, 74, 75, 76, 77, 78, 79, 13, 12, 29, 28, 24, 23, 6, 6, 7, 9, 4, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 13, 12, 29, 28, 24, 23, 6, 6, 7, 9,
36, 37, 16, 11, 25, 50, 38, 80, 81, 82, 83, 84, 51, 54, 86, 26, 53, 52, }; 4, 36, 37, 16, 11, 25, 50, 38, 80, 81, 82, 83, 84, 51, 54, 86, 26, 53, 52 };
uint8_t Block_SideTex[BLOCK_CPE_COUNT] = { 0, 1, 3, 2, 16, 4, 15, 17, 14, 14, static uint8_t Block_SideTex[BLOCK_CPE_COUNT] = { 0, 1, 3, 2, 16, 4, 15,
30, 30, 18, 19, 32, 33, 34, 20, 22, 48, 49, 64, 65, 66, 67, 68, 69, 70, 71, 17, 14, 14, 30, 30, 18, 19, 32, 33, 34, 20, 22, 48, 49, 64, 65, 66, 67, 68, 69,
72, 73, 74, 75, 76, 77, 78, 79, 13, 12, 29, 28, 40, 39, 5, 5, 7, 8, 35, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 13, 12, 29, 28, 40, 39, 5, 5, 7, 8,
36, 37, 16, 11, 41, 50, 38, 80, 81, 82, 83, 84, 51, 54, 86, 42, 53, 52, }; 35, 36, 37, 16, 11, 41, 50, 38, 80, 81, 82, 83, 84, 51, 54, 86, 42, 53, 52 };
uint8_t Block_BottomTex[BLOCK_CPE_COUNT] = { 0, 1, 2, 2, 16, 4, 15, 17, 14, 14, static uint8_t Block_BottomTex[BLOCK_CPE_COUNT] = { 0, 1, 2, 2, 16, 4, 15,
30, 30, 18, 19, 32, 33, 34, 21, 22, 48, 49, 64, 65, 66, 67, 68, 69, 70, 71, 17, 14, 14, 30, 30, 18, 19, 32, 33, 34, 21, 22, 48, 49, 64, 65, 66, 67, 68, 69,
72, 73, 74, 75, 76, 77, 78, 79, 13, 12, 29, 28, 56, 55, 6, 6, 7, 10, 4, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 13, 12, 29, 28, 56, 55, 6, 6, 7, 10,
36, 37, 16, 11, 57, 50, 38, 80, 81, 82, 83, 84, 51, 54, 86, 58, 53, 52 }; 4, 36, 37, 16, 11, 57, 50, 38, 80, 81, 82, 83, 84, 51, 54, 86, 58, 53, 52 };
#ifdef EXTENDED_BLOCKS #ifdef EXTENDED_BLOCKS
void Block_SetUsedCount(int count) { void Block_SetUsedCount(int count) {
@ -589,11 +589,13 @@ float DefaultSet_FogDensity(BlockID b) {
} }
PackedCol DefaultSet_FogColour(BlockID b) { PackedCol DefaultSet_FogColour(BlockID b) {
if (b == BLOCK_WATER || b == BLOCK_STILL_WATER) PackedCol colWater = PACKEDCOL_CONST( 5, 5, 51, 255);
return PackedCol_Create3(5, 5, 51); PackedCol colLava = PACKEDCOL_CONST(153, 25, 0, 255);
if (b == BLOCK_LAVA || b == BLOCK_STILL_LAVA) PackedCol colZero = PACKEDCOL_CONST( 0, 0, 0, 0);
return PackedCol_Create3(153, 25, 0);
return PackedCol_Create4(0, 0, 0, 0); if (b == BLOCK_WATER || b == BLOCK_STILL_WATER) return colWater;
if (b == BLOCK_LAVA || b == BLOCK_STILL_LAVA) return colLava;
return colZero;
} }
CollideType DefaultSet_Collide(BlockID b) { CollideType DefaultSet_Collide(BlockID b) {

View File

@ -353,13 +353,17 @@ static void Drawer2D_DrawBitmapText(Bitmap* bmp, struct DrawTextArgs* args, int
} }
static Size2D Drawer2D_MeasureBitmapText(struct DrawTextArgs* args) { static Size2D Drawer2D_MeasureBitmapText(struct DrawTextArgs* args) {
int point = args->Font.Size; int i, point = args->Font.Size;
/* adjust coords to make drawn text match GDI fonts */ int offset, xPadding;
int i, offset; Size2D total;
int xPadding = Drawer2D_XPadding(point); String text;
Size2D total = { 0, Drawer2D_AdjHeight(point) };
String text = args->Text; /* adjust coords to make drawn text match GDI fonts */
xPadding = Drawer2D_XPadding(point);
total.Width = 0;
total.Height = Drawer2D_AdjHeight(point);
text = args->Text;
for (i = 0; i < text.length; i++) { for (i = 0; i < text.length; i++) {
char c = text.buffer[i]; char c = text.buffer[i];
if (c == '&' && Drawer2D_ValidColCodeAt(&text, i + 1)) { if (c == '&' && Drawer2D_ValidColCodeAt(&text, i + 1)) {

View File

@ -1628,16 +1628,20 @@ static void KeyBindingsScreen_OnBindingClick(void* screen, void* widget) {
static int KeyBindingsScreen_MakeWidgets(struct KeyBindingsScreen* s, int y, int arrowsY, int leftLength, const char* title, int btnWidth) { static int KeyBindingsScreen_MakeWidgets(struct KeyBindingsScreen* s, int y, int arrowsY, int leftLength, const char* title, int btnWidth) {
static String lArrow = String_FromConst("<"); static String lArrow = String_FromConst("<");
static String rArrow = String_FromConst(">"); static String rArrow = String_FromConst(">");
String text; char textBuffer[STRING_SIZE];
String titleText;
Widget_LeftClick backClick;
int origin, xOffset;
int i, xDir;
int i, origin = y, xOffset = btnWidth / 2 + 5; origin = y;
xOffset = btnWidth / 2 + 5;
s->CurI = -1; s->CurI = -1;
String_InitArray(text, textBuffer);
char textBuffer[STRING_SIZE];
String text = String_FromArray(textBuffer);
for (i = 0; i < s->BindsCount; i++) { for (i = 0; i < s->BindsCount; i++) {
if (i == leftLength) y = origin; /* reset y for next column */ if (i == leftLength) y = origin; /* reset y for next column */
int xDir = leftLength == -1 ? 0 : (i < leftLength ? -1 : 1); xDir = leftLength == -1 ? 0 : (i < leftLength ? -1 : 1);
text.length = 0; text.length = 0;
KeyBindingsScreen_GetText(s, i, &text); KeyBindingsScreen_GetText(s, i, &text);
@ -1647,11 +1651,11 @@ static int KeyBindingsScreen_MakeWidgets(struct KeyBindingsScreen* s, int y, int
y += 50; /* distance between buttons */ y += 50; /* distance between buttons */
} }
String titleText = String_FromReadonly(title); titleText = String_FromReadonly(title);
Menu_Label(s, i, &s->Title, &titleText, &s->TitleFont, Menu_Label(s, i, &s->Title, &titleText, &s->TitleFont,
ANCHOR_CENTRE, ANCHOR_CENTRE, 0, -180); i++; ANCHOR_CENTRE, ANCHOR_CENTRE, 0, -180); i++;
Widget_LeftClick backClick = Game_UseClassicOptions ? Menu_SwitchClassicOptions : Menu_SwitchOptions; backClick = Game_UseClassicOptions ? Menu_SwitchClassicOptions : Menu_SwitchOptions;
Menu_Back(s, i, &s->Back, "Done", &s->TitleFont, backClick); i++; Menu_Back(s, i, &s->Back, "Done", &s->TitleFont, backClick); i++;
if (!s->LeftPage && !s->RightPage) return i; if (!s->LeftPage && !s->RightPage) return i;
@ -2997,11 +3001,14 @@ static void TexIdsOverlay_RenderTerrain(struct TexIdsOverlay* s) {
} }
static void TexIdsOverlay_RenderTextOverlay(struct TexIdsOverlay* s) { static void TexIdsOverlay_RenderTextOverlay(struct TexIdsOverlay* s) {
int x, y, size = s->TileSize;
VertexP3fT2fC4b vertices[TEXID_OVERLAY_VERTICES_COUNT]; VertexP3fT2fC4b vertices[TEXID_OVERLAY_VERTICES_COUNT];
VertexP3fT2fC4b* ptr = vertices; VertexP3fT2fC4b* ptr = vertices;
struct TextAtlas* idAtlas;
int size, count;
int x, y, id;
struct TextAtlas* idAtlas = &s->IdAtlas; size = s->TileSize;
idAtlas = &s->IdAtlas;
idAtlas->Tex.Y = s->YOffset + (size - idAtlas->Tex.Height); idAtlas->Tex.Y = s->YOffset + (size - idAtlas->Tex.Height);
for (y = 0; y < ATLAS2D_TILES_PER_ROW; y++) { for (y = 0; y < ATLAS2D_TILES_PER_ROW; y++) {
@ -3010,11 +3017,12 @@ static void TexIdsOverlay_RenderTextOverlay(struct TexIdsOverlay* s) {
int id = x + y * ATLAS2D_TILES_PER_ROW; int id = x + y * ATLAS2D_TILES_PER_ROW;
TextAtlas_AddInt(idAtlas, id + s->BaseTexLoc, &ptr); TextAtlas_AddInt(idAtlas, id + s->BaseTexLoc, &ptr);
} }
idAtlas->Tex.Y += size;
idAtlas->Tex.Y += size;
if ((y % 4) != 3) continue; if ((y % 4) != 3) continue;
Gfx_BindTexture(idAtlas->Tex.ID); Gfx_BindTexture(idAtlas->Tex.ID);
int count = (int)(ptr - vertices);
count = (int)(ptr - vertices);
GfxCommon_UpdateDynamicVb_IndexedTris(s->DynamicVb, vertices, count); GfxCommon_UpdateDynamicVb_IndexedTris(s->DynamicVb, vertices, count);
ptr = vertices; ptr = vertices;
} }
@ -3035,16 +3043,14 @@ static void TexIdsOverlay_Render(void* screen, double delta) {
Gfx_SetBatchFormat(VERTEX_FORMAT_P3FT2FC4B); Gfx_SetBatchFormat(VERTEX_FORMAT_P3FT2FC4B);
Menu_Render(s, delta); Menu_Render(s, delta);
rows = Atlas2D_RowsCount;
origXOffset = s->XOffset; origXOffset = s->XOffset;
s->BaseTexLoc = 0; s->BaseTexLoc = 0;
while (rows > 0) { for (rows = Atlas2D_RowsCount; rows > 0; rows -= ATLAS2D_TILES_PER_ROW) {
TexIdsOverlay_RenderTerrain(s); TexIdsOverlay_RenderTerrain(s);
TexIdsOverlay_RenderTextOverlay(s); TexIdsOverlay_RenderTextOverlay(s);
rows -= ATLAS2D_TILES_PER_ROW;
s->XOffset += s->TileSize * ATLAS2D_TILES_PER_ROW; s->XOffset += s->TileSize * ATLAS2D_TILES_PER_ROW;
s->BaseTexLoc += ATLAS2D_TILES_PER_ROW * ATLAS2D_TILES_PER_ROW; s->BaseTexLoc += ATLAS2D_TILES_PER_ROW * ATLAS2D_TILES_PER_ROW;
} }

View File

@ -1,14 +1,6 @@
#include "PackedCol.h" #include "PackedCol.h"
#include "ExtMath.h" #include "ExtMath.h"
PackedCol PackedCol_Create4(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
PackedCol c; c.R = r; c.G = g; c.B = b; c.A = a; return c;
}
PackedCol PackedCol_Create3(uint8_t r, uint8_t g, uint8_t b) {
PackedCol c; c.R = r; c.G = g; c.B = b; c.A = 255; return c;
}
bool PackedCol_Equals(PackedCol a, PackedCol b) { bool PackedCol_Equals(PackedCol a, PackedCol b) {
return a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A; return a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A;
} }
@ -54,9 +46,12 @@ void PackedCol_ToHex(String* str, PackedCol value) {
} }
bool PackedCol_TryParseHex(const String* str, PackedCol* value) { bool PackedCol_TryParseHex(const String* str, PackedCol* value) {
PackedCol colZero = PACKEDCOL_CONST(0, 0, 0, 0);
int rH, rL, gH, gL, bH, bL; int rH, rL, gH, gL, bH, bL;
char* buffer = str->buffer; char* buffer;
*value = PackedCol_Create4(0, 0, 0, 0);
buffer = str->buffer;
*value = colZero;
/* accept XXYYZZ or #XXYYZZ forms */ /* accept XXYYZZ or #XXYYZZ forms */
if (str->length < 6) return false; if (str->length < 6) return false;
@ -67,6 +62,9 @@ bool PackedCol_TryParseHex(const String* str, PackedCol* value) {
if (!PackedCol_Unhex(buffer[2], &gH) || !PackedCol_Unhex(buffer[3], &gL)) return false; if (!PackedCol_Unhex(buffer[2], &gH) || !PackedCol_Unhex(buffer[3], &gL)) return false;
if (!PackedCol_Unhex(buffer[4], &bH) || !PackedCol_Unhex(buffer[5], &bL)) return false; if (!PackedCol_Unhex(buffer[4], &bH) || !PackedCol_Unhex(buffer[5], &bL)) return false;
*value = PackedCol_Create3((rH << 4) | rL, (gH << 4) | gL, (bH << 4) | bL); value->R = (uint8_t)((rH << 4) | rL);
value->G = (uint8_t)((gH << 4) | gL);
value->B = (uint8_t)((bH << 4) | bL);
value->A = 255;
return true; return true;
} }

View File

@ -24,12 +24,9 @@ typedef union PackedColUnion_ { PackedCol C; uint32_t Raw; } PackedColUnion;
#define PACKEDCOL_CONST(r, g, b, a) { r, g, b, a } #define PACKEDCOL_CONST(r, g, b, a) { r, g, b, a }
#endif #endif
#define PACKEDCOL_WHITE PACKEDCOL_CONST(255, 255, 255, 255) #define PACKEDCOL_WHITE PACKEDCOL_CONST(255, 255, 255, 255)
PackedCol PackedCol_Create4(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
PackedCol PackedCol_Create3(uint8_t r, uint8_t g, uint8_t b);
bool PackedCol_Equals(PackedCol a, PackedCol b);
#define PackedCol_ARGB(r, g, b, a) (((uint32_t)(r) << 16) | ((uint32_t)(g) << 8) | ((uint32_t)(b)) | ((uint32_t)(a) << 24)) #define PackedCol_ARGB(r, g, b, a) (((uint32_t)(r) << 16) | ((uint32_t)(g) << 8) | ((uint32_t)(b)) | ((uint32_t)(a) << 24))
bool PackedCol_Equals(PackedCol a, PackedCol b);
PackedCol PackedCol_Scale(PackedCol value, float t); PackedCol PackedCol_Scale(PackedCol value, float t);
PackedCol PackedCol_Lerp(PackedCol a, PackedCol b, float t); PackedCol PackedCol_Lerp(PackedCol a, PackedCol b, float t);
CC_NOINLINE bool PackedCol_Unhex(char hex, int* value); CC_NOINLINE bool PackedCol_Unhex(char hex, int* value);

View File

@ -69,7 +69,9 @@ void PickedPosRenderer_Update(struct PickedPos* selected) {
PickedPos_X(0) PickedPos_X(3) /* XMin, XMax */ PickedPos_X(0) PickedPos_X(3) /* XMin, XMax */
PickedPos_Z(0) PickedPos_Z(3) /* ZMin, ZMax */ PickedPos_Z(0) PickedPos_Z(3) /* ZMin, ZMax */
}; };
PackedCol col = PACKEDCOL_CONST(0, 0, 0, 102);
VertexP3fC4b* ptr;
int i;
Vector3 delta; Vector3 delta;
float dist, offset, size; float dist, offset, size;
Vector3 coords[4]; Vector3 coords[4];
@ -107,10 +109,7 @@ void PickedPosRenderer_Update(struct PickedPos* selected) {
Vector3_Add1(&coords[3], &selected->Max, offset); Vector3_Add1(&coords[3], &selected->Max, offset);
Vector3_Add1(&coords[2], &coords[3], -size); Vector3_Add1(&coords[2], &coords[3], -size);
PackedCol col = PACKEDCOL_CONST(0, 0, 0, 102); ptr = pickedPos_vertices;
VertexP3fC4b* ptr = pickedPos_vertices;
int i;
for (i = 0; i < Array_Elems(indices); i += 3, ptr++) { for (i = 0; i < Array_Elems(indices); i += 3, ptr++) {
ptr->X = coords[indices[i + 0]].X; ptr->X = coords[indices[i + 0]].X;
ptr->Y = coords[indices[i + 1]].Y; ptr->Y = coords[indices[i + 1]].Y;