Author Topic: New script: aberration-spotter.js  (Read 10007 times)

Offline David Serrano

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 503
New script: aberration-spotter.js
« on: 2007 October 10 07:06:47 »
Code: [Select]
/*
    aberration-spotter.js v0.1 - Group the corners of an image in another one
    Copyright (C) 2007  David Serrano

    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, version 3 of the License.

    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, see <http://www.gnu.org/licenses/>.
*/

/*
    Changelog:
    0.1:   Initial version.
*/

#define VERSION "0.1"
#define SURNAME "_corners"
#define SET_PREFIX "aberration_spotter"

#include <pjsr/DataType.jsh>
#include <pjsr/FrameStyle.jsh>
#include <pjsr/NumericControl.jsh>
#include <pjsr/SampleType.jsh>
#include <pjsr/Sizer.jsh>
#include <pjsr/UndoFlag.jsh>

#feature-id AberrationSpotter
#feature-info Simple script that creates an image containing the corners \
    and, optionally, the center of another image. Useful to highlight \
    the aberrations of the optical elements used.
//#feature-icon aberration-spotter.xpm

function AS_user_data() {
    this.hsize = 150;         // pixels
    this.vsize = 150;         // pixels
    this.show_center = true;
    this.sep = 50;            // percent
    this.bgcolor = 0.25;      // normalized value
    this.delete_settings = false;
}
var user_data = new AS_user_data;

function AS_engine() {
    var rect = new Rect;   // for creating previews...
    var points;            // ...we'll move rect to these points
    var dest_points;       // points in the destination image
    var win;               // original window
    var sep;               // user_data.sep translated into pixels
    // randomized ids, to avoid clashing with (maybe) existing ones
    var preview_ids = new Array (
        "UL_so8fh", "UR_so8fh",
        "LL_so8fh", "LR_so8fh",
        "C_so8fh"
    );

    this.set_win = function (w) {
        if (w.isNull) {
            throw Error ("Invalid/No image window.");
        }

        this.win = w;
    }

    this._calc_sep = function() {
        if (user_data.show_center) {
            this.sep = Math.floor (
                Math.min (user_data.hsize, user_data.vsize) * user_data.sep / 100
            );
            if (this.sep < 1) this.sep = 1;
        } else {
            this.sep = 1;
        }
    }

    // creates points in both the original and destination images
    this._create_points = function() {
        var img = this.win.mainView.image;
        if (!user_data.show_center) {
            preview_ids.pop();     // remove "C" from its elements
        }

        // source points
        this.points = new Array;
        this.points[preview_ids[0]] = new Point (0, 0);
        this.points[preview_ids[1]] = new Point (img.width - user_data.hsize - 1, 0);
        this.points[preview_ids[2]] = new Point (0, img.height - user_data.vsize - 1);
        this.points[preview_ids[3]] = new Point (
            img.width  - user_data.hsize - 1,
            img.height - user_data.vsize - 1
        );
        if (user_data.show_center) {
            this.points[preview_ids[4]] = new Point (
                Math.floor (img.bounds.center.x - user_data.hsize / 2),
                Math.floor (img.bounds.center.y - user_data.vsize / 2)
            );
        }

        // destination points
        this.dest_points = new Array;
        this.dest_points[preview_ids[0]] = new Point (0, 0);
        this.dest_points[preview_ids[1]] = new Point (user_data.hsize + this.sep, 0);
        this.dest_points[preview_ids[2]] = new Point (0, user_data.vsize + this.sep);
        this.dest_points[preview_ids[3]] = new Point (
            user_data.hsize + this.sep,
            user_data.vsize + this.sep
        );
        if (user_data.show_center) {
            this.dest_points[preview_ids[4]] = new Point (Math.floor (
                // dest image isn't created yet, so we have to guess its center
                // we'll use the same operation to create the image later
                (2 * user_data.hsize + this.sep) / 2 - (user_data.hsize / 2)
            ), Math.floor (
                (2 * user_data.vsize + this.sep) / 2 - (user_data.vsize / 2)
            ));
        }
    }

    this._create_previews = function() {
        // why "rect" instead of "this.rect"????
        rect.width  = user_data.hsize;
        rect.height = user_data.vsize;

        for (var i in preview_ids) {
            var str = preview_ids[i];
            rect.moveTo (this.points[str]);
            this.win.createPreview (rect, str);
        }
    }

    this._join_previews = function() {
        var v = this.win.mainView;
        // create destination image
        var dest = new ImageWindow (
            2 * user_data.hsize + this.sep,
            2 * user_data.vsize + this.sep,
            3, v.image.bitsPerSample,
            v.image.sampleType == SampleType_Real,
            true, v.id + SURNAME
        );
        with (dest.mainView) {
            beginProcess (UndoFlag_NoSwapFile);
            with (image) {
                fill (user_data.bgcolor);

                // copy previews into the destination image. Not the central one
                for (var i = 0; i < 4; i++) {
                    selectedPoint = this.dest_points[preview_ids[i]];
                    apply (this.win.previewById (preview_ids[i]).image);
                }
                resetSelections();

                // fill the center and put the central image over it
                if (user_data.show_center) {
                    var p = this.dest_points[preview_ids[4]];

                    // but only draw the "border" if separation is less than 100%
                    if (user_data.sep < 100) {
                        selectedRect = new Rect (
                            p.x - 1,
                            p.y - 1,
                            p.x + user_data.hsize + 1,
                            p.y + user_data.vsize + 1
                        );
                        fill (user_data.bgcolor);
                    }

                    selectedPoint = p;
                    apply (this.win.previewById (preview_ids[4]).image);
                }
            }
            endProcess();
        }
        dest.show();
    }

    this._destroy_all = function() {
        this.points = null;
        this.dest_points = null;
        for (var i = 0; i < preview_ids.length; i++) {
            this.win.deletePreview (this.win.previewById (preview_ids[i]));
        }
        rect = null;
        gc();
    }

    this.work = function() {
        this._calc_sep();
        this._create_points();
        this._create_previews();
        this._join_previews();
        this._destroy_all();
    }
}
var engine = new AS_engine;

