comparison tools/libgfx.c @ 1895:eb03869a10d3

Clean up the IFF reader and make it more robust.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 26 Jun 2018 03:09:01 +0300
parents 2e3f188c6bf0
children f80b2dc77c30
comparison
equal deleted inserted replaced
1894:2e3f188c6bf0 1895:eb03869a10d3
1399 { 1399 {
1400 Uint32 id; 1400 Uint32 id;
1401 Uint32 size; 1401 Uint32 size;
1402 int count; 1402 int count;
1403 char idStr[6]; 1403 char idStr[6];
1404 off_t offs;
1404 } DMIFFChunk; 1405 } DMIFFChunk;
1405 1406
1406 1407
1407 typedef struct 1408 typedef struct
1408 { 1409 {
1466 return dmError(DMERR_FREAD, 1467 return dmError(DMERR_FREAD,
1467 "IFF: Could not read IFF chunk header.\n"); 1468 "IFF: Could not read IFF chunk header.\n");
1468 } 1469 }
1469 else 1470 else
1470 { 1471 {
1472 chunk->offs = dmftell(fp);
1471 dmMakeIFFChunkIDStr(chunk); 1473 dmMakeIFFChunkIDStr(chunk);
1472 return DMERR_OK; 1474 return DMERR_OK;
1473 } 1475 }
1474 } 1476 }
1475 1477
1476 1478
1477 static int dmSkipIFFChunkRest(DMResource *fp, const DMIFFChunk *chunk, const Uint32 used) 1479 static int dmSkipIFFChunkRest(DMResource *fp, const DMIFFChunk *chunk)
1478 { 1480 {
1479 if (chunk->size > used) 1481 off_t read = dmftell(fp) - chunk->offs;
1482 if (chunk->size > read)
1480 { 1483 {
1481 dmMsg(4, "IFF: Skipping %d bytes (%d of %d consumed)\n", 1484 dmMsg(4, "IFF: Skipping %d bytes (%d of %d consumed)\n",
1482 chunk->size - used, used, chunk->size); 1485 chunk->size - read, read, chunk->size);
1483 1486
1484 if (dmfseek(fp, chunk->size - used, SEEK_CUR) != 0) 1487 if (dmfseek(fp, chunk->size - read, SEEK_CUR) != 0)
1485 { 1488 {
1486 return dmError(DMERR_FSEEK, 1489 return dmError(DMERR_FSEEK,
1487 "IFF: Failed to skip chunk end.\n"); 1490 "IFF: Failed to skip chunk end.\n");
1488 } 1491 }
1489 else 1492 else
1579 for (int xc = 0; xc < width; xc++) 1582 for (int xc = 0; xc < width; xc++)
1580 dst[xc] |= dmDecodeBit(src, xc) << nplane; 1583 dst[xc] |= dmDecodeBit(src, xc) << nplane;
1581 } 1584 }
1582 1585
1583 1586
1584 static int dmDecodeILBMBody(DMResource *fp, DMIFF *iff, DMImage *img, Uint32 *read) 1587 static int dmDecodeILBMBody(DMResource *fp, DMIFF *iff, DMImage *img)
1585 { 1588 {
1586 Uint8 *buf; 1589 Uint8 *buf;
1587 size_t bufLen; 1590 size_t bufLen;
1588 int res = DMERR_OK; 1591 int res = DMERR_OK;
1589 const int nplanes = iff->bmhd.nplanes; 1592 const int nplanes = iff->bmhd.nplanes;
1590 1593
1591 *read = 0;
1592
1593 // Allocate planar decoding buffer 1594 // Allocate planar decoding buffer
1594 bufLen = ((img->width + 15) / 16) * 2; 1595 bufLen = ((img->width + 15) / 16) * 2;
1595 if ((buf = dmMalloc(bufLen)) == NULL) 1596 if ((buf = dmMalloc(bufLen)) == NULL)
1596 return DMERR_MALLOC; 1597 return DMERR_MALLOC;
1597 1598
1615 goto error; 1616 goto error;
1616 } 1617 }
1617 1618
1618 // Decode bitplane 1619 // Decode bitplane
1619 dmDecodeBitPlane(dp, buf, img->width, plane); 1620 dmDecodeBitPlane(dp, buf, img->width, plane);
1620
1621 *read += bufLen;
1622 } 1621 }
1623 1622
1624 // Read mask data 1623 // Read mask data
1625 if (iff->bmhd.masking == IFF_MASK_HAS_MASK) 1624 if (iff->bmhd.masking == IFF_MASK_HAS_MASK)
1626 { 1625 {
1639 1638
1640 // Black out any pixels with mask bit 0 1639 // Black out any pixels with mask bit 0
1641 if (!data) 1640 if (!data)
1642 dp[xc] = img->ctransp < 0 ? 0 : img->ctransp; 1641 dp[xc] = img->ctransp < 0 ? 0 : img->ctransp;
1643 } 1642 }
1644
1645 *read += bufLen;
1646 } 1643 }
1647 } 1644 }
1648 1645
1649 error: 1646 error:
1650 dmFree(buf); 1647 dmFree(buf);
1651 return res; 1648 return res;
1652 } 1649 }
1653 1650
1654 1651
1655 static int dmDecodePBMBody(DMResource *fp, DMIFF *iff, DMImage *img, Uint32 *read) 1652 static int dmDecodePBMBody(DMResource *fp, DMIFF *iff, DMImage *img)
1656 { 1653 {
1657 int res = DMERR_OK;
1658
1659 *read = 0;
1660
1661 // Decode the chunk
1662 for (int yc = 0; yc < img->height; yc++) 1654 for (int yc = 0; yc < img->height; yc++)
1663 { 1655 {
1664 Uint8 *dp = img->data + (yc * img->pitch); 1656 if (!dmIFFReadOneRow(fp, iff, img->data + (yc * img->pitch), img->width))
1665 1657 {
1666 if (!dmIFFReadOneRow(fp, iff, dp, img->width)) 1658 return dmError(DMERR_FREAD,
1667 { 1659 "IFF: Error reading PBM image row #%d.\n", yc);
1668 res = dmError(DMERR_FREAD, 1660 }
1669 "IFF: Error in reading image row #%d.\n", yc); 1661 }
1670 goto error; 1662
1671 } 1663 return DMERR_OK;
1672
1673 *read += img->width;
1674 }
1675
1676 error:
1677 return res;
1678 } 1664 }
1679 1665
1680 1666
1681 int dmReadIFFImage(DMResource *fp, DMImage **pimg) 1667 int dmReadIFFImage(DMResource *fp, DMImage **pimg)
1682 { 1668 {
1683 DMIFFChunk chunk; 1669 DMIFFChunk chunk;
1684 DMIFF iff; 1670 DMIFF iff;
1685 Uint32 read, idsig; 1671 Uint32 idsig;
1686 BOOL parsed = FALSE, planar; 1672 BOOL parsed = FALSE, planar;
1687 int res = DMERR_OK; 1673 int res = DMERR_OK;
1688 1674
1689 dmMemset(&iff, 0, sizeof(iff)); 1675 dmMemset(&iff, 0, sizeof(iff));
1690 1676
1709 1695
1710 planar = (idsig == IFF_ID_ILBM); 1696 planar = (idsig == IFF_ID_ILBM);
1711 1697
1712 while (!parsed && !dmfeof(fp)) 1698 while (!parsed && !dmfeof(fp))
1713 { 1699 {
1700 // Read chunk header
1714 if ((res = dmReadIFFChunkHdr(fp, &chunk)) != DMERR_OK) 1701 if ((res = dmReadIFFChunkHdr(fp, &chunk)) != DMERR_OK)
1715 return res; 1702 return res;
1716 1703
1717 switch (chunk.id) 1704 switch (chunk.id)
1718 { 1705 {
1754 iff.bmhd.masking != IFF_MASK_TRANSP)) 1741 iff.bmhd.masking != IFF_MASK_TRANSP))
1755 { 1742 {
1756 return dmError(DMERR_NOT_SUPPORTED, 1743 return dmError(DMERR_NOT_SUPPORTED,
1757 "IFF: Unsupported features, refusing to load.\n"); 1744 "IFF: Unsupported features, refusing to load.\n");
1758 } 1745 }
1759
1760 if ((res = dmSkipIFFChunkRest(fp, &chunk, sizeof(iff.bmhd))) != DMERR_OK)
1761 return res;
1762 break; 1746 break;
1763 1747
1764 1748
1765 case IFF_ID_CMAP: 1749 case IFF_ID_CMAP:
1766 // Check for multiple occurences of CMAP 1750 // Check for multiple occurences of CMAP
1830 (*pimg)->aspect = (float) iff.bmhd.yasp / (float) iff.bmhd.xasp; 1814 (*pimg)->aspect = (float) iff.bmhd.yasp / (float) iff.bmhd.xasp;
1831 1815
1832 // Decode the body 1816 // Decode the body
1833 if (planar) 1817 if (planar)
1834 { 1818 {
1835 if ((res = dmDecodeILBMBody(fp, &iff, *pimg, &read)) != DMERR_OK) 1819 if ((res = dmDecodeILBMBody(fp, &iff, *pimg)) != DMERR_OK)
1836 return res; 1820 return res;
1837 } 1821 }
1838 else 1822 else
1839 { 1823 {
1840 if ((res = dmDecodePBMBody(fp, &iff, *pimg, &read)) != DMERR_OK) 1824 if ((res = dmDecodePBMBody(fp, &iff, *pimg)) != DMERR_OK)
1841 return res; 1825 return res;
1842 } 1826 }
1843 1827
1844 if ((res = dmSkipIFFChunkRest(fp, &chunk, read)) != DMERR_OK) 1828 if ((res = dmSkipIFFChunkRest(fp, &chunk)) != DMERR_OK)
1845 return res; 1829 return res;
1846 1830
1847 if (iff.chCMAP.count) 1831 if (iff.chCMAP.count)
1848 parsed = TRUE; 1832 parsed = TRUE;
1849 break; 1833 break;
1861 if ((iff.camg & IFF_CAMG_HAM)) 1845 if ((iff.camg & IFF_CAMG_HAM))
1862 { 1846 {
1863 return dmError(DMERR_NOT_SUPPORTED, 1847 return dmError(DMERR_NOT_SUPPORTED,
1864 "IFF: HAM files are not supported.\n"); 1848 "IFF: HAM files are not supported.\n");
1865 } 1849 }
1866
1867 if ((res = dmSkipIFFChunkRest(fp, &chunk, sizeof(Uint32))) != DMERR_OK)
1868 return res;
1869 break; 1850 break;
1870 1851
1871 1852
1872 default: 1853 default:
1873 { 1854 {
1881 } 1862 }
1882 } 1863 }
1883 break; 1864 break;
1884 } 1865 }
1885 1866
1886 if (chunk.size & 1) 1867 if ((res = dmSkipIFFChunkRest(fp, &chunk)) != DMERR_OK)
1887 dmfgetc(fp); 1868 return res;
1888 } 1869 }
1889 1870
1890 // Set colormap after finishing 1871 // Set colormap after finishing
1891 if (iff.pal != NULL && iff.ncolors > 0 && *pimg != NULL) 1872 if (iff.pal != NULL && iff.ncolors > 0 && *pimg != NULL)
1892 { 1873 {