view src/dmimage.c @ 2298:b5abfff07ca9

Add new DMGrowBuf helper functions dmGrowBufCopyOffsSize() and dmGrowBufConstCopyOffsSize().
author Matti Hamalainen <ccr@tnsp.org>
date Thu, 04 Jul 2019 10:54:16 +0300
parents 7a2337dcd1b3
children 0e355702435d
line wrap: on
line source

/*
 * DMLib
 * -- Bitmap image conversion and loading
 * Programmed and designed by Matti 'ccr' Hamalainen
 * (C) Copyright 2012-2015 Tecnic Software productions (TNSP)
 */
#include "dmimage.h"
#include "dmzlib.h"

// Formats
#define STBI_ONLY_JPEG 1
#define STBI_ONLY_PNG 1
//#define STBI_NO_HDR 1

// Other options, etc.
#ifndef DM_DEBUG
#define STBI_NO_FAILURE_STRINGS 1
#define STBI_ASSERT(x)
#endif
#define STBI_FAILURE_USERMSG 1

#define STB_IMAGE_IMPLEMENTATION 1
#define STBI_NO_STDIO 1

#include "stb_image.c"


SDL_Surface *dmCreateRGBSurfaceFrom(void *data,
    const int width, const int height,
    const int depth, const int pitch,
    const Uint32 format)
{
    // Create source surface from given data
    SDL_Surface
        *result = NULL,
        *tmp = SDL_CreateRGBSurfaceWithFormatFrom(data, width, height, depth, pitch, format);

    // Create result conversion surface
    if (tmp != NULL)
    {
        result = SDL_ConvertSurfaceFormat(tmp, SDL_PIXELFORMAT_RGBA32, 0);
        SDL_FreeSurface(tmp);
    }

    return result;
}


SDL_Surface *dmCreatePaletteSurfaceFrom(void *data, const int width, const int height, const int pitch)
{
    int yc;
    Uint8 *dst, *src;
    SDL_Surface *result;
    result = SDL_CreateRGBSurfaceWithFormat(0, width, height, 8, SDL_PIXELFORMAT_INDEX8);
    if (result == NULL)
        return NULL;

    dst = result->pixels;
    src = data;
    for (yc = 0; yc < height; yc++)
    {
        memcpy(dst, src, width * sizeof(Uint8));
        dst += result->pitch;
        src += pitch;
    }

    return result;
}


static int dmSTBIread(void *user, char *data, int size)
{
    return dmfread(data, 1, size, (DMResource *) user);
}


static void dmSTBIskip(void *user, int n)
{
    dmfseek((DMResource *) user, n, SEEK_CUR);
}


static int dmSTBIeof(void *user)
{
    return dmfeof((DMResource *) user);
}


static const stbi_io_callbacks dmSTBICallbacks =
{
    dmSTBIread,
    dmSTBIskip,
    dmSTBIeof,
};


SDL_Surface *dmLoadImage(DMResource *file)
{
    SDL_Surface *result = NULL;
    int width = 0, height = 0, comp = 0;
    Uint8 *data;

    dmfreset(file);
    data = stbi_load_from_callbacks(&dmSTBICallbacks, file, &width, &height, &comp, 0);

    if (data == NULL)
    {
        dmErrorDBGMsg(
            "Error decoding image resource %p '%s' [%d, %d, %d]: %s\n",
            file, file->filename, width, height, comp, stbi_failure_reason());
        return NULL;
    }


    switch (comp)
    {
        case 4:
            result = dmCreateRGBSurfaceFrom(data, width, height, comp * 8, width * comp,
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
                SDL_PIXELFORMAT_ABGR8888
#else
                SDL_PIXELFORMAT_ARGB8888
#endif
                );
            break;

        case 3:
            // These masks are different from the dmX*masks
            result = dmCreateRGBSurfaceFrom(data, width, height, comp * 8, width * comp,
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
                SDL_PIXELFORMAT_BGR888
#else
                SDL_PIXELFORMAT_RGB888
#endif
                );
            break;

        case 1:
            result = dmCreatePaletteSurfaceFrom(data, width, height, width * comp);
            break;
    }

    stbi_image_free(data);

    if (result == NULL)
    {
        dmErrorDBGMsg(
            "Format conversion failed for image resource %p '%s' [%d, %d, %d].\n",
            file, file->filename, width, height, comp);
    }

    return result;
}


SDL_Texture *dmLoadImageToTexture(DMResource *file, SDL_Renderer *renderer)
{
    SDL_Surface *tmp;
    SDL_Texture *texture;

    // Sanity checks
    if (renderer == NULL || file == NULL)
        return NULL;

    if ((tmp = dmLoadImage(file)) == NULL)
        return NULL;

    // Attempt to create the texture
    texture = SDL_CreateTextureFromSurface(renderer, tmp);
    SDL_FreeSurface(tmp);

    return texture;
}