mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 08:44:19 -04:00
pnmimage: Support reading of .bmp files with RLE8 compression
This commit is contained in:
parent
d5263b597b
commit
79a60688ce
@ -92,19 +92,7 @@ BMPlenrgbtable(int classv, unsigned long bitcount)
|
|||||||
pm_error(er_internal, "BMPlenrgbtable");
|
pm_error(er_internal, "BMPlenrgbtable");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
switch (classv)
|
lenrgb = (classv == C_OS2) ? 3 : 4;
|
||||||
{
|
|
||||||
case C_WIN:
|
|
||||||
lenrgb = 4;
|
|
||||||
break;
|
|
||||||
case C_OS2:
|
|
||||||
lenrgb = 3;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
pm_error(er_internal, "BMPlenrgbtable");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (1 << bitcount) * lenrgb;
|
return (1 << bitcount) * lenrgb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +55,7 @@ public:
|
|||||||
unsigned long offBits;
|
unsigned long offBits;
|
||||||
|
|
||||||
unsigned short cBitCount;
|
unsigned short cBitCount;
|
||||||
|
unsigned short cCompression;
|
||||||
int indexed;
|
int indexed;
|
||||||
int classv;
|
int classv;
|
||||||
|
|
||||||
|
@ -177,6 +177,7 @@ BMPreadinfoheader(
|
|||||||
unsigned long *pcx,
|
unsigned long *pcx,
|
||||||
unsigned long *pcy,
|
unsigned long *pcy,
|
||||||
unsigned short *pcBitCount,
|
unsigned short *pcBitCount,
|
||||||
|
unsigned short *pcCompression,
|
||||||
int *pclassv)
|
int *pclassv)
|
||||||
{
|
{
|
||||||
unsigned long cbFix;
|
unsigned long cbFix;
|
||||||
@ -185,6 +186,7 @@ BMPreadinfoheader(
|
|||||||
unsigned long cx = 0;
|
unsigned long cx = 0;
|
||||||
unsigned long cy = 0;
|
unsigned long cy = 0;
|
||||||
unsigned short cBitCount = 0;
|
unsigned short cBitCount = 0;
|
||||||
|
unsigned long cCompression = 0;
|
||||||
int classv = 0;
|
int classv = 0;
|
||||||
|
|
||||||
cbFix = GetLong(fp);
|
cbFix = GetLong(fp);
|
||||||
@ -229,7 +231,9 @@ BMPreadinfoheader(
|
|||||||
* for the required total.
|
* for the required total.
|
||||||
*/
|
*/
|
||||||
if (classv != C_OS2) {
|
if (classv != C_OS2) {
|
||||||
for (int i = 0; i < (int)cbFix - 16; i += 4) {
|
cCompression = GetLong(fp);
|
||||||
|
|
||||||
|
for (int i = 0; i < (int)cbFix - 20; i += 4) {
|
||||||
GetLong(fp);
|
GetLong(fp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -273,11 +277,13 @@ BMPreadinfoheader(
|
|||||||
pm_message("cy: %d", cy);
|
pm_message("cy: %d", cy);
|
||||||
pm_message("cPlanes: %d", cPlanes);
|
pm_message("cPlanes: %d", cPlanes);
|
||||||
pm_message("cBitCount: %d", cBitCount);
|
pm_message("cBitCount: %d", cBitCount);
|
||||||
|
pm_message("cCompression: %d", cCompression);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
*pcx = cx;
|
*pcx = cx;
|
||||||
*pcy = cy;
|
*pcy = cy;
|
||||||
*pcBitCount = cBitCount;
|
*pcBitCount = cBitCount;
|
||||||
|
*pcCompression = cCompression;
|
||||||
*pclassv = classv;
|
*pclassv = classv;
|
||||||
|
|
||||||
*ppos += cbFix;
|
*ppos += cbFix;
|
||||||
@ -401,45 +407,84 @@ BMPreadbits(xel *array, xelval *alpha_array,
|
|||||||
unsigned long cx,
|
unsigned long cx,
|
||||||
unsigned long cy,
|
unsigned long cy,
|
||||||
unsigned short cBitCount,
|
unsigned short cBitCount,
|
||||||
int /* classv */,
|
unsigned long cCompression,
|
||||||
int indexed,
|
int indexed,
|
||||||
pixval *R,
|
pixval *R,
|
||||||
pixval *G,
|
pixval *G,
|
||||||
pixval *B)
|
pixval *B)
|
||||||
{
|
{
|
||||||
long y;
|
long y;
|
||||||
|
|
||||||
readto(fp, ppos, offBits);
|
readto(fp, ppos, offBits);
|
||||||
|
|
||||||
if(cBitCount > 24 && cBitCount != 32)
|
if (cBitCount > 24 && cBitCount != 32) {
|
||||||
{
|
pm_error("%s: cannot handle cBitCount: %d", ifname, cBitCount);
|
||||||
pm_error("%s: cannot handle cBitCount: %d"
|
}
|
||||||
,ifname
|
|
||||||
,cBitCount);
|
if (cCompression == 1) {
|
||||||
|
// RLE8 compression
|
||||||
|
xel *row = array + (cy - 1) * cx;
|
||||||
|
xel *p = row;
|
||||||
|
unsigned long nbyte = 0;
|
||||||
|
while (true) {
|
||||||
|
int first = GetByte(fp);
|
||||||
|
int second = GetByte(fp);
|
||||||
|
nbyte += 2;
|
||||||
|
|
||||||
|
if (first != 0) {
|
||||||
|
// Repeated index.
|
||||||
|
for (int i = 0; i < first; ++i) {
|
||||||
|
PPM_ASSIGN(*p, R[second], G[second], B[second]);
|
||||||
|
++p;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/*
|
else if (second == 0) {
|
||||||
* The picture is stored bottom line first, top line last
|
// End of line.
|
||||||
*/
|
row -= cx;
|
||||||
|
p = row;
|
||||||
for (y = (long)cy - 1; y >= 0; y--)
|
}
|
||||||
{
|
else if (second == 1) {
|
||||||
int rc;
|
// End of image.
|
||||||
rc = BMPreadrow(fp, ppos, array + y*cx, alpha_array + y*cx, cx, cBitCount, indexed, R, G, B);
|
break;
|
||||||
if(rc == -1)
|
}
|
||||||
{
|
else if (second == 2) {
|
||||||
pm_error("%s: couldn't read row %d"
|
// Delta.
|
||||||
,ifname
|
int xoffset = GetByte(fp);
|
||||||
,y);
|
int yoffset = GetByte(fp);
|
||||||
}
|
nbyte += 2;
|
||||||
if(rc%4)
|
row -= cx * yoffset;
|
||||||
{
|
p += xoffset - cx * yoffset;
|
||||||
pm_error("%s: row had bad number of bytes: %d"
|
}
|
||||||
,ifname
|
else {
|
||||||
,rc);
|
// Absolute run.
|
||||||
}
|
for (int i = 0; i < second; ++i) {
|
||||||
|
int v = GetByte(fp);
|
||||||
|
++nbyte;
|
||||||
|
PPM_ASSIGN(*p, R[v], G[v], B[v]);
|
||||||
|
++p;
|
||||||
}
|
}
|
||||||
|
nbyte += second;
|
||||||
|
if (second % 2) {
|
||||||
|
// Pad to 16-bit boundary.
|
||||||
|
GetByte(fp);
|
||||||
|
++nbyte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*ppos += nbyte;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// The picture is stored bottom line first, top line last
|
||||||
|
for (y = (long)cy - 1; y >= 0; y--) {
|
||||||
|
int rc = BMPreadrow(fp, ppos, array + y*cx, alpha_array + y*cx, cx, cBitCount, indexed, R, G, B);
|
||||||
|
if (rc == -1) {
|
||||||
|
pm_error("%s: couldn't read row %d", ifname, y);
|
||||||
|
}
|
||||||
|
if (rc % 4) {
|
||||||
|
pm_error("%s: row had bad number of bytes: %d", ifname, rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -474,7 +519,7 @@ Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number) :
|
|||||||
pos = 0;
|
pos = 0;
|
||||||
|
|
||||||
BMPreadfileheader(file, &pos, &offBits);
|
BMPreadfileheader(file, &pos, &offBits);
|
||||||
BMPreadinfoheader(file, &pos, &cx, &cy, &cBitCount, &classv);
|
BMPreadinfoheader(file, &pos, &cx, &cy, &cBitCount, &cCompression, &classv);
|
||||||
|
|
||||||
if (offBits != BMPoffbits(classv, cBitCount)) {
|
if (offBits != BMPoffbits(classv, cBitCount)) {
|
||||||
pnmimage_bmp_cat.warning()
|
pnmimage_bmp_cat.warning()
|
||||||
@ -523,9 +568,10 @@ Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number) :
|
|||||||
int PNMFileTypeBMP::Reader::
|
int PNMFileTypeBMP::Reader::
|
||||||
read_data(xel *array, xelval *alpha_array) {
|
read_data(xel *array, xelval *alpha_array) {
|
||||||
BMPreadbits(array, alpha_array, _file, &pos, offBits, _x_size, _y_size,
|
BMPreadbits(array, alpha_array, _file, &pos, offBits, _x_size, _y_size,
|
||||||
cBitCount, classv, indexed, R, G, B);
|
cBitCount, cCompression, indexed, R, G, B);
|
||||||
|
|
||||||
if (pos != BMPlenfile(classv, cBitCount, _x_size, _y_size)) {
|
if (cCompression != 1 &&
|
||||||
|
pos != BMPlenfile(classv, cBitCount, _x_size, _y_size)) {
|
||||||
pnmimage_bmp_cat.warning()
|
pnmimage_bmp_cat.warning()
|
||||||
<< "Read " << pos << " bytes, expected to read "
|
<< "Read " << pos << " bytes, expected to read "
|
||||||
<< BMPlenfile(classv, cBitCount, _x_size, _y_size) << " bytes\n";
|
<< BMPlenfile(classv, cBitCount, _x_size, _y_size) << " bytes\n";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user