Blame src/gd_filename.c

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