classdef Extra_morphs < matlab.apps.AppBase

    % Properties that correspond to app components
    properties (Access = public)
        UIFigure                matlab.ui.Figure
        InfButton               matlab.ui.control.Button
        KernelsizeSpinnerLabel  matlab.ui.control.Label
        KernelsizeSpinner       matlab.ui.control.Spinner
        ResetButton             matlab.ui.control.Button
        SetAsWorkingButton      matlab.ui.control.Button
        InverseButton           matlab.ui.control.StateButton
        EditeImageLabel         matlab.ui.control.Label
        WorkImageLabel          matlab.ui.control.Label
        MethodDropDown          matlab.ui.control.DropDown
        MethodDropDownLabel     matlab.ui.control.Label
        LoadImageButton         matlab.ui.control.Button
        EditedImageAxes         matlab.ui.control.UIAxes
        WorkImageAxes           matlab.ui.control.UIAxes
    end

    
    properties (Access = private)
        OriginalImage
        WorkImage
        EditedImage
        MethodIndex
    end
    
    methods (Access = private)
        
        
        function results = DrawWorkImage(app)
            imshow(app.WorkImage,'Parent',app.WorkImageAxes);
        end
        function results = DrawEditedImage(app)
            imshow(app.EditedImage,'Parent',app.EditedImageAxes);
        end
        function result = ApplyMethod(app)
            if app.MethodDropDown.ValueIndex<5
                lst= {@imerode, @imdilate, @imopen, @imclose};
                app.EditedImage = lst{app.MethodDropDown.ValueIndex}(app.WorkImage,ones(app.KernelsizeSpinner.Value));
            elseif app.MethodDropDown.ValueIndex>5
                app.EditedImage = bwmorph(app.WorkImage,app.MethodDropDown.Items{app.MethodIndex},app.KernelsizeSpinner.Value);
            else
                app.EditedImage = bwmorph(app.WorkImage,"remove");
            end
            app.DrawEditedImage;
        end
        
    end
    

    % Callbacks that handle component events
    methods (Access = private)

        % Code that executes after component creation
        function startupFcn(app)
            app.WorkImage = zeros(60,60);
            app.EditedImage = zeros(60,60);
            app.MethodIndex = 1;
            app.WorkImageAxes.Visible = 'off';
            app.EditedImageAxes.Visible = 'off';
            app.KernelsizeSpinner.Visible = "off";
            app.ResetButton.Visible = "off";
            app.SetAsWorkingButton.Visible = "off";
            app.InverseButton.Visible = "off";
            app.EditeImageLabel.Visible ="off";
            app.WorkImageLabel.Visible = "off";
            app.MethodDropDown.Visible= "off";
            app.MethodDropDownLabel.Visible = "off";
            app.KernelsizeSpinnerLabel.Visible = "off";
            app.InfButton.Visible = "off";
            

        end

        % Button pushed function: LoadImageButton
        function LoadImageButtonPushed(app, event)
            try
            [file, path] = uigetimagefile;
            if ~isempty(file)
                app.OriginalImage = imbinarize(rgb2gray(double(imread(file))/255));
                app.WorkImage = app.OriginalImage;
                app.ApplyMethod;
                app.DrawWorkImage;
                app.DrawEditedImage
                app.InverseButton.Value=0;
            app.WorkImageAxes.Visible = 'on';
            app.EditedImageAxes.Visible = 'on';
            app.KernelsizeSpinner.Visible = "on";
            app.ResetButton.Visible = "on";
            app.SetAsWorkingButton.Visible = "on";
            app.InverseButton.Visible = "on";
            app.EditeImageLabel.Visible ="on";
            app.WorkImageLabel.Visible = "on";
            app.MethodDropDown.Visible= "on";
            app.MethodDropDownLabel.Visible = "on";
            app.KernelsizeSpinnerLabel.Visible = "on";
            end
            catch e
                uialert(app.UIFigure, e.message, "Error while loading image",Interpreter="html");
            end
        end

        % Value changed function: MethodDropDown
        function MethodDropDownValueChanged(app, event)
            value = app.MethodDropDown.ValueIndex;
            app.MethodIndex = value;
            KvN = [1,1,1,1,2,0,0,0,0];
            if KvN(value)==1
                app.KernelsizeSpinner.Visible = "on";
                app.KernelsizeSpinnerLabel.Text = "Kernel Size";
                app.KernelsizeSpinner.Limits = [3,Inf];
                app.KernelsizeSpinner.Step = 2;
                if app.KernelsizeSpinner.Value < 3
                app.KernelsizeSpinner.Value = 3;
                elseif ~mod(app.KernelsizeSpinner.Value,2)
                    app.KernelsizeSpinner.Value = app.KernelsizeSpinner.Value-1;
                end
                app.InfButton.Visible = "off";
            elseif KvN(value) == 2
                app.KernelsizeSpinner.Visible = "off";
                app.InfButton.Visible = "off";
            else
                app.KernelsizeSpinner.Visible="on";
                app.KernelsizeSpinnerLabel.Text = "N";
                app.KernelsizeSpinner.Limits = [1,Inf];
                app.KernelsizeSpinner.Value = 1;
                app.KernelsizeSpinner.Step = 1;
                app.InfButton.Visible = "on";
            end
           
            app.ApplyMethod;
            app.DrawEditedImage;
        end

        % Button pushed function: InfButton
        function InfButtonPushed(app, event)
            app.KernelsizeSpinner.Value = Inf;
            app.ApplyMethod;
            app.DrawEditedImage;
        end

        % Button pushed function: ResetButton
        function ResetButtonPushed(app, event)
            app.WorkImage = app.OriginalImage;
            app.InverseButton.Value = 0;
            app.ApplyMethod;
            app.DrawEditedImage;
            app.DrawWorkImage;
        end

        % Button pushed function: SetAsWorkingButton
        function SetAsWorkingButtonPushed(app, event)
            app.WorkImage = app.EditedImage;
            app.ApplyMethod;
            app.DrawEditedImage;
            app.DrawWorkImage;
        end

        % Value changed function: KernelsizeSpinner
        function KernelsizeSpinnerValueChanged(app, event)
            value = app.KernelsizeSpinner.Value;
            app.ApplyMethod;
            app.DrawEditedImage;
        end

        % Value changed function: InverseButton
        function InverseButtonValueChanged(app, event)
            app.WorkImage = ~app.WorkImage;
            app.EditedImage = ~app.EditedImage;
            app.DrawEditedImage;
            app.DrawWorkImage;
        end
    end

    % Component initialization
    methods (Access = private)

        % Create UIFigure and components
        function createComponents(app)

            % Create UIFigure and hide until all components are created
            app.UIFigure = uifigure('Visible', 'off');
            app.UIFigure.Position = [100 100 1280 1114];
            app.UIFigure.Name = 'MATLAB App';

            % Create WorkImageAxes
            app.WorkImageAxes = uiaxes(app.UIFigure);
            app.WorkImageAxes.XTick = [];
            app.WorkImageAxes.YTick = [];
            app.WorkImageAxes.Position = [15 568 840 532];

            % Create EditedImageAxes
            app.EditedImageAxes = uiaxes(app.UIFigure);
            app.EditedImageAxes.Toolbar.Visible = 'off';
            app.EditedImageAxes.XTick = [];
            app.EditedImageAxes.YTick = [];
            app.EditedImageAxes.Position = [14 35 841 516];

            % Create LoadImageButton
            app.LoadImageButton = uibutton(app.UIFigure, 'push');
            app.LoadImageButton.ButtonPushedFcn = createCallbackFcn(app, @LoadImageButtonPushed, true);
            app.LoadImageButton.Position = [1072 1076 100 23];
            app.LoadImageButton.Text = 'Load Image';

            % Create MethodDropDownLabel
            app.MethodDropDownLabel = uilabel(app.UIFigure);
            app.MethodDropDownLabel.HorizontalAlignment = 'right';
            app.MethodDropDownLabel.Position = [1093 1046 45 22];
            app.MethodDropDownLabel.Text = 'Method';

            % Create MethodDropDown
            app.MethodDropDown = uidropdown(app.UIFigure);
            app.MethodDropDown.Items = {'erode', 'dilate', 'open', 'close', 'remove', 'shrink', 'thin', 'thicken', 'skel'};
            app.MethodDropDown.ItemsData = {'1', '2', '3', '4', '5', '6', '7', '8', '9'};
            app.MethodDropDown.ValueChangedFcn = createCallbackFcn(app, @MethodDropDownValueChanged, true);
            app.MethodDropDown.Position = [1154 1046 100 22];
            app.MethodDropDown.Value = '1';

            % Create WorkImageLabel
            app.WorkImageLabel = uilabel(app.UIFigure);
            app.WorkImageLabel.Position = [52 1093 85 22];
            app.WorkImageLabel.Text = 'Working image';

            % Create EditeImageLabel
            app.EditeImageLabel = uilabel(app.UIFigure);
            app.EditeImageLabel.Position = [53 547 75 22];
            app.EditeImageLabel.Text = 'Edited image';

            % Create InverseButton
            app.InverseButton = uibutton(app.UIFigure, 'state');
            app.InverseButton.ValueChangedFcn = createCallbackFcn(app, @InverseButtonValueChanged, true);
            app.InverseButton.Text = 'Inverse';
            app.InverseButton.Position = [1172 1076 100 23];

            % Create SetAsWorkingButton
            app.SetAsWorkingButton = uibutton(app.UIFigure, 'push');
            app.SetAsWorkingButton.ButtonPushedFcn = createCallbackFcn(app, @SetAsWorkingButtonPushed, true);
            app.SetAsWorkingButton.Position = [967 528 100 23];
            app.SetAsWorkingButton.Text = 'Set as Working';

            % Create ResetButton
            app.ResetButton = uibutton(app.UIFigure, 'push');
            app.ResetButton.ButtonPushedFcn = createCallbackFcn(app, @ResetButtonPushed, true);
            app.ResetButton.Position = [966 1077 100 23];
            app.ResetButton.Text = 'Reset';

            % Create KernelsizeSpinner
            app.KernelsizeSpinner = uispinner(app.UIFigure);
            app.KernelsizeSpinner.Step = 2;
            app.KernelsizeSpinner.Limits = [3 Inf];
            app.KernelsizeSpinner.RoundFractionalValues = 'on';
            app.KernelsizeSpinner.ValueChangedFcn = createCallbackFcn(app, @KernelsizeSpinnerValueChanged, true);
            app.KernelsizeSpinner.Position = [1153 1014 68 22];
            app.KernelsizeSpinner.Value = 3;

            % Create KernelsizeSpinnerLabel
            app.KernelsizeSpinnerLabel = uilabel(app.UIFigure);
            app.KernelsizeSpinnerLabel.HorizontalAlignment = 'right';
            app.KernelsizeSpinnerLabel.Position = [1074 1014 64 22];
            app.KernelsizeSpinnerLabel.Text = 'Kernel size';

            % Create InfButton
            app.InfButton = uibutton(app.UIFigure, 'push');
            app.InfButton.ButtonPushedFcn = createCallbackFcn(app, @InfButtonPushed, true);
            app.InfButton.Position = [1220 1013 34 23];
            app.InfButton.Text = 'Inf';

            % Show the figure after all components are created
            app.UIFigure.Visible = 'on';
        end
    end

    % App creation and deletion
    methods (Access = public)

        % Construct app
        function app = Extra_morphs

            % Create UIFigure and components
            createComponents(app)

            % Register the app with App Designer
            registerApp(app, app.UIFigure)

            % Execute the startup function
            runStartupFcn(app, @startupFcn)

            if nargout == 0
                clear app
            end
        end

        % Code that executes before app deletion
        function delete(app)

            % Delete UIFigure when app is deleted
            delete(app.UIFigure)
        end
    end
end