// Copyright (C) 2006  Paul A. Price (price@ifa.hawaii.edu)
//
// This program 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.
//
// This program 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 program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

/*
 * Some utility routines that should be in psLib
 */
#include <stdio.h>
#include <memory.h>
#include <assert.h>
#include "pslib.h"
#include "pois.h"

psImage *poisImageSetVal(psImage *restrict in,       // Input image
                         const psC64 val             // set to this value
    )
{
    assert (in != NULL);

    switch (in->type.type) {
      case PS_TYPE_U8:
        {
            const int numCols = in->numCols;
            psU8 *row0 = in->data.U8[0];
            for (int c = 0; c < numCols; c++) {
                row0[c] = val;
            }
            for (int r = 1; r < in->numRows; r++) {
                memcpy(in->data.U8[r], row0, numCols*sizeof(psU8));
            }
        }
        break;
      case PS_TYPE_F32:
        {
            const int numCols = in->numCols;
            psF32 *row0 = in->data.F32[0];
            for (int c = 0; c < numCols; c++) {
                row0[c] = val;
            }
            for (int r = 1; r < in->numRows; r++) {
                memcpy(in->data.F32[r], row0, numCols*sizeof(psF32));
            }
        }
        break;
      default:
        psError(POIS_ERR_UNSUPPORTED_TYPE, true,
                "Type %d is not supported", in->type.type);
        return NULL;
    }

    return in;
}

psImage *poisImageSetValInMask(psImage *out,                    // Image to update, or NULL
                               const psImage *restrict in,      // Input image
                               const psImage *mask,             // mask for image
                               const psC64 val,                 // set to this value
                               const unsigned long bits         // set pixels where mask & bits != 0
    )
{
    assert(mask != NULL);
    assert(mask->type.type == PS_TYPE_U8);
    const int numCols = mask->numCols;
    const int numRows = mask->numRows;
    assert(in != NULL);
    assert(in->type.type == PS_TYPE_F32);
    assert(in->numCols == numCols && in->numRows == numRows);

    // Allocate the output image, if necessary
    if (out == NULL) {
        out = psImageCopy(NULL, in, in->type.type);
    }

    switch (in->type.type) {
      case PS_TYPE_F32:
        {
            const int numCols = in->numCols;
            for (int r = 0; r < in->numRows; r++) {
                psF32 *row = out->data.F32[r]; // n.b. a copy of in
                psU8 *mrow = mask->data.U8[r];
                for (int c = 0; c < numCols; c++) {
                    if (mrow[c] & bits) {
                        row[c] = val;
                    }
                }
            }
        }
        break;
      default:
        psError(POIS_ERR_UNSUPPORTED_TYPE, true,
                "Type %d is not supported", in->type.type);
        return NULL;
    }

    return out;
}
