Blame src/gd_filename.c

Packit ed3af9
/* Convenience functions to read or write images from or to disk,
Packit ed3af9
 * determining file type from the filename extension. */
Packit ed3af9
Packit ed3af9
#ifdef HAVE_CONFIG_H
Packit ed3af9
#	include "config.h"
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
#include <stdio.h>
Packit ed3af9
#include <string.h>
Packit ed3af9
Packit ed3af9
#include "gd.h"
Packit ed3af9
Packit ed3af9
typedef gdImagePtr (BGD_STDCALL *ReadFn)(FILE *in);
Packit ed3af9
typedef void (BGD_STDCALL *WriteFn)(gdImagePtr im, FILE *out);
Packit ed3af9
typedef gdImagePtr (BGD_STDCALL *LoadFn)(char *filename);
Packit ed3af9
Packit ed3af9
#ifdef HAVE_LIBZ
Packit ed3af9
static void BGD_STDCALL writegd2(gdImagePtr im, FILE *out) {
Packit ed3af9
    gdImageGd2(im, out, 0, GD2_FMT_COMPRESSED);
Packit ed3af9
}/* writegd*/
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
#ifdef HAVE_LIBJPEG
Packit ed3af9
static void BGD_STDCALL writejpeg(gdImagePtr im, FILE *out) {
Packit ed3af9
    gdImageJpeg(im, out, -1);
Packit ed3af9
}/* writejpeg*/
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
static void BGD_STDCALL writewbmp(gdImagePtr im, FILE *out) {
Packit ed3af9
    int fg = gdImageColorClosest(im, 0, 0, 0);
Packit ed3af9
    
Packit ed3af9
    gdImageWBMP(im, fg, out);
Packit ed3af9
}/* writejpeg*/
Packit ed3af9
Packit ed3af9
static void BGD_STDCALL writebmp(gdImagePtr im, FILE *out) {
Packit ed3af9
    gdImageBmp(im, out, GD_TRUE);
Packit ed3af9
}/* writejpeg*/
Packit ed3af9
Packit ed3af9
Packit ed3af9
enum FType {UNKNOWN, PNG, JPG, GIF, TIFF, GD, GD2, WEBP};
Packit ed3af9
static struct FileType {
Packit ed3af9
    const char *ext;
Packit ed3af9
    ReadFn reader;
Packit ed3af9
    WriteFn writer;
Packit ed3af9
    LoadFn loader;
Packit ed3af9
} Types[] = {
Packit ed3af9
    {".gif",    gdImageCreateFromGif,   gdImageGif,     NULL},
Packit ed3af9
    {".gd",     gdImageCreateFromGd,    gdImageGd,      NULL},
Packit ed3af9
    {".wbmp",   gdImageCreateFromWBMP,  writewbmp,      NULL},
Packit ed3af9
    {".bmp",    gdImageCreateFromBmp,   writebmp,       NULL},
Packit ed3af9
Packit ed3af9
    {".xbm",    gdImageCreateFromXbm,   NULL,           NULL},
Packit ed3af9
    {".tga",    gdImageCreateFromTga,   NULL,           NULL},
Packit ed3af9
Packit ed3af9
#ifdef HAVE_LIBPNG
Packit ed3af9
    {".png",    gdImageCreateFromPng,   gdImagePng,     NULL},
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
#ifdef HAVE_LIBJPEG
Packit ed3af9
    {".jpg",    gdImageCreateFromJpeg,  writejpeg,      NULL},
Packit ed3af9
    {".jpeg",   gdImageCreateFromJpeg,  writejpeg,      NULL},
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
#ifdef HAVE_LIBTIFF    
Packit ed3af9
    {".tiff",   gdImageCreateFromTiff,  gdImageTiff,    NULL},
Packit ed3af9
    {".tif" ,   gdImageCreateFromTiff,  gdImageTiff,    NULL},
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
#ifdef HAVE_LIBZ
Packit ed3af9
    {".gd2",    gdImageCreateFromGd2,   writegd2,       NULL},
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
#ifdef HAVE_LIBWEBP
Packit ed3af9
    {".webp",   gdImageCreateFromWebp,  gdImageWebp,    NULL},
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
#ifdef HAVE_LIBXPM
Packit ed3af9
    {".xpm",    NULL,                   NULL,           gdImageCreateFromXpm},
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
    {NULL, NULL, NULL}
Packit ed3af9
};
Packit ed3af9
Packit ed3af9
Packit ed3af9
struct FileType *
Packit ed3af9
ftype(const char *filename) {
Packit ed3af9
    int n;
Packit ed3af9
    char *ext;
Packit ed3af9
Packit ed3af9
    /* Find the file extension (i.e. the last period in the string. */
Packit ed3af9
    ext = strrchr(filename, '.');
Packit ed3af9
    if (!ext) return NULL;
Packit ed3af9
    
Packit ed3af9
    for (n = 0; Types[n].ext; n++) {
Packit ed3af9
        if (strcasecmp(ext, Types[n].ext) == 0) {
Packit ed3af9
            return &Types[n];
Packit ed3af9
        }/* if */
Packit ed3af9
    }/* for */
Packit ed3af9
Packit ed3af9
    return NULL;
Packit ed3af9
}/* ftype*/
Packit ed3af9
Packit ed3af9
Packit ed3af9
/*
Packit ed3af9
  Function: gdSupportsFileType
Packit ed3af9
  
Packit ed3af9
    Tests if a given file type is supported by GD.
Packit ed3af9
Packit ed3af9
    Given the name of an image file (which does not have to exist),
Packit ed3af9
    returns 1 (i.e. TRUE) if <gdImageCreateFromFile> can read a file
Packit ed3af9
    of that type.  This is useful if you do not know which image types
Packit ed3af9
    were enabled at compile time.
Packit ed3af9
Packit ed3af9
    If _writing_ is true, the result will be true only if
Packit ed3af9
    <gdImageFile> can write a file of this type.
Packit ed3af9
Packit ed3af9
    Note that filename parsing is done exactly the same as is done by
Packit ed3af9
    <gdImageCreateFromFile> and <gdImageFile> and is subject to the
Packit ed3af9
    same limitations.
Packit ed3af9
Packit ed3af9
    Assuming LibGD is compiled with support for these image types, the
Packit ed3af9
    following extensions are supported:
Packit ed3af9
Packit ed3af9
        - .gif
Packit ed3af9
        - .gd, .gd2
Packit ed3af9
        - .wbmp
Packit ed3af9
        - .bmp
Packit ed3af9
        - .xbm
Packit ed3af9
        - .tga
Packit ed3af9
        - .png
Packit ed3af9
        - .jpg, .jpeg
Packit ed3af9
        - .tiff, .tif
Packit ed3af9
        - .webp
Packit ed3af9
        - .xpm
Packit ed3af9
Packit ed3af9
    Names are parsed case-insenstively.
Packit ed3af9
Packit ed3af9
  Parameters:
Packit ed3af9
Packit ed3af9
    filename    - Filename with tested extension.
Packit ed3af9
    writing     - Flag: true tests if writing works
Packit ed3af9
Packit ed3af9
  Returns:
Packit ed3af9
Packit ed3af9
    GD_TRUE (1) if the file type is supported, GD_FALSE (0) if not.
Packit ed3af9
Packit ed3af9
*/
Packit ed3af9
BGD_DECLARE(int) 
Packit ed3af9
gdSupportsFileType(const char *filename, int writing) {
Packit ed3af9
    struct FileType *entry = ftype(filename);
Packit ed3af9
    return !!entry && (!writing || !!entry->writer);
Packit ed3af9
}/* gdSupportsFileType*/
Packit ed3af9
Packit ed3af9
Packit ed3af9
/*
Packit ed3af9
  Function: gdImageCreateFromFile
Packit ed3af9
Packit ed3af9
    Read an image file of any supported.
Packit ed3af9
Packit ed3af9
    Given the path to a file, <gdImageCreateFromFile> will open the
Packit ed3af9
    file, read its contents with the appropriate _gdImageCreateFrom*_
Packit ed3af9
    function and return it.  
Packit ed3af9
Packit ed3af9
    File type is determined by the filename extension, so having an
Packit ed3af9
    incorrect extension will probably not work.  For example, renaming
Packit ed3af9
    PNG image "foo.png" to "foo.gif" and then attempting to load it
Packit ed3af9
    will fail even if GD supports both formats.  See
Packit ed3af9
    <gdSupportsFiletype> for more details.
Packit ed3af9
Packit ed3af9
    NULL is returned on error.
Packit ed3af9
Packit ed3af9
  Parameters:
Packit ed3af9
Packit ed3af9
    filename    - the input file name
Packit ed3af9
Packit ed3af9
  Returns:
Packit ed3af9
Packit ed3af9
    A pointer to the new image or NULL if an error occurred.
Packit ed3af9
Packit ed3af9
*/
Packit ed3af9
Packit ed3af9
BGD_DECLARE(gdImagePtr) 
Packit ed3af9
gdImageCreateFromFile(const char *filename) {
Packit ed3af9
    struct FileType *entry = ftype(filename);
Packit ed3af9
    FILE *fh;
Packit ed3af9
    gdImagePtr result;
Packit ed3af9
 
Packit ed3af9
    if (!entry) return NULL;
Packit ed3af9
    if (entry->loader) return entry->loader((char *)filename);
Packit ed3af9
    if (!entry->reader) return NULL;
Packit ed3af9
Packit ed3af9
    fh = fopen(filename, "rb");
Packit ed3af9
    if (!fh) return NULL;
Packit ed3af9
Packit ed3af9
    result = entry->reader(fh);
Packit ed3af9
    
Packit ed3af9
    fclose(fh);
Packit ed3af9
Packit ed3af9
    return result;
Packit ed3af9
}/* gdImageCreateFromFile*/
Packit ed3af9
Packit ed3af9
Packit ed3af9
Packit ed3af9
/*
Packit ed3af9
  Function: gdImageFile
Packit ed3af9
Packit ed3af9
    Writes an image to a file in the format indicated by the filename.
Packit ed3af9
Packit ed3af9
    File type is determined by the extension of the file name.  See
Packit ed3af9
    <gdSupportsFiletype> for an overview of the parsing.
Packit ed3af9
Packit ed3af9
    For file types that require extra arguments, <gdImageFile>
Packit ed3af9
    attempts to use sane defaults:
Packit ed3af9
Packit ed3af9
    <gdImageGd2>    - chunk size = 0, compression is enabled.
Packit ed3af9
    <gdImageJpeg>   - quality = -1 (i.e. the reasonable default)
Packit ed3af9
    <gdImageWBMP>   - foreground is the darkest available color
Packit ed3af9
Packit ed3af9
    Everything else is called with the two-argument function and so
Packit ed3af9
    will use the default values.
Packit ed3af9
Packit ed3af9
    <gdImageFile> has some rudimentary error detection and will return
Packit ed3af9
    GD_FALSE (0) if a detectable error occurred.  However, the image
Packit ed3af9
    loaders do not normally return their error status so a result of
Packit ed3af9
    GD_TRUE (1) does **not** mean the file was saved successfully.
Packit ed3af9
Packit ed3af9
  Parameters:
Packit ed3af9
Packit ed3af9
    im          - The image to save.
Packit ed3af9
    filename    - The path to the file to which the image is saved.
Packit ed3af9
Packit ed3af9
  Returns:
Packit ed3af9
Packit ed3af9
    GD_FALSE (0) if an error was detected, GD_TRUE (1) if not.
Packit ed3af9
Packit ed3af9
*/
Packit ed3af9
Packit ed3af9
BGD_DECLARE(int) 
Packit ed3af9
gdImageFile(gdImagePtr im, const char *filename) {
Packit ed3af9
    struct FileType *entry = ftype(filename);
Packit ed3af9
    FILE *fh;
Packit ed3af9
Packit ed3af9
    if (!entry || !entry->writer) return GD_FALSE;
Packit ed3af9
Packit ed3af9
    fh = fopen(filename, "wb");
Packit ed3af9
    if (!fh) return GD_FALSE;
Packit ed3af9
Packit ed3af9
    entry->writer(im, fh);
Packit ed3af9
Packit ed3af9
    fclose(fh);
Packit ed3af9
Packit ed3af9
    return GD_TRUE;
Packit ed3af9
}/* gdImageFile*/
Packit ed3af9