diff --git a/src/sp65/pcx.c b/src/sp65/pcx.c index d721671b3..489c65c5d 100644 --- a/src/sp65/pcx.c +++ b/src/sp65/pcx.c @@ -153,11 +153,12 @@ static PCXHeader* ReadPCXHeader (FILE* F, const char* Name) P->Compressed, Name); } /* We support: - ** - one plane with either 1 or 8 bits per pixel - ** - three planes with 8 bits per pixel - ** - four planes with 8 bits per pixel (does this exist?) - */ + * - one plane with either 1, 4 or 8 bits per pixel + * - three planes with 8 bits per pixel + * - four planes with 8 bits per pixel (does this exist?) + */ if (!((P->BPP == 1 && P->Planes == 1) || + (P->BPP == 4 && P->Planes == 1) || (P->BPP == 8 && (P->Planes == 1 || P->Planes == 3 || P->Planes == 4)))) { /* We could support others, but currently we don't */ Error ("Unsupported PCX format: %u planes, %u bpp in PCX file '%s'", @@ -204,11 +205,14 @@ static void DumpPCXHeader (const PCXHeader* P, const char* Name) static void ReadPlane (FILE* F, PCXHeader* P, unsigned char* L) /* Read one (possibly compressed) plane from the file */ { - if (P->Compressed) { + unsigned i; + if (P->Compressed) { /* Uncompress RLE data */ - unsigned Remaining = P->Width; - while (Remaining) { + signed Remaining = P->BytesPerPlane; + signed WidthCounter = P->Width; + + while (Remaining > 0) { unsigned char C; @@ -224,21 +228,111 @@ static void ReadPlane (FILE* F, PCXHeader* P, unsigned char* L) } /* Write the data to the buffer */ - if (C > Remaining) { - C = Remaining; - } - memset (L, B, C); - - /* Bump counters */ - L += C; - Remaining -= C; - + switch (P->BPP) { + default: + for (i = 0; i < C; i++) { + if (WidthCounter > 0) { + *L = B; + L += 1; + WidthCounter -= 1; + } + Remaining -= 1; + } + break; + case 4: + for (i = 0; i < C; i++) { + if (WidthCounter > 0) { + *L = B >> 4; + L += 1; + WidthCounter -= 1; + } + if (WidthCounter > 0) { + *L = B & 15; + L += 1; + WidthCounter -= 1; + } + Remaining -= 1; + } + break; + case 2: + for (i = 0; i < C; i++) { + if (WidthCounter > 0) { + *L = (B >> 6) & 3; + L += 1; + WidthCounter -= 1; + } + if (WidthCounter > 0) { + *L = (B >> 4) & 3; + L += 1; + WidthCounter -= 1; + } + if (WidthCounter > 0) { + *L = (B >> 2) & 3; + L += 1; + WidthCounter -= 1; + } + if (WidthCounter > 0) { + *L = B & 3; + L += 1; + WidthCounter -= 1; + } + Remaining -= 1; + } + break; + case 1: + for (i = 0; i < C; i++) { + if (WidthCounter > 0) { + *L = (B >> 7) & 1; + L += 1; + WidthCounter -= 1; + } + if (WidthCounter > 0) { + *L = (B >> 6) & 1; + L += 1; + WidthCounter -= 1; + } + if (WidthCounter > 0) { + *L = (B >> 5) & 1; + L += 1; + WidthCounter -= 1; + } + if (WidthCounter > 0) { + *L = (B >> 4) & 1; + L += 1; + WidthCounter -= 1; + } + if (WidthCounter > 0) { + *L = (B >> 3) & 1; + L += 1; + WidthCounter -= 1; + } + if (WidthCounter > 0) { + *L = (B >> 2) & 1; + L += 1; + WidthCounter -= 1; + } + if (WidthCounter > 0) { + *L = (B >> 1) & 1; + L += 1; + WidthCounter -= 1; + } + if (WidthCounter > 0) { + *L = B & 1; + L += 1; + WidthCounter -= 1; + } + Remaining -= 1; + } + break; + } } } else { - /* Just read one line */ - ReadData (F, L, P->Width); - + if (P->BPP == 4) { + printf("Not implemented\n"); + } else { + ReadData (F, L, P->Width); + } } } @@ -309,25 +403,42 @@ Bitmap* ReadPCXFile (const Collection* A) } } else { - /* One plane with 8bpp is indexed */ - for (Y = 0, Px = B->Data; Y < P->Height; ++Y) { + if (P->BPP == 4) { + /* One plane with 8bpp is indexed */ + for (Y = 0, Px = B->Data; Y < P->Height; ++Y) { - /* Read the plane */ - ReadPlane (F, P, L); + /* Read the plane */ + ReadPlane (F, P, L); - /* Create pixels */ - for (X = 0; X < P->Width; ++X, ++Px) { - if (L[X] > MaxIdx) { - MaxIdx = L[X]; + /* Create pixels */ + for (X = 0; X < P->Width; ++X, ++Px) { + if (L[X] > MaxIdx) { + MaxIdx = L[X]; + } + Px->Index = L[X]; + } + } + } else { + /* One plane with 8bpp is indexed */ + for (Y = 0, Px = B->Data; Y < P->Height; ++Y) { + + /* Read the plane */ + ReadPlane (F, P, L); + + /* Create pixels */ + for (X = 0; X < P->Width; ++X, ++Px) { + if (L[X] > MaxIdx) { + MaxIdx = L[X]; + } + Px->Index = L[X]; } - Px->Index = L[X]; } } } /* One plane means we have a palette which is either part of the header - ** or follows. - */ + * or follows. + */ if (P->PalInfo == 0) { /* Create the monochrome palette */