/*
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */


#include <stdlib.h>
#include <string.h>
#include "vpx/vpx_image.h"

static vpx_image_t *img_alloc_helper(vpx_image_t  *img,
                                     vpx_img_fmt_t fmt,
                                     unsigned int  d_w,
                                     unsigned int  d_h,
                                     unsigned int  stride_align,
                                     unsigned char      *img_data)
{

    unsigned int  h, w, s, xcs, ycs, bps;
    int           align;

    /* Treat align==0 like align==1 */
    if (!stride_align)
        stride_align = 1;

    /* Validate alignment (must be power of 2) */
    if (stride_align & (stride_align - 1))
        goto fail;

    /* Get sample size for this format */
    switch (fmt)
    {
    case VPX_IMG_FMT_RGB32:
    case VPX_IMG_FMT_RGB32_LE:
    case VPX_IMG_FMT_ARGB:
    case VPX_IMG_FMT_ARGB_LE:
        bps = 32;
        break;
    case VPX_IMG_FMT_RGB24:
    case VPX_IMG_FMT_BGR24:
        bps = 24;
        break;
    case VPX_IMG_FMT_RGB565:
    case VPX_IMG_FMT_RGB565_LE:
    case VPX_IMG_FMT_RGB555:
    case VPX_IMG_FMT_RGB555_LE:
    case VPX_IMG_FMT_UYVY:
    case VPX_IMG_FMT_YUY2:
    case VPX_IMG_FMT_YVYU:
        bps = 16;
        break;
    case VPX_IMG_FMT_I420:
    case VPX_IMG_FMT_YV12:
    case VPX_IMG_FMT_VPXI420:
    case VPX_IMG_FMT_VPXYV12:
        bps = 12;
        break;
    default:
        bps = 16;
        break;
    }

    /* Get chroma shift values for this format */
    switch (fmt)
    {
    case VPX_IMG_FMT_I420:
    case VPX_IMG_FMT_YV12:
    case VPX_IMG_FMT_VPXI420:
    case VPX_IMG_FMT_VPXYV12:
        xcs = 1;
        break;
    default:
        xcs = 0;
        break;
    }

    switch (fmt)
    {
    case VPX_IMG_FMT_I420:
    case VPX_IMG_FMT_YV12:
    case VPX_IMG_FMT_VPXI420:
    case VPX_IMG_FMT_VPXYV12:
        ycs = 1;
        break;
    default:
        ycs = 0;
        break;
    }

    /* Calculate storage sizes given the chroma subsampling */
    align = (1 << xcs) - 1;
    w = (d_w + align) & ~align;
    align = (1 << ycs) - 1;
    h = (d_h + align) & ~align;
    s = (fmt & VPX_IMG_FMT_PLANAR) ? w : bps * w / 8;
    s = (s + stride_align - 1) & ~(stride_align - 1);

    /* Allocate the new image */
    if (!img)
    {
        img = (vpx_image_t *)calloc(1, sizeof(vpx_image_t));

        if (!img)
            goto fail;

        img->self_allocd = 1;
    }
    else
    {
        memset(img, 0, sizeof(vpx_image_t));
    }

    img->img_data = img_data;

    if (!img_data)
    {
        img->img_data = malloc((fmt & VPX_IMG_FMT_PLANAR) ? h * w * bps / 8 : h * s);
        img->img_data_owner = 1;
    }

    if (!img->img_data)
        goto fail;

    img->fmt = fmt;
    img->w = w;
    img->h = h;
    img->x_chroma_shift = xcs;
    img->y_chroma_shift = ycs;
    img->bps = bps;

    /* Calculate strides */
    img->stride[VPX_PLANE_Y] = img->stride[VPX_PLANE_ALPHA] = s;
    img->stride[VPX_PLANE_U] = img->stride[VPX_PLANE_V] = s >> xcs;

    /* Default viewport to entire image */
    if (!vpx_img_set_rect(img, 0, 0, d_w, d_h))
        return img;

fail:
    vpx_img_free(img);
    return NULL;
}

vpx_image_t *vpx_img_alloc(vpx_image_t  *img,
                           vpx_img_fmt_t fmt,
                           unsigned int  d_w,
                           unsigned int  d_h,
                           unsigned int  stride_align)
{
    return img_alloc_helper(img, fmt, d_w, d_h, stride_align, NULL);
}

vpx_image_t *vpx_img_wrap(vpx_image_t  *img,
                          vpx_img_fmt_t fmt,
                          unsigned int  d_w,
                          unsigned int  d_h,
                          unsigned int  stride_align,
                          unsigned char       *img_data)
{
    return img_alloc_helper(img, fmt, d_w, d_h, stride_align, img_data);
}

int vpx_img_set_rect(vpx_image_t  *img,
                     unsigned int  x,
                     unsigned int  y,
                     unsigned int  w,
                     unsigned int  h)
{
    unsigned char      *data;

    if (x + w <= img->w && y + h <= img->h)
    {
        img->d_w = w;
        img->d_h = h;

        /* Calculate plane pointers */
        if (!(img->fmt & VPX_IMG_FMT_PLANAR))
        {
            img->planes[VPX_PLANE_PACKED] =
                img->img_data + x * img->bps / 8 + y * img->stride[VPX_PLANE_PACKED];
        }
        else
        {
            data = img->img_data;

            if (img->fmt & VPX_IMG_FMT_HAS_ALPHA)
            {
                img->planes[VPX_PLANE_ALPHA] =
                    data + x + y * img->stride[VPX_PLANE_ALPHA];
                data += img->h * img->stride[VPX_PLANE_ALPHA];
            }

            img->planes[VPX_PLANE_Y] = data + x + y * img->stride[VPX_PLANE_Y];
            data += img->h * img->stride[VPX_PLANE_Y];

            if (!(img->fmt & VPX_IMG_FMT_UV_FLIP))
            {
                img->planes[VPX_PLANE_U] = data
                                       + (x >> img->x_chroma_shift)
                                       + (y >> img->y_chroma_shift) * img->stride[VPX_PLANE_U];
                data += (img->h >> img->y_chroma_shift) * img->stride[VPX_PLANE_U];
                img->planes[VPX_PLANE_V] = data
                                       + (x >> img->x_chroma_shift)
                                       + (y >> img->y_chroma_shift) * img->stride[VPX_PLANE_V];
            }
            else
            {
                img->planes[VPX_PLANE_V] = data
                                       + (x >> img->x_chroma_shift)
                                       + (y >> img->y_chroma_shift) * img->stride[VPX_PLANE_V];
                data += (img->h >> img->y_chroma_shift) * img->stride[VPX_PLANE_V];
                img->planes[VPX_PLANE_U] = data
                                       + (x >> img->x_chroma_shift)
                                       + (y >> img->y_chroma_shift) * img->stride[VPX_PLANE_U];
            }
        }

        return 0;
    }

    return -1;
}

void vpx_img_flip(vpx_image_t *img)
{
    /* Note: In the calculation pointer adjustment calculation, we want the
     * rhs to be promoted to a signed type. Section 6.3.1.8 of the ISO C99
     * standard indicates that if the adjustment parameter is unsigned, the
     * stride parameter will be promoted to unsigned, causing errors when
     * the lhs is a larger type than the rhs.
     */
    img->planes[VPX_PLANE_Y] += (signed)(img->d_h - 1) * img->stride[VPX_PLANE_Y];
    img->stride[VPX_PLANE_Y] = -img->stride[VPX_PLANE_Y];

    img->planes[VPX_PLANE_U] += (signed)((img->d_h >> img->y_chroma_shift) - 1)
                            * img->stride[VPX_PLANE_U];
    img->stride[VPX_PLANE_U] = -img->stride[VPX_PLANE_U];

    img->planes[VPX_PLANE_V] += (signed)((img->d_h >> img->y_chroma_shift) - 1)
                            * img->stride[VPX_PLANE_V];
    img->stride[VPX_PLANE_V] = -img->stride[VPX_PLANE_V];

    img->planes[VPX_PLANE_ALPHA] += (signed)(img->d_h - 1) * img->stride[VPX_PLANE_ALPHA];
    img->stride[VPX_PLANE_ALPHA] = -img->stride[VPX_PLANE_ALPHA];
}

void vpx_img_free(vpx_image_t *img)
{
    if (img)
    {
        if (img->img_data && img->img_data_owner)
            free(img->img_data);

        if (img->self_allocd)
            free(img);
    }
}