function AS_dialog() {
    this.__base__ = Dialog;
    this.__base__();

    // help label
    this.helpLabel = new Label (this);
    with (this.helpLabel) {
        frameStyle = FrameStyle_Box;
        margin = 4;
        wordWrapping = true;
        useRichText = true;
        text = "<b>AberrationSpotter v"+VERSION+"</b> - A " +
            "script to take the corners of an existing image and putting " +
            "them in another image. Optionally takes the center too. You " +
            "can choose the background brightness and the separation of " +
            "the corners (only if showing the center).";
    }

    // horizontal size
    this.hsize_NC = new NumericControl (this);
    with (this.hsize_NC) {
        label.text = "Horizontal size:";
        setRange (2, 500);
        slider.setRange (0, 498);
        slider.minWidth = 510;
        setPrecision (0);
        setValue (user_data.hsize);
        toolTip = "Horizontal size of each image portion."
        onValueUpdated = function (value) { user_data.hsize = value; }
    }

    // vertical size
    this.vsize_NC = new NumericControl (this);
    with (this.vsize_NC) {
        label.text = "Vertical size:";
        setRange (2, 500);
        slider.setRange (0, 498);
        slider.minWidth = 510;
        setPrecision (0);
        setValue (user_data.vsize);
        toolTip = "Vertical size of each image portion."
        onValueUpdated = function (value) { user_data.vsize = value; }
    }

    // separation
    this.sep_NC = new NumericControl (this);
    with (this.sep_NC) {
        label.text = "Separation between portions (percent):";
        setRange (0, 100);
        slider.setRange (0, 101);
        slider.minWidth = 110;
        setPrecision (0);
        setValue (user_data.sep);
        toolTip = "Portions of the image will be separated this amount. It " +
            "represents a percentage over the size of each portion. Ignored " +
            "if we're not showing the center.";
        onValueUpdated = function (value) { user_data.sep = value; }
    }

    // background color
    this.bc_NC = new NumericControl (this);
    with (this.bc_NC) {
        label.text = "Background brightness:";
        setRange (0, 1);
        slider.setRange (0, 101);
        slider.minWidth = 110;
        setPrecision (2);
        setValue (user_data.bgcolor);
        toolTip = "Brightness of background. 0 is black and 1 is white.";
        onValueUpdated = function (value) { user_data.bgcolor = value; }
    }

    // show center checkbox
    this.sc_CB = new CheckBox (this);
    with (this.sc_CB) {
        text = "Show center";
        checked = user_data.show_center;
        toolTip = "Check to show the center portion of the image. The " +
            "separation is ignored if the center isn't to be shown.";
        onCheck = function (checked) { user_data.show_center = checked; }
    }

    // delete settings checkbox
    this.ds_CB = new CheckBox (this);
    with (this.ds_CB) {
        text = "Delete settings and exit";
        checked = user_data.delete_settings;
        onCheck = function (checked) { user_data.delete_settings = checked; }
        toolTip = "Check to remove the stored settings and exit the program.";
    }

    // buttons
    this.ok_Button = new PushButton (this);
    this.ok_Button.text = " OK ";
    this.ok_Button.onClick = function() { this.dialog.ok(); };

    this.cancel_Button = new PushButton (this);
    this.cancel_Button.text = " Cancel ";
    this.cancel_Button.onClick = function() { this.dialog.cancel(); };

    this.buttons_Sizer = new HorizontalSizer;
    this.buttons_Sizer.spacing = 4;
    this.buttons_Sizer.addStretch();
    this.buttons_Sizer.add (this.ok_Button);
    this.buttons_Sizer.add (this.cancel_Button);

    // pack everything
    this.sizer = new VerticalSizer;
    with (this.sizer) {
        margin = 6;
        spacing = 6;
        add (this.helpLabel);
        addSpacing (4);
        add (this.hsize_NC);
        add (this.vsize_NC);
        add (this.sep_NC);
        add (this.bc_NC);
        add (this.sc_CB);
        add (this.ds_CB);
        add (this.buttons_Sizer);
    }

    this.windowTitle = "AberrationSpotter v" + VERSION;
    this.adjustToContents();

}
AS_dialog.prototype = new Dialog;

function AS_settings() {
    var conf = new Array (
        // important: use the same name as the user_data variables
        new Array ("hsize", DataType_UInt16),
        new Array ("vsize", DataType_UInt16),
        new Array ("show_center", DataType_Boolean),
        new Array ("sep", DataType_UInt16),
        new Array ("bgcolor", DataType_Float)
    );

    this.load = function() {
        var temp;

        for (var i in conf) {
            var str  = conf[i][0];
            var type = conf[i][1];

            temp = Settings.read (SET_PREFIX + "/" + str, type);
            if (Settings.lastReadOK) {
                user_data[str] = temp;
            } else {
                console.writeln (format (
                    "Couldn't read setting '%s/%s'", SET_PREFIX, str
                ));
            }
        }
    }

    this.save = function() {
        for (var i in conf) {
            var str  = conf[i][0];
            var type = conf[i][1];

            Settings.write (SET_PREFIX + "/" + str, type, user_data[str]);
        }
    }

    this.del = function() {
        Settings.remove (SET_PREFIX);
    }
}
var AS_settings = new AS_settings;

function main() {
    engine.set_win (ImageWindow.activeWindow);

    AS_settings.load();

    var dialog = new AS_dialog;   // has to be done after settings are loaded
    if (!dialog.execute()) {
        return;
    }

    if (user_data.delete_settings) {
        AS_settings.del();
        return;
    } else {
        AS_settings.save();
    }

    engine.work();
}

main();
--
 David Serrano

Offline David Serrano

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 503
New script: aberration-spotter.js
« Reply #1 on: 2007 October 10 07:11:19 »
Buenas. Este es el script que he estado haciendo durante estos días. Coge las esquinas de una imagen y las pone en otra imagen más pequeña para facilitar la comparación entre ellas. Opcionalmente también coge el centro. Permite especificar el tamaño a usar, y la separación entre ellas. Podría poner alguna captura de pantalla pero estoy un poco vago y con un par de pruebas, el funcionamiento resulta obvio.

Espero que os guste.


Hi. This is the script I've been working lately. It takes the corners of an image and puts them in another smaller one for making it easier to compare them. Optionally it takes the center too. You can specify the size and separation between image portions. I could show you some screenshots but I'm feeling lazy right now and it takes no more than a couple of quick tests to discover how it works.

I hope you like it.
--
 David Serrano

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
New script: aberration-spotter.js
« Reply #2 on: 2007 October 10 08:48:07 »
Hi David,

Fantastic! I love it! :)

Great work. Can we add this one to the default set of featured scripts starting from the next version? BTW, I want to do the same with iterative stretch and k-sigma, but was waiting until you get them more polished ;)
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline Jordi Gallego

  • PixInsight Addict
  • ***
  • Posts: 279
New script: aberration-spotter.js
« Reply #3 on: 2007 October 10 11:56:06 »
David,

funciona de maravilla!, muchas gracias de nuevo por este otro magnífico script :wink:

Saludos
Jordi
Jordi Gallego
www.astrophoto.es

Offline David Serrano

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 503
New script: aberration-spotter.js
« Reply #4 on: 2007 October 10 13:07:47 »
Quote from: "Juan Conejero"
Can we add this one to the default set of featured scripts starting from the next version? BTW, I want to do the same with iterative stretch and k-sigma, but was waiting until you get them more polished ;)


Oh yes, será un honor :). Al masked-stretch-transform todavía le quería poner una chorradita más: un diálogo mostrando algo como "Try %d, iteration %d" mientras calcula MTF, y luego quizá "Final image, iteration %d". Y también integrar lo del undoAll, por supuesto.

Por cierto, muchas felicitationes por la versión final ;). Yo aún no la he bajado :oops:.
--
 David Serrano

Offline C. Sonnenstein

  • PixInsight Addict
  • ***
  • Posts: 262
    • http://astrosurf.com/astro35mm
New script: aberration-spotter.js
« Reply #5 on: 2007 October 10 14:35:47 »
Hello 'scriptman':

Aberration-Spotter is very nice and useful. Congratulations.
Carlos Sonnenstein