Mercurial > hg > dmlib
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 { |