/*
 Bmp
 Copyright (C) 2010 Martin Štrympl
 
 This library 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 3.0 of the License, or (at your option) any later version.
 
 This library 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 this library.
 
 Martin Štrympl
 xstrym00@stud.feec.vutbr.cz
 */

/*
 *  bmp.c
 *  Bmp
 *
 *  Created by Martin Štrympl on 11/4/10.
 *  Copyright 2010 School. All rights reserved.
 *
 */

#include "bmp.h"

bool BMP_PixelMask_Resize(struct sBMP *ps_bmp, struct sBMP_PixelMask *ps_pixels, int32_t i4_x_min, int32_t i4_x_max, int32_t i4_y_min, int32_t i4_y_max)
{
  // generate new pixel mask
  
  struct sBMP_PixelMask s_newmask;
  
  // exchange minimum adn maximum values, minumum must be lower
  if (i4_x_min>i4_x_max)
  {
    int32_t i4_move;
    
    i4_move=i4_x_min;
    i4_x_min=i4_x_max;
    i4_x_max=i4_move;
  }
  if (i4_y_min>i4_y_max)
  {
    int32_t i4_move;
    
    i4_move=i4_y_min;
    i4_y_min=i4_y_max;
    i4_y_max=i4_move;
  }
  
  // show action
  if (ps_bmp->i4_debuglevel>2) printf("Module BMP: Debug: RESIZE TO: X: from %i to %i Y: from %i to %i\n", 
                                      i4_x_min, i4_x_max, i4_y_min, i4_y_max);
  
  // for bug finding
  /*if (i4_y_min==-3747)
  {
    printf("DEBUG START\n");
  }*/
  
  // old move values
  s_newmask.i4_x_move=ps_pixels->i4_x_move;
  s_newmask.i4_y_move=ps_pixels->i4_y_move;
  
  // move to positive coordinates
  // must correct, because move old pixel to new pixels must be divided 8
  {
    int32_t i4_mod;
    
    if ((i4_x_min+s_newmask.i4_x_move)<0)
    {
      s_newmask.i4_x_move=-i4_x_min;
      i4_mod=s_newmask.i4_x_move%8;
      if (i4_mod)
      {
        /*if (i4_mod>0) s_newmask.i4_x_move-=i4_mod;
        else */s_newmask.i4_x_move+=8-i4_mod;
      }
    }
    if ((i4_y_min+s_newmask.i4_y_move)<0)
    {
      s_newmask.i4_y_move=-i4_y_min;
      i4_mod=s_newmask.i4_y_move%8;
      if (i4_mod)
      {
        /*if (i4_mod>0)
        {
          s_newmask.i4_y_move-=i4_mod;
        }
        else */s_newmask.i4_y_move+=8-i4_mod;
      }
    }
  }
  
  // move values
  
  //i4_x_min+=s_newmask.i4_x_move;
  i4_x_max+=s_newmask.i4_x_move;
  //i4_y_min+=s_newmask.i4_y_move;
  i4_y_max+=s_newmask.i4_y_move;
  
  // find new minimal and maximal values, minimum values go to zero
  if (ps_pixels->au1_pixels)
  {
    uint32_t u4_x_max, u4_y_max;
    
    
    u4_x_max=ps_pixels->u4_x_max+(s_newmask.i4_x_move-ps_pixels->i4_x_move);
    u4_y_max=ps_pixels->u4_y_max+(s_newmask.i4_y_move-ps_pixels->i4_y_move);
  
    s_newmask.u4_x_min= 0;
    s_newmask.u4_x_max= (i4_x_max>u4_x_max)?(i4_x_max):(u4_x_max);
    s_newmask.u4_y_min= 0;
    s_newmask.u4_y_max= (i4_y_max>u4_y_max)?(i4_y_max):(u4_y_max);
  }
  else
  {
    s_newmask.u4_x_min=0;
    s_newmask.u4_x_max=i4_x_max;
    s_newmask.u4_y_min=0;
    s_newmask.u4_y_max=i4_y_max;
  }
  
  // alignment to multiple of number 8
  s_newmask.u4_x_min&=0xFFFFFFF8;
  s_newmask.u4_x_max|=0x07;
  
  s_newmask.u4_y_min&=0xFFFFFFF8;
  s_newmask.u4_y_max|=0x07;
  
  s_newmask.u4_width = s_newmask.u4_x_max-s_newmask.u4_x_min+1;
  s_newmask.u4_height = s_newmask.u4_y_max-s_newmask.u4_y_min+1;
  
  if ((s_newmask.u4_width<=ps_pixels->u4_width)&&(s_newmask.u4_height<=ps_pixels->u4_height))
      //&&(s_newmask.i4_x_move==ps_pixels->i4_x_move)&&(s_newmask.i4_y_move==ps_pixels->i4_y_move))
  {
    s_newmask.au1_pixels=ps_pixels->au1_pixels;
    *ps_pixels=s_newmask;
    
    if (ps_bmp->i4_debuglevel>3) printf("Module BMP: Debug: NORESIZE NEW PICTURE: WIDTH: %i HEIGHT: %i MOVE X: %i Y: %i\n", 
                                        s_newmask.u4_width, s_newmask.u4_height, s_newmask.i4_x_move, s_newmask.i4_y_move);
    return true;
  }
  
  s_newmask.au1_pixels = (uint8_t *)malloc((s_newmask.u4_width*s_newmask.u4_height)>>3);
  
  if (s_newmask.au1_pixels)
  {
    // fill area with white color
    memset(s_newmask.au1_pixels, 0xFFFFFFFF,(s_newmask.u4_width*s_newmask.u4_height)>>3);
    
    // copy old pixel to new pixels
    if (ps_pixels->au1_pixels)
    {
      uint32_t u4_x_offset, u4_y_offset;
      uint32_t u4_y, u4_line;
    
      u4_line=(ps_pixels->u4_width)>>3;
    
      // usage move values, new is greater than old move value
      //u4_x_offset=(ps_pixels->u4_x_min-s_newmask.u4_x_min)>>3;
      //u4_y_offset=ps_pixels->u4_y_min-s_newmask.u4_y_min;
      u4_x_offset=(s_newmask.i4_x_move-ps_pixels->i4_x_move)>>3;
      u4_y_offset=s_newmask.i4_y_move-ps_pixels->i4_y_move;
    
      // copy lines
      for (u4_y=0;u4_y<ps_pixels->u4_height;u4_y++)
      {
        memcpy(s_newmask.au1_pixels+((u4_y+u4_y_offset)*(s_newmask.u4_width>>3))+u4_x_offset,
               ps_pixels->au1_pixels+(u4_y*u4_line),
               u4_line);
      }
      
      free(ps_pixels->au1_pixels);
    }
    
    *ps_pixels=s_newmask;
    
    if (ps_bmp->i4_debuglevel>2) printf("Module BMP: Debug: RESIZE NEW PICTURE: WIDTH: %i HEIGHT: %i MOVE X: %i Y: %i\n", 
                                        s_newmask.u4_width, s_newmask.u4_height, s_newmask.i4_x_move, s_newmask.i4_y_move);
    return true;
  }
  
  return false;
}
bool BMP_PixelMask_Pixel(struct sBMP *ps_bmp, struct sBMP_PixelMask *ps_pixels, int32_t s4_x, int32_t s4_y, bool b_positive)
{
  uint32_t u4_x, u4_y;
  uint8_t u1_x, u1_pixel;

  u4_x=s4_x+ps_pixels->i4_x_move-ps_pixels->u4_x_min;
  u4_y=s4_y+ps_pixels->i4_y_move-ps_pixels->u4_y_min;
  
  if (ps_bmp->i4_debuglevel>2) printf("Module BMP: Debug: POINT: [%u,%u]\n", u4_x, u4_y);
  
  u1_x = u4_x&0x7;
  u4_x = u4_x>>3;
  
  u1_pixel=0x80>>u1_x;
  if (!b_positive)
  {
    // draw white
    ps_pixels->au1_pixels[(ps_pixels->u4_width>>3)*u4_y+u4_x]|=u1_pixel;
  }
  else
  {
    // draw black
    u1_pixel=~u1_pixel;
    ps_pixels->au1_pixels[(ps_pixels->u4_width>>3)*u4_y+u4_x]&=u1_pixel;
  }
  
  return true;
}
