/*
 *  Copyright 1994-2022 Olivier Girondel
 *
 *  This file is part of lebiniou.
 *
 *  lebiniou is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  lebiniou is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with lebiniou. If not, see <http://www.gnu.org/licenses/>.
 */

#include "context.h"


Pixel_t *
export_RGB_buffer(const Context_t *ctx, const uint8_t screen, const uint8_t flip)
{
  rgba_t *colors = &ctx->cf->cur->colors[0];
  Buffer8_t *buf = ctx->buffers[screen];
  const Pixel_t *src = NULL;
  Pixel_t *res;
  uint32_t c, i = 0;

  if (flip) {
    Buffer8_flip_v(buf);
  }
  src = buf->buffer;

  res = xmalloc(RGB_BUFFSIZE*sizeof(Pixel_t));

  for (c = 0; c < BUFFSIZE; c++) {
    res[i++] = colors[src[c]].col.r;
    res[i++] = colors[src[c]].col.g;
    res[i++] = colors[src[c]].col.b;
  }

  if (flip) {
    Buffer8_flip_v(buf);
  }

  return res;
}


Pixel_t *
export_RGB_active_buffer(const Context_t *ctx, const uint8_t flip)
{
  return export_RGB_buffer(ctx, ACTIVE_BUFFER, flip);
}


Pixel_t *
export_YUV_buffer(const Context_t *ctx, const uint8_t screen, const uint8_t flip)
{
  rgba_t *colors = &ctx->cf->cur->colors[0];
  Buffer8_t *buf = ctx->buffers[screen];
  const Pixel_t *src = NULL;
  Pixel_t *res;
  uint32_t c, i = 0;

  if (flip) {
    Buffer8_flip_v(buf);
  }
  src = buf->buffer;

  res = xmalloc(3*BUFFSIZE*sizeof(Pixel_t));

  /*
   * From wikipedia, sorry
   *
   * Y = 0,299⋅R + 0,587⋅G + 0,114⋅B
   * U = 0,492⋅(B − Y) = −0,14713⋅R − 0,28886⋅G + 0,436⋅B
   * V = 0,877⋅(R − Y) = 0,615⋅R − 0,51498⋅G- 0,10001⋅B
   */
#define CR (colors[src[c]].col.r)
#define CG (colors[src[c]].col.g)
#define CB (colors[src[c]].col.b)

  for (c = 0; c < BUFFSIZE; c++) {
    res[i++] = 0.299*CR + 0.587*CG + 0.114*CB;
    res[i++] = -0.14713*CR - 0.28886*CG + 0.436*CB;
    res[i++] = 0.615*CR - 0.51498*CG - 0.10001*CB;
  }

  if (flip) {
    Buffer8_flip_v(buf);
  }

  return res;
}


Pixel_t *
export_YUV_active_buffer(const Context_t *ctx, const uint8_t flip)
{
  return export_YUV_buffer(ctx, ACTIVE_BUFFER, flip);
}


const RGBA_t *
export_RGBA_buffer(const Context_t *ctx, const uint8_t screen)
{
  rgba_t *colors = &ctx->cf->cur->colors[0];
  Pixel_t *src = ctx->buffers[screen]->buffer, *start;
  RGBA_t *dst = ctx->rgba_buffers[screen]->buffer;

  assert(NULL != dst);
  start = src;

  for ( ; src < start+BUFFSIZE*sizeof(Pixel_t); src++, dst++) {
    *dst = colors[*src].col;
  }

  return ctx->rgba_buffers[screen]->buffer;
}


const RGBA_t *
export_RGBA_active_buffer(const Context_t *ctx)
{
  return export_RGBA_buffer(ctx, ACTIVE_BUFFER);
}
