changeset 1609:c29adf5ce240

Convert libgfx file format routines to use DMResource instead of stdio FILE. Also do necessary changes in gfxconv due to these API changes.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 14 May 2018 12:42:24 +0300
parents 7f9fe2a9a87e
children 61246926756a
files tools/gfxconv.c tools/libgfx.c tools/libgfx.h
diffstat 3 files changed, 200 insertions(+), 173 deletions(-) [+]
line wrap: on
line diff
--- a/tools/gfxconv.c	Mon May 14 12:40:57 2018 +0300
+++ b/tools/gfxconv.c	Mon May 14 12:42:24 2018 +0300
@@ -1091,6 +1091,32 @@
 }
 
 
+#define DMCOL(x) (((x) >> 4) & 0xf)
+
+void dmWriteIFFMasterRAWPalette(FILE *fp,
+    const DMImage *img, int ncolors,
+    const char *indent, const char *type)
+{
+    for (int i = 0; i < ncolors; i++)
+    {
+        int color;
+        if (i < img->ncolors)
+        {
+            color = (DMCOL(img->pal[i].r) << 8) |
+                    (DMCOL(img->pal[i].g) << 4) |
+                    (DMCOL(img->pal[i].b));
+        }
+        else
+            color = 0;
+
+        fprintf(fp, "%s%s $%04X\n",
+            indent != NULL ? indent : "\t",
+            type != NULL ? type : "dc.w",
+            color);
+    }
+}
+
+
 int dmWriteImage(const char *filename, DMImage *pimage, DMImageConvSpec *spec, int iformat, BOOL info)
 {
     int res = DMERR_OK;
@@ -1786,6 +1812,7 @@
             {
                 DMImage *inImage = NULL;
                 int res = DMERR_OK;
+                DMResource *fp;
 
                 if (optOutFilename == NULL)
                 {
@@ -1793,13 +1820,21 @@
                     goto error;
                 }
 
+                if ((res = dmf_open_memio(NULL, optInFilename, dataBuf, dataSize, &fp)) != DMERR_OK)
+                {
+                    dmErrorMsg("Could not create MemIO handle for input.\n");
+                    goto error;
+                }
+
                 // Read input
                 DMImageFormat *ifmt = &dmImageFormatList[optInSubFormat];
                 if (ifmt->readFILE != NULL)
-                    res = ifmt->readFILE(inFile, &inImage);
+                    res = ifmt->readFILE(fp, &inImage);
                 else
                     dmErrorMsg("Unsupported input image format for bitmap/image conversion.\n");
 
+                dmf_close(fp);
+
                 if (res != DMERR_OK || inImage == NULL)
                     break;
 
@@ -1831,9 +1866,6 @@
     }
 
 error:
-    if (inFile != NULL)
-        fclose(inFile);
-
     dmFree(dataBufOrig);
     dmC64ImageFree(inC64Image);
     dmC64ImageFree(outC64Image);
--- a/tools/libgfx.c	Mon May 14 12:40:57 2018 +0300
+++ b/tools/libgfx.c	Mon May 14 12:42:24 2018 +0300
@@ -6,7 +6,7 @@
  * Please read file 'COPYING' for information on license and distribution.
  */
 #include "libgfx.h"
-#include "dmfile.h"
+#include "dmresw.h"
 
 #ifdef DM_USE_LIBPNG
 #include <png.h>
@@ -66,11 +66,11 @@
 
 static BOOL dmPutByteFILE(DMBitStreamContext *ctx, const Uint8 val)
 {
-    return fputc(val, (FILE *) ctx->handle) == val;
+    return dmf_write_byte((DMResource *) ctx->handle, val);
 }
 
 
-int dmInitBitStreamFILE(DMBitStreamContext *ctx, FILE *fp)
+int dmInitBitStreamFILE(DMBitStreamContext *ctx, DMResource *fp)
 {
     if (ctx == NULL || fp == NULL)
         return DMERR_NULLPTR;
@@ -147,8 +147,6 @@
 
 BOOL dmPaletteAlloc(DMColor **ppal, int ncolors, int ctransp)
 {
-    int i;
-
     if (ppal == NULL)
         return FALSE;
 
@@ -157,7 +155,7 @@
         return FALSE;
 
     // Set alpha values to max, except for transparent color
-    for (i = 0; i < ncolors; i++)
+    for (int i = 0; i < ncolors; i++)
     {
         (*ppal)[i].a = (i == ctransp) ? 0 : 255;
     }
@@ -177,16 +175,14 @@
 }
 
 
-static BOOL dmReadPaletteData(FILE *fp, DMColor *pal, int ncolors)
+static BOOL dmReadPaletteData(DMResource *fp, DMColor *pal, int ncolors)
 {
-    int i;
-
-    for (i = 0; i < ncolors; i++)
+    for (int i = 0; i < ncolors; i++)
     {
         Uint8 colR, colG, colB;
-        if (!dm_fread_byte(fp, &colR) ||
-            !dm_fread_byte(fp, &colG) ||
-            !dm_fread_byte(fp, &colB))
+        if (!dmf_read_byte(fp, &colR) ||
+            !dmf_read_byte(fp, &colG) ||
+            !dmf_read_byte(fp, &colB))
             return FALSE;
 
         pal[i].r = colR;
@@ -301,37 +297,7 @@
 }
 
 
-#define DMCOL(x) (((x) >> 4) & 0xf)
-
-int dmWriteIFFMasterRAWPalette(FILE *fp,
-    const DMImage *img, int ncolors,
-    const char *indent, const char *type)
-{
-    int i;
-
-    for (i = 0; i < ncolors; i++)
-    {
-        int color;
-        if (i < img->ncolors)
-        {
-            color = (DMCOL(img->pal[i].r) << 8) |
-                    (DMCOL(img->pal[i].g) << 4) |
-                    (DMCOL(img->pal[i].b));
-        }
-        else
-            color = 0;
-
-        fprintf(fp, "%s%s $%04X\n",
-            indent != NULL ? indent : "\t",
-            type != NULL ? type : "dc.w",
-            color);
-    }
-
-    return DMERR_OK;
-}
-
-
-int dmWriteRAWImageFILE(FILE *fp, const DMImage *img, const DMImageConvSpec *spec)
+int dmWriteRAWImageFILE(DMResource *fp, const DMImage *img, const DMImageConvSpec *spec)
 {
     int xc, yc, plane, res;
     DMBitStreamContext bs;
@@ -375,10 +341,10 @@
 
 int dmWriteRAWImage(const char *filename, const DMImage *img, const DMImageConvSpec *spec)
 {
-    FILE *fp;
+    DMResource *fp;
     int res;
 
-    if ((fp = fopen(filename, "wb")) == NULL)
+    if ((res = dmf_open_stdio(filename, "wb", &fp)) != DMERR_OK)
     {
         return dmError(DMERR_FOPEN,
             "RAW: Could not open file '%s' for writing.\n",
@@ -387,30 +353,36 @@
 
     res = dmWriteRAWImageFILE(fp, img, spec);
 
-    fclose(fp);
+    dmf_close(fp);
     return res;
 }
 
 
 static int dmWritePPMRow(void *cbdata, const Uint8 *row, const size_t len)
 {
-    if (fwrite(row, sizeof(Uint8), len, (FILE *) cbdata) == len)
+    if (dmf_write_str((DMResource *) cbdata, row, len))
         return DMERR_OK;
     else
         return DMERR_FWRITE;
 }
 
 
-int dmWritePPMImageFILE(FILE *fp, const DMImage *img, const DMImageConvSpec *spec)
+int dmWritePPMImageFILE(DMResource *fp, const DMImage *img, const DMImageConvSpec *spec)
 {
     DMImageConvSpec tmpSpec;
 
     // Write PPM header
-    fprintf(fp,
+    char *tmp = dm_strdup_printf(
         "P6\n%d %d\n255\n",
         img->width * spec->scaleX,
         img->height * spec->scaleY);
 
+    if (tmp == NULL)
+        return DMERR_MALLOC;
+
+    dmfputs(tmp, fp);
+    dmFree(tmp);
+
     // Write image data
     memcpy(&tmpSpec, spec, sizeof(DMImageConvSpec));
     tmpSpec.format = DM_IFMT_RGB;
@@ -420,11 +392,11 @@
 
 int dmWritePPMImage(const char *filename, const DMImage *img, const DMImageConvSpec *spec)
 {
-    FILE *fp;
+    DMResource *fp;
     int res;
 
     // Create output file
-    if ((fp = fopen(filename, "wb")) == NULL)
+    if ((res = dmf_open_stdio(filename, "wb", &fp)) != DMERR_OK)
     {
         return dmError(DMERR_FOPEN,
             "PPM: could not open file '%s' for writing.\n",
@@ -433,7 +405,7 @@
 
     res = dmWritePPMImageFILE(fp, img, spec);
 
-    fclose(fp);
+    dmf_close(fp);
     return res;
 }
 
@@ -453,7 +425,22 @@
 }
 
 
-int dmWritePNGImageFILE(FILE *fp, const DMImage *img, const DMImageConvSpec *spec)
+static void dmPNGWriteData(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+    DMResource *res = (DMResource *) png_get_io_ptr(png_ptr);
+
+    // XXX TODO: How the fuck does one do error handling here?
+    dmf_write_str(res, data, length);
+}
+
+
+static void dmPNGWriteFlush(png_structp png_ptr)
+{
+    (void) png_ptr;
+}
+
+
+int dmWritePNGImageFILE(DMResource *fp, const DMImage *img, const DMImageConvSpec *spec)
 {
     png_structp png_ptr = NULL;
     png_infop info_ptr = NULL;
@@ -488,7 +475,7 @@
     }
 
     res = DMERR_OK;
-    png_init_io(png_ptr, fp);
+    png_set_write_fn(png_ptr, fp, dmPNGWriteData, dmPNGWriteFlush);
 
     // Write PNG header info
     switch (spec->format)
@@ -564,9 +551,9 @@
 int dmWritePNGImage(const char *filename, const DMImage *img, const DMImageConvSpec *spec)
 {
     int res;
-    FILE *fp;
+    DMResource *fp;
 
-    if ((fp = fopen(filename, "wb")) == NULL)
+    if ((res = dmf_open_stdio(filename, "wb", &fp)) != DMERR_OK)
     {
         return dmError(DMERR_FOPEN,
             "PNG: could not open file '%s' for writing.\n",
@@ -575,12 +562,20 @@
 
     res = dmWritePNGImageFILE(fp, img, spec);
 
-    fclose(fp);
+    dmf_close(fp);
     return res;
 }
 
 
-int dmReadPNGImageFILE(FILE *fp, DMImage **pimg)
+void dmPNGReadData(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+    DMResource *res = (DMResource *) png_get_io_ptr(png_ptr);
+
+    // XXX TODO: How the fuck does one do error handling here?
+    dmf_read_str(res, data, length);
+}
+
+int dmReadPNGImageFILE(DMResource *fp, DMImage **pimg)
 {
     png_structp png_ptr = NULL;
     png_infop info_ptr = NULL;
@@ -620,7 +615,7 @@
         goto error;
     }
 
-    png_init_io(png_ptr, fp);
+    png_set_read_fn(png_ptr, fp, dmPNGReadData);
 
     // Read image information
     png_read_info(png_ptr, info_ptr);
@@ -752,9 +747,9 @@
 int dmReadPNGImage(const char *filename, DMImage **img)
 {
     int res;
-    FILE *fp;
+    DMResource *fp;
 
-    if ((fp = fopen(filename, "rb")) == NULL)
+    if ((res = dmf_open_stdio(filename, "rb", &fp)) != DMERR_OK)
     {
         return dmError(DMERR_FOPEN,
             "PNG: Could not open file '%s' for reading.\n",
@@ -763,7 +758,7 @@
 
     res = dmReadPNGImageFILE(fp, img);
 
-    fclose(fp);
+    dmf_close(fp);
     return res;
 }
 #endif
@@ -806,7 +801,7 @@
     DMPCXHeader *header;
     Uint8 *buf;
     size_t bufLen, bufOffs;
-    FILE *fp;
+    DMResource *fp;
 } DMPCXData;
 
 
@@ -821,7 +816,7 @@
 {
     BOOL ret = TRUE;
     if (pcx->bufOffs > 0)
-        ret = fwrite(pcx->buf, sizeof(Uint8), pcx->bufOffs, pcx->fp) == pcx->bufOffs;
+        ret = dmf_write_str(pcx->fp, pcx->buf, pcx->bufOffs);
 
     pcx->bufOffs = 0;
     return ret;
@@ -899,7 +894,7 @@
 }
 
 
-int dmWritePCXImageFILE(FILE *fp, const DMImage *img, const DMImageConvSpec *pspec)
+int dmWritePCXImageFILE(DMResource *fp, const DMImage *img, const DMImageConvSpec *pspec)
 {
     DMPCXData pcx;
     DMPCXHeader hdr;
@@ -974,42 +969,42 @@
     }
 
     // Write PCX header
-    if (!dm_fwrite_byte(pcx.fp, hdr.manufacturer) ||
-        !dm_fwrite_byte(pcx.fp, hdr.version) ||
-        !dm_fwrite_byte(pcx.fp, hdr.encoding) ||
-        !dm_fwrite_byte(pcx.fp, hdr.bitsPerPlane))
+    if (!dmf_write_byte(pcx.fp, hdr.manufacturer) ||
+        !dmf_write_byte(pcx.fp, hdr.version) ||
+        !dmf_write_byte(pcx.fp, hdr.encoding) ||
+        !dmf_write_byte(pcx.fp, hdr.bitsPerPlane))
     {
         res = dmError(DMERR_FWRITE,
             "PCX: Could not write basic header data.\n");
         goto error;
     }
 
-    if (!dm_fwrite_le16(pcx.fp, hdr.xmin) ||
-        !dm_fwrite_le16(pcx.fp, hdr.ymin) ||
-        !dm_fwrite_le16(pcx.fp, hdr.xmax) ||
-        !dm_fwrite_le16(pcx.fp, hdr.ymax) ||
-        !dm_fwrite_le16(pcx.fp, hdr.hres) ||
-        !dm_fwrite_le16(pcx.fp, hdr.vres))
+    if (!dmf_write_le16(pcx.fp, hdr.xmin) ||
+        !dmf_write_le16(pcx.fp, hdr.ymin) ||
+        !dmf_write_le16(pcx.fp, hdr.xmax) ||
+        !dmf_write_le16(pcx.fp, hdr.ymax) ||
+        !dmf_write_le16(pcx.fp, hdr.hres) ||
+        !dmf_write_le16(pcx.fp, hdr.vres))
     {
         res = dmError(DMERR_FWRITE,
             "PCX: Could not write image dimensions.\n");
         goto error;
     }
 
-    if (!dm_fwrite_str(pcx.fp, (Uint8 *) &hdr.colorMap, sizeof(hdr.colorMap)))
+    if (!dmf_write_str(pcx.fp, (Uint8 *) &hdr.colorMap, sizeof(hdr.colorMap)))
     {
         res = dmError(DMERR_FWRITE,
             "PCX: Could not write colormap.\n");
         goto error;
     }
 
-    if (!dm_fwrite_byte(pcx.fp, hdr.reserved) ||
-        !dm_fwrite_byte(pcx.fp, hdr.nplanes) ||
-        !dm_fwrite_le16(pcx.fp, hdr.bpl) ||
-        !dm_fwrite_le16(pcx.fp, hdr.palInfo) ||
-        !dm_fwrite_le16(pcx.fp, hdr.hScreenSize) ||
-        !dm_fwrite_le16(pcx.fp, hdr.vScreenSize) ||
-        !dm_fwrite_str(pcx.fp, (Uint8 *) &hdr.filler, sizeof(hdr.filler)))
+    if (!dmf_write_byte(pcx.fp, hdr.reserved) ||
+        !dmf_write_byte(pcx.fp, hdr.nplanes) ||
+        !dmf_write_le16(pcx.fp, hdr.bpl) ||
+        !dmf_write_le16(pcx.fp, hdr.palInfo) ||
+        !dmf_write_le16(pcx.fp, hdr.hScreenSize) ||
+        !dmf_write_le16(pcx.fp, hdr.vScreenSize) ||
+        !dmf_write_str(pcx.fp, (Uint8 *) &hdr.filler, sizeof(hdr.filler)))
     {
         res = dmError(DMERR_FWRITE,
             "PCX: Could not write header remainder.\n");
@@ -1025,13 +1020,13 @@
         int i;
         dmMsg(2, "PCX: Writing palette of %d active entries.\n", img->ncolors);
 
-        dm_fwrite_byte(pcx.fp, 0x0C);
+        dmf_write_byte(pcx.fp, 0x0C);
 
         for (i = 0; i < img->ncolors; i++)
         {
-            if (!dm_fwrite_byte(pcx.fp, img->pal[i].r) ||
-                !dm_fwrite_byte(pcx.fp, img->pal[i].g) ||
-                !dm_fwrite_byte(pcx.fp, img->pal[i].b))
+            if (!dmf_write_byte(pcx.fp, img->pal[i].r) ||
+                !dmf_write_byte(pcx.fp, img->pal[i].g) ||
+                !dmf_write_byte(pcx.fp, img->pal[i].b))
             {
                 res = dmError(DMERR_FWRITE,
                     "PCX: Could not write palette data.\n");
@@ -1042,9 +1037,9 @@
         // Pad the palette, if necessary
         for (; i < 256; i++)
         {
-            if (!dm_fwrite_byte(pcx.fp, 0) ||
-                !dm_fwrite_byte(pcx.fp, 0) ||
-                !dm_fwrite_byte(pcx.fp, 0))
+            if (!dmf_write_byte(pcx.fp, 0) ||
+                !dmf_write_byte(pcx.fp, 0) ||
+                !dmf_write_byte(pcx.fp, 0))
             {
                 res = dmError(DMERR_FWRITE,
                     "PCX: Could not write palette data.\n");
@@ -1061,10 +1056,10 @@
 
 int dmWritePCXImage(const char *filename, const DMImage *img, const DMImageConvSpec *spec)
 {
-    FILE *fp;
+    DMResource *fp;
     int res;
 
-    if ((fp = fopen(filename, "wb")) == NULL)
+    if ((res = dmf_open_stdio(filename, "wb", &fp)) != DMERR_OK)
     {
         return dmError(DMERR_FOPEN,
             "PCX: Could not open file '%s' for writing.\n",
@@ -1073,12 +1068,12 @@
 
     res = dmWritePCXImageFILE(fp, img, spec);
 
-    fclose(fp);
+    dmf_close(fp);
     return res;
 }
 
 
-static BOOL dmPCXDecodeRLERow(FILE *fp, Uint8 *buf, const size_t bufLen)
+static BOOL dmPCXDecodeRLERow(DMResource *fp, Uint8 *buf, const size_t bufLen)
 {
     size_t offs = 0;
     do
@@ -1086,7 +1081,7 @@
         int count;
         Uint8 data;
 
-        if (!dm_fread_byte(fp, &data))
+        if (!dmf_read_byte(fp, &data))
             return FALSE;
 
         if ((data & 0xC0) == 0xC0)
@@ -1115,7 +1110,7 @@
                 }
             }
 
-            if (!skip && !dm_fread_byte(fp, &data))
+            if (!skip && !dmf_read_byte(fp, &data))
                 return FALSE;
         }
         else
@@ -1134,7 +1129,7 @@
 }
 
 
-int dmReadPCXImageFILE(FILE *fp, DMImage **pimg)
+int dmReadPCXImageFILE(DMResource *fp, DMImage **pimg)
 {
     DMImage *img;
     DMPCXData pcx;
@@ -1144,24 +1139,24 @@
     pcx.buf = NULL;
 
     // Read PCX header
-    if (!dm_fread_byte(fp, &hdr.manufacturer) ||
-        !dm_fread_byte(fp, &hdr.version) ||
-        !dm_fread_byte(fp, &hdr.encoding) ||
-        !dm_fread_byte(fp, &hdr.bitsPerPlane) ||
-        !dm_fread_le16(fp, &hdr.xmin) ||
-        !dm_fread_le16(fp, &hdr.ymin) ||
-        !dm_fread_le16(fp, &hdr.xmax) ||
-        !dm_fread_le16(fp, &hdr.ymax) ||
-        !dm_fread_le16(fp, &hdr.hres) ||
-        !dm_fread_le16(fp, &hdr.vres) ||
-        !dm_fread_str(fp, (Uint8 *) &hdr.colorMap, sizeof(hdr.colorMap)) ||
-        !dm_fread_byte(fp, &hdr.reserved) ||
-        !dm_fread_byte(fp, &hdr.nplanes) ||
-        !dm_fread_le16(fp, &hdr.bpl) ||
-        !dm_fread_le16(fp, &hdr.palInfo) ||
-        !dm_fread_le16(fp, &hdr.hScreenSize) ||
-        !dm_fread_le16(fp, &hdr.vScreenSize) ||
-        !dm_fread_str(fp, (Uint8 *) &hdr.filler, sizeof(hdr.filler)))
+    if (!dmf_read_byte(fp, &hdr.manufacturer) ||
+        !dmf_read_byte(fp, &hdr.version) ||
+        !dmf_read_byte(fp, &hdr.encoding) ||
+        !dmf_read_byte(fp, &hdr.bitsPerPlane) ||
+        !dmf_read_le16(fp, &hdr.xmin) ||
+        !dmf_read_le16(fp, &hdr.ymin) ||
+        !dmf_read_le16(fp, &hdr.xmax) ||
+        !dmf_read_le16(fp, &hdr.ymax) ||
+        !dmf_read_le16(fp, &hdr.hres) ||
+        !dmf_read_le16(fp, &hdr.vres) ||
+        !dmf_read_str(fp, (Uint8 *) &hdr.colorMap, sizeof(hdr.colorMap)) ||
+        !dmf_read_byte(fp, &hdr.reserved) ||
+        !dmf_read_byte(fp, &hdr.nplanes) ||
+        !dmf_read_le16(fp, &hdr.bpl) ||
+        !dmf_read_le16(fp, &hdr.palInfo) ||
+        !dmf_read_le16(fp, &hdr.hScreenSize) ||
+        !dmf_read_le16(fp, &hdr.vScreenSize) ||
+        !dmf_read_str(fp, (Uint8 *) &hdr.filler, sizeof(hdr.filler)))
     {
         res = dmError(DMERR_FREAD,
             "PCX: Could not read image header data.\n");
@@ -1181,7 +1176,7 @@
     {
         dmMsg(2,
             "PCX: Probably invalid combination of nplanes and bpp, attempting to fix ..\n");
-        
+
         hdr.bitsPerPlane = 1;
     }
 
@@ -1257,7 +1252,7 @@
                 "PCX: Error decoding RLE compressed data.\n");
             goto error;
         }
-        
+
         // Decode bitplanes
         switch (hdr.bitsPerPlane)
         {
@@ -1311,7 +1306,7 @@
         Uint8 tmpb;
         BOOL read;
 
-        if (!dm_fread_byte(fp, &tmpb) || tmpb != 0x0C)
+        if (!dmf_read_byte(fp, &tmpb) || tmpb != 0x0C)
         {
             read = FALSE;
             ncolors = DMPCX_PAL_COLORS;
@@ -1362,10 +1357,10 @@
 
 int dmReadPCXImage(const char *filename, DMImage **pimg)
 {
-    FILE *fp;
+    DMResource *fp;
     int res;
 
-    if ((fp = fopen(filename, "rb")) == NULL)
+    if ((res = dmf_open_stdio(filename, "rb", &fp)) != DMERR_OK)
     {
         return dmError(DMERR_FOPEN,
             "PCX: Could not open file '%s' for reading.\n",
@@ -1374,7 +1369,7 @@
 
     res = dmReadPCXImageFILE(fp, pimg);
 
-    fclose(fp);
+    dmf_close(fp);
     return res;
 }
 
@@ -1433,10 +1428,10 @@
 } DMIFF;
 
 
-static BOOL dmReadIFFChunk(FILE *fp, DMIFFChunk *chunk)
+static BOOL dmReadIFFChunk(DMResource *fp, DMIFFChunk *chunk)
 {
-    if (!dm_fread_be32(fp, &chunk->id) ||
-        !dm_fread_be32(fp, &chunk->size))
+    if (!dmf_read_be32(fp, &chunk->id) ||
+        !dmf_read_be32(fp, &chunk->size))
     {
         dmError(DMERR_FREAD,
             "ILBM: Could not read IFF chunk header.\n");
@@ -1456,14 +1451,14 @@
     return chunk->str;
 }
 
-static int dmSkipIFFChunkRest(FILE *fp, const DMIFFChunk *chunk, const Uint32 used)
+static int dmSkipIFFChunkRest(DMResource *fp, const DMIFFChunk *chunk, const Uint32 used)
 {
     if (chunk->size > used)
     {
         dmMsg(4, "ILBM: Skipping %d bytes (%d of %d consumed)\n",
             chunk->size - used, used, chunk->size);
 
-        if (fseeko(fp, chunk->size - used, SEEK_CUR) != 0)
+        if (dmfseek(fp, chunk->size - used, SEEK_CUR) != 0)
         {
             return dmError(DMERR_FSEEK,
                 "ILBM: Failed to skip chunk end.\n");
@@ -1497,7 +1492,7 @@
 }
 
 
-static BOOL dmIFFDecodeByteRun1Row(FILE *fp, Uint8 *buf, const size_t bufLen)
+static BOOL dmIFFDecodeByteRun1Row(DMResource *fp, Uint8 *buf, const size_t bufLen)
 {
     size_t offs = 0;
     do
@@ -1505,19 +1500,19 @@
         Sint8 dcount;
         Uint8 data;
 
-        if (!dm_fread_byte(fp, (Uint8 *) &dcount))
+        if (!dmf_read_byte(fp, (Uint8 *) &dcount))
             return FALSE;
 
         if (dcount == -128)
         {
-            if (!dm_fread_byte(fp, &data))
+            if (!dmf_read_byte(fp, &data))
                 return FALSE;
         }
         else
         if (dcount < 0)
         {
             int count = (-dcount) + 1;
-            if (!dm_fread_byte(fp, &data))
+            if (!dmf_read_byte(fp, &data))
                 return FALSE;
 
             while (count-- && offs < bufLen)
@@ -1528,7 +1523,7 @@
             int count = dcount + 1;
             while (count-- && offs < bufLen)
             {
-                if (!dm_fread_byte(fp, &data))
+                if (!dmf_read_byte(fp, &data))
                     return FALSE;
 
                 buf[offs++] = data;
@@ -1540,12 +1535,12 @@
 }
 
 
-static BOOL dmIFFReadOneRow(FILE *fp, DMIFF *iff, Uint8 *buf, const size_t bufLen)
+static BOOL dmIFFReadOneRow(DMResource *fp, DMIFF *iff, Uint8 *buf, const size_t bufLen)
 {
     if (iff->bmhd.compression == IFF_COMP_BYTERUN1)
         return dmIFFDecodeByteRun1Row(fp, buf, bufLen);
     else
-        return dm_fread_str(fp, buf, bufLen);
+        return dmf_read_str(fp, buf, bufLen);
 }
 
 
@@ -1560,7 +1555,7 @@
 }
 
 
-int dmDecodeILBMBody(FILE *fp, DMIFF *iff, DMImage **pimg, Uint32 *read)
+int dmDecodeILBMBody(DMResource *fp, DMIFF *iff, DMImage **pimg, Uint32 *read)
 {
     DMImage *img;
     Uint8 *buf;
@@ -1644,7 +1639,7 @@
 }
 
 
-int dmDecodePBMBody(FILE *fp, DMIFF *iff, DMImage **pimg, Uint32 *read)
+int dmDecodePBMBody(DMResource *fp, DMIFF *iff, DMImage **pimg, Uint32 *read)
 {
     DMImage *img;
     int yc, res = DMERR_OK;
@@ -1680,7 +1675,7 @@
 }
 
 
-int dmReadILBMImageFILE(FILE *fp, DMImage **pimg)
+int dmReadILBMImageFILE(DMResource *fp, DMImage **pimg)
 {
     Uint32 idILBM;
     DMIFFChunk chunk;
@@ -1702,7 +1697,7 @@
     }
 
     // Check IFF ILBM signature
-    if (!dm_fread_be32(fp, &idILBM) ||
+    if (!dmf_read_be32(fp, &idILBM) ||
         (idILBM != IFF_ID_ILBM && idILBM != IFF_ID_PBM))
     {
         return dmError(DMERR_INVALID_DATA,
@@ -1711,7 +1706,7 @@
 
     iff.planar = (idILBM == IFF_ID_ILBM);
 
-    while (!parsed && !feof(fp))
+    while (!parsed && !dmfeof(fp))
     {
         if (!dmReadIFFChunk(fp, &chunk))
         {
@@ -1727,19 +1722,19 @@
                     return res;
 
                 // Read BMHD data
-                if (!dm_fread_be16(fp, &iff.bmhd.w) ||
-                    !dm_fread_be16(fp, &iff.bmhd.h) ||
-                    !dm_fread_be16(fp, (Uint16 *) &iff.bmhd.x) ||
-                    !dm_fread_be16(fp, (Uint16 *) &iff.bmhd.y) ||
-                    !dm_fread_byte(fp, &iff.bmhd.nplanes) ||
-                    !dm_fread_byte(fp, &iff.bmhd.masking) ||
-                    !dm_fread_byte(fp, &iff.bmhd.compression) ||
-                    !dm_fread_byte(fp, &iff.bmhd.pad1) ||
-                    !dm_fread_be16(fp, &iff.bmhd.transp) ||
-                    !dm_fread_byte(fp, &iff.bmhd.xasp) ||
-                    !dm_fread_byte(fp, &iff.bmhd.yasp) ||
-                    !dm_fread_be16(fp, (Uint16 *) &iff.bmhd.pagew) ||
-                    !dm_fread_be16(fp, (Uint16 *) &iff.bmhd.pageh))
+                if (!dmf_read_be16(fp, &iff.bmhd.w) ||
+                    !dmf_read_be16(fp, &iff.bmhd.h) ||
+                    !dmf_read_be16(fp, (Uint16 *) &iff.bmhd.x) ||
+                    !dmf_read_be16(fp, (Uint16 *) &iff.bmhd.y) ||
+                    !dmf_read_byte(fp, &iff.bmhd.nplanes) ||
+                    !dmf_read_byte(fp, &iff.bmhd.masking) ||
+                    !dmf_read_byte(fp, &iff.bmhd.compression) ||
+                    !dmf_read_byte(fp, &iff.bmhd.pad1) ||
+                    !dmf_read_be16(fp, &iff.bmhd.transp) ||
+                    !dmf_read_byte(fp, &iff.bmhd.xasp) ||
+                    !dmf_read_byte(fp, &iff.bmhd.yasp) ||
+                    !dmf_read_be16(fp, (Uint16 *) &iff.bmhd.pagew) ||
+                    !dmf_read_be16(fp, (Uint16 *) &iff.bmhd.pageh))
                 {
                     return dmError(DMERR_FREAD,
                         "ILBM: Error reading BMHD chunk.\n");
@@ -1841,7 +1836,7 @@
 
 
             case IFF_ID_CAMG:
-                if (!dm_fread_be32(fp, &iff.camg))
+                if (!dmf_read_be32(fp, &iff.camg))
                 {
                     return dmError(DMERR_FREAD,
                         "ILBM: Error reading CAMG chunk.\n");
@@ -1865,7 +1860,7 @@
                     dmMsg(4, "Unknown chunk ID '%s', size %d\n",
                         dmGetIFFChunkID(&chunk), chunk.size);
 
-                    if (fseeko(fp, chunk.size, SEEK_CUR) != 0)
+                    if (dmfseek(fp, chunk.size, SEEK_CUR) != 0)
                     {
                         return dmError(DMERR_FSEEK,
                             "ILBM: Error skipping in file.");
@@ -1875,7 +1870,7 @@
         }
 
         if (chunk.size & 1)
-            fgetc(fp);
+            dmfgetc(fp);
     }
 
     // Set colormap after finishing
@@ -1920,10 +1915,10 @@
 
 int dmReadILBMImage(const char *filename, DMImage **pimg)
 {
-    FILE *fp;
+    DMResource *fp;
     int res;
 
-    if ((fp = fopen(filename, "rb")) == NULL)
+    if ((res = dmf_open_stdio(filename, "rb", &fp)) != DMERR_OK)
     {
         return dmError(DMERR_FOPEN,
             "ILBM: Could not open file '%s' for reading.\n",
@@ -1932,7 +1927,7 @@
 
     res = dmReadILBMImageFILE(fp, pimg);
 
-    fclose(fp);
+    dmf_close(fp);
     return res;
 }
 
--- a/tools/libgfx.h	Mon May 14 12:40:57 2018 +0300
+++ b/tools/libgfx.h	Mon May 14 12:42:24 2018 +0300
@@ -9,6 +9,7 @@
 #define LIBMGFX_H 1
 
 #include "dmlib.h"
+#include "dmres.h"
 
 
 #ifdef __cplusplus
@@ -66,7 +67,7 @@
 };
 
 
-// Bitmapped image struct 
+// Bitmapped image struct
 typedef struct
 {
     int format;     // one of types specified by DM_IFMT_*
@@ -99,9 +100,9 @@
     char *desc;
     int  (*probe)(const Uint8 *buf, const size_t len);
     int  (*read)(const char *filename, DMImage **pimg);
-    int  (*readFILE)(FILE *fp, DMImage **pimg);
+    int  (*readFILE)(DMResource *fp, DMImage **pimg);
     int  (*write)(const char *filename, const DMImage *pimg, const DMImageConvSpec *spec);
-    int  (*writeFILE)(FILE *fp, const DMImage *pimg, const DMImageConvSpec *spec);
+    int  (*writeFILE)(DMResource *fp, const DMImage *pimg, const DMImageConvSpec *spec);
 } DMImageFormat;
 
 
@@ -119,24 +120,23 @@
 
 int dmWriteImageData(const DMImage *img, void *cbdata, int (*writeRowCB)(void *, const Uint8 *, const size_t), const DMImageConvSpec *spec);
 
-int dmWriteIFFMasterRAWPalette(FILE *fp, const DMImage *img, int ncolors, const char *indent, const char *type);
-int dmWriteRAWImageFILE(FILE *fp, const DMImage *img, const DMImageConvSpec *spec);
+int dmWriteRAWImageFILE(DMResource *fp, const DMImage *img, const DMImageConvSpec *spec);
 int dmWriteRAWImage(const char *filename, const DMImage *img, const DMImageConvSpec *spec);
 
-int dmWritePPMImageFILE(FILE *fp, const DMImage *img, const DMImageConvSpec *spec);
+int dmWritePPMImageFILE(DMResource *fp, const DMImage *img, const DMImageConvSpec *spec);
 int dmWritePPMImage(const char *filename, const DMImage *img, const DMImageConvSpec *spec);
 
 #ifdef DM_USE_LIBPNG
-int dmWritePNGImageFILE(FILE *fp, const DMImage *img, const DMImageConvSpec *spec);
+int dmWritePNGImageFILE(DMResource *fp, const DMImage *img, const DMImageConvSpec *spec);
 int dmWritePNGImage(const char *filename, const DMImage *img, const DMImageConvSpec *spec);
 #endif
 
-int dmReadILBMImageFILE(FILE *fp, DMImage **pimg);
+int dmReadILBMImageFILE(DMResource *fp, DMImage **pimg);
 int dmReadILBMImage(const char *filename, DMImage **pimg);
 
-int dmWritePCXImageFILE(FILE *fp, const DMImage *img, const DMImageConvSpec *spec);
+int dmWritePCXImageFILE(DMResource *fp, const DMImage *img, const DMImageConvSpec *spec);
 int dmWritePCXImage(const char *filename, const DMImage *img, const DMImageConvSpec *spec);
-int dmReadPCXImageFILE(FILE *fp, DMImage **pimg);
+int dmReadPCXImageFILE(DMResource *fp, DMImage **pimg);
 int dmReadPCXImage(const char *filename, DMImage **pimg);
 
 
@@ -153,7 +153,7 @@
 void  dmInitBitStreamContext(DMBitStreamContext *ctx);
 int   dmFlushBitStream(DMBitStreamContext *ctx);
 BOOL  dmPutBits(DMBitStreamContext *ctx, const int val, const int n);
-int   dmInitBitStreamFILE(DMBitStreamContext *ctx, FILE *fp);
+int   dmInitBitStreamFILE(DMBitStreamContext *ctx, DMResource *fp);