//
//  PRCustTraceEdges.m
//  PRICE
//
//  Created by Riccardo Mottola on Fri Mar 19 2004.
//  Copyright (c) 2004 Carduus. All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under the terms of the version 2 of the GNU General Public License as published by the Free Software Foundation.
// 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.

#import "PRCustTraceEdges.h"
#import "PRTraceEdges.h"
#import "PRMedian.h"
#import "PRGrayscaleFilter.h"
#import <math.h>
#import <limits.h>


@implementation PRCustTraceEdges

- (PRImage *)edgeImage :(PRImage *)srcImage :(int)filterType :(float)thresholdLevel :(BOOL)useZeroCross :(BOOL)enable1 :(enum medianForms)form1 :(int)size1 :(BOOL)separable1 :(BOOL)enable2 :(enum medianForms)form2 :(int)size2 :(BOOL)separable2 :(BOOL) enable3 :(enum medianForms)form3 :(int)size3 :(BOOL)separable3 :(PRCProgress *)prPanel
{
    NSBitmapImageRep  *srcImageRep;
    unsigned char     *srcData;
    PRImage           *destImage;
    NSBitmapImageRep  *destImageRep;
    unsigned char     *destData;
    PRImage           *firstImage, *secondImage, *thirdImage;
    NSBitmapImageRep  *firstImageRep, *secondImageRep, *thirdImageRep;
    unsigned char     *fiData, *siData, *tiData;
    int               w, h;
    int               i;
    int               bytesPerPixel;
    int               pixNum;
    PRMedian          *medianFilter;
    PRTraceEdges      *edgeFilter;
    int               finalLevels;
    int               finalLevelSize;
    
    progressSteps = 0;
    totalProgressSteps = 1;
    if (enable1)
        totalProgressSteps += 2;
    if (enable2)
        totalProgressSteps += 2;
    if (enable3)
        totalProgressSteps += 2;
    
    if (!enable1 && !enable2 && !enable3) /* if none of the median processors is enabled */
         totalProgressSteps++;
    
    progPanel = prPanel;
    
    /* check the number of images to process */
    finalLevels = 0;
    if (enable1)
        finalLevels++;
    if (enable2)
        finalLevels++;
    if (enable3)
        finalLevels++;
    finalLevelSize = UCHAR_MAX / finalLevels;
    
    printf("Level number: %d\n", finalLevels);
    
    /* get source image representation and associated information */
    if (progPanel != nil)
    {
        [self setActivity:@"Get image size"];
        [self advanceProgress];
    }
    srcImageRep = [srcImage tiffRep];
    
    w = [srcImageRep pixelsWide];
    h = [srcImageRep pixelsHigh];
    pixNum = h * w;
    printf("pixels: %d\n", pixNum);
    bytesPerPixel = [srcImageRep bitsPerPixel] /8;
    
    /* check bith depth and color/greyscale image */
    if ([srcImageRep hasAlpha])
    {
        if ([srcImageRep samplesPerPixel] == 2)
        {
//            printf("Grayscale image\n");
        }
        else
        {
            PRGrayscaleFilter *grayFilter;
            grayFilter = [[PRGrayscaleFilter alloc] init];
            srcImage = [grayFilter filterImage:srcImage];
            [grayFilter release];
            NSLog (@"done greyscale converting");
            /* we reget previous information that is no longer valid */
            /* get source image representation and associated information */
            srcImageRep = [NSBitmapImageRep imageRepWithData:[srcImage TIFFRepresentation]];
            bytesPerPixel = [srcImageRep bitsPerPixel] /8;
        }
    }
    else
    {
        if ([srcImageRep samplesPerPixel] == 1)
        {
            printf("Grayscale image\n");
        }
        else
        {
            PRGrayscaleFilter *grayFilter;
            grayFilter = [[PRGrayscaleFilter alloc] init];
            srcImage = [[grayFilter filterImage:srcImage] retain];
            [grayFilter release];
            NSLog (@"done greyscale converting");
            /* we reget previous information that is no longer valid */
            /* get source image representation and associated information */
            srcImageRep = [NSBitmapImageRep imageRepWithData:[srcImage TIFFRepresentation]];
            bytesPerPixel = [srcImageRep bitsPerPixel] /8;
        }
    }

    /* allocate destination image and its representation */
    destImage = [[PRImage alloc] initWithSize:NSMakeSize(w, h)];
    destImageRep = [[NSBitmapImageRep alloc]
                    initWithBitmapDataPlanes:NULL
                    pixelsWide:w
                    pixelsHigh:h
                    bitsPerSample:8
                    samplesPerPixel:1
                    hasAlpha:NO
                    isPlanar:NO
                    colorSpaceName:NSCalibratedWhiteColorSpace
                    bytesPerRow:0
                    bitsPerPixel:0];
    
    destData = [destImageRep bitmapData];
    
    /* let's make the paper white */
    memset(destData, UCHAR_MAX, pixNum);

    /* allocate filters */
    medianFilter = [[PRMedian alloc] init];
    edgeFilter   = [[PRTraceEdges alloc] init];

    if (finalLevels > 0)
    {
        if (enable1)
        {
            if (progPanel != nil)
            {
                [self setActivity:@"Processing image 1: median"];
                [self advanceProgress];
            }
            firstImage  = [medianFilter medianImage :srcImage :form1 :size1 :separable1 :NULL];
            if (progPanel != nil)
            {
                [self setActivity:@"Processing image 1: trace edges"];
                [self advanceProgress];
            }
            firstImage  = [edgeFilter edgeImage :firstImage  :filterType :YES :thresholdLevel :useZeroCross];
            firstImageRep = [NSBitmapImageRep imageRepWithData:[firstImage TIFFRepresentation]];
            fiData = [firstImageRep bitmapData];
            for (i = 0; i < pixNum; i++)
            {
                if (*(fiData + i) == 0)
                    *(destData + i) -= finalLevelSize;
            }
        }
        
        if (enable2)
        {
            if (progPanel != nil)
            {
                [self setActivity:@"Processing image 2: median"];
                [self advanceProgress];
            }
            secondImage = [medianFilter medianImage :srcImage :form2 :size2 :separable2 :NULL];
            if (progPanel != nil)
            {
                [self setActivity:@"Processing image 2: trace edges"];
                [self advanceProgress];
            }
            secondImage = [edgeFilter edgeImage :secondImage :filterType :YES :thresholdLevel :useZeroCross];
            secondImageRep = [NSBitmapImageRep imageRepWithData:[secondImage TIFFRepresentation]];
            siData = [secondImageRep bitmapData];
            for (i = 0; i < pixNum; i++)
            {
                if (*(siData + i) == 0)
                    *(destData + i) -= finalLevelSize;
            }
        }
        
        if (enable3)
        {
            if (progPanel != nil)
            {
                [self setActivity:@"Processing image 3: median"];
                [self advanceProgress];
            }
            thirdImage  = [medianFilter medianImage :srcImage :form3 :size3 :separable3 :NULL];
            if (progPanel != nil)
            {
                [self setActivity:@"Processing image 3: trace edges"];
                [self advanceProgress];
            }
            thirdImage  = [edgeFilter edgeImage :thirdImage  :filterType :YES :thresholdLevel :useZeroCross];
            thirdImageRep = [NSBitmapImageRep imageRepWithData:[thirdImage TIFFRepresentation]];
            tiData = [thirdImageRep bitmapData];
            for (i = 0; i < pixNum; i++)
            {
                if (*(tiData + i) == 0)
                    *(destData + i) -= finalLevelSize;
            }
        }
    } else
    {
        /* no median processing */
        /* we conventionally process the image */
        if (progPanel != nil)
        {
            [self setActivity:@"Processing image: trace edges"];
            [self advanceProgress];
        }
        srcImage  = [edgeFilter edgeImage :srcImage  :filterType :YES :thresholdLevel :useZeroCross];
        srcImageRep = [NSBitmapImageRep imageRepWithData:[srcImage TIFFRepresentation]];
        srcData = [srcImageRep bitmapData];
        for (i = 0; i < pixNum; i++)
        {
            if (*(srcData + i) == 0)
                *(destData + i) = 0;
        }
    }
    
    /* release filters */
    [medianFilter release];
    [edgeFilter release];

    if (progPanel != nil)
    {
        [self setActivity:@"Done"];
        [self showProgress];
    }
    
    [destImage addRepresentation:destImageRep];
    [destImageRep release];
    [destImage autorelease];
    return destImage;
}

@end
