view src/dmimage.c @ 1557:5e5f75b45f8d

Initial port to SDL2. Many things will not work now.
author Matti Hamalainen <ccr@tnsp.org>
date Sun, 13 May 2018 06:00:50 +0300
parents 2b48b7fe95bc
children 7a2337dcd1b3
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"


static Uint32
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
        dmXrmask = 0xff000000,
        dmXgmask = 0x00ff0000,
        dmXbmask = 0x0000ff00,
        dmXamask = 0x000000ff;
#else
        dmXrmask = 0x000000ff,
        dmXgmask = 0x0000ff00,
        dmXbmask = 0x00ff0000,
        dmXamask = 0xff000000;
#endif


SDL_Surface *dmCreateRGBSurfaceFrom(void *data,
    const int width, const int height,
    const int depth, const int pitch,
    const int rmask, const int gmask, const int bmask, const int amask)
{
    // Create source surface from given data
    SDL_Surface *tmp = SDL_CreateRGBSurfaceFrom(data, width, height, depth, pitch, bmask, gmask, rmask, amask);

    // Create result conversion surface
    SDL_Surface
        *result = NULL,
        *pixtmp = SDL_CreateRGBSurface(
            SDL_SWSURFACE,
            16, 16, 32,
            dmXrmask, dmXgmask, dmXbmask, dmXamask);

    if (tmp != NULL && pixtmp != NULL)
    {
        // Convert surface
        result = SDL_ConvertSurface(tmp, pixtmp->format, SDL_SWSURFACE);
        SDL_FreeSurface(tmp);
    }
    if (pixtmp != NULL)
        SDL_FreeSurface(pixtmp);

    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_CreateRGBSurface(SDL_SWSURFACE, width, height, 8, 0,0,0,0);
    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)
{
    Uint32 rmask, gmask, bmask, amask;
    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, dmXrmask, dmXgmask, dmXbmask, dmXamask);
            break;

        case 3:
            // These masks are different from the dmX*masks
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
            rmask = 0x00ff0000;
            gmask = 0x0000ff00;
            bmask = 0x000000ff;
            amask = 0x00000000;
#else
            rmask = 0x000000ff;
            gmask = 0x0000ff00;
            bmask = 0x00ff0000;
            amask = 0x00000000;
#endif
            result = dmCreateRGBSurfaceFrom(data, width, height, comp * 8,
                width * comp, rmask, gmask, bmask, amask);
            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;
}