# include "psphotInternal.h"

/*
 * Grow a psArray of pmFootprints isotropically by r pixels, returning a new psArray of new pmFootprints
 */
psArray *pmFootprintArrayGrow(const psArray *footprints, // footprints to grow
			      int r) {	// how much to grow each footprint
    assert (footprints->n == 0 || pmFootprintTest(footprints->data[0]));

    psTimerStart ("grow");

    if (footprints->n == 0) {		// we don't know the size of the footprint's region
	return psArrayAlloc(0);
    }
    /*
     * We'll insert the footprints into an image, then convolve with a disk,
     * then extract a footprint from the result --- this is magically what we want.
     */
    psImage *idImage = pmSetFootprintArrayIDs(footprints, true);
    psLogMsg ("psphot", PS_LOG_DETAIL, "set footprint array IDs: %f sec\n", psTimerMark ("grow"));

    if (r <= 0) {
	r = 1;				// r == 1 => no grow
    }
    psKernel *circle = psKernelAlloc(-r, r, -r, r);
    assert (circle->image->numRows == 2*r + 1 && circle->image->numCols == circle->image->numRows);
    for (int i = 0; i <= r; i++) {
	for (int j = 0; j <= r; j++) {
	    if (i*i + j*j <= r*r) {
		circle->kernel[i][j] = 
		    circle->kernel[i][-j] = 
		    circle->kernel[-i][j] = 
		    circle->kernel[-i][-j] = 1;
	    }
	}
    }

# if (1)    
    psImage *f32ImageIn = psImageCopy (NULL, idImage, PS_TYPE_F32);
    psImage *f32ImageOut = psImageConvolveFFT(NULL, f32ImageIn, NULL, 0, circle);
    psImage *grownIdImage = psImageCopy (NULL, f32ImageOut, PS_TYPE_S32);
    psFree (f32ImageIn);
    psFree (f32ImageOut);
# else
    psImage *grownIdImage = psImageConvolveDirect(NULL, idImage, circle); // Here's the actual grow step
# endif

    psLogMsg ("psphot", PS_LOG_DETAIL, "convolved with grow disc: %f sec\n", psTimerMark ("grow"));
    psFree(circle);	

    psArray *grown = pmFootprintsFind(grownIdImage, 0.5, 1); // and here we rebuild the grown footprints
    psLogMsg ("psphot", PS_LOG_DETAIL, "found grown footprints: %f sec\n", psTimerMark ("grow"));

    assert (grown != NULL);
    psFree(idImage); psFree(grownIdImage);
    /*
     * Now assign the peaks appropriately.  We could do this more efficiently
     * using grownIdImage (which we just freed), but this is easy and probably fast enough
     */
    const psArray *peaks = pmFootprintArrayToPeaks(footprints);
    pmFootprintsAssignPeaks(grown, peaks);
    psFree((psArray *)peaks);

    psLogMsg ("psphot", PS_LOG_DETAIL, "finished grow: %f sec\n", psTimerMark ("grow"));

    return grown;
    
}

