001/* 002 * Copyright 2010-2015 Institut Pasteur. 003 * 004 * This file is part of Icy. 005 * 006 * Icy is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * Icy is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with Icy. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package icy.math; 020 021import icy.common.CollapsibleEvent; 022import icy.common.UpdateEventHandler; 023import icy.common.listener.ChangeListener; 024import icy.file.xml.XMLPersistent; 025import icy.type.TypeUtil; 026import icy.type.collection.array.ArrayUtil; 027import icy.util.XMLUtil; 028 029import javax.swing.event.EventListenerList; 030 031import org.w3c.dom.Node; 032 033/** 034 * @author stephane 035 */ 036public class Scaler implements ChangeListener, XMLPersistent 037{ 038 private enum ScalerRange 039 { 040 SR_ABSIN, SR_IN, SR_OUT 041 }; 042 043 private static final String ID_ABSLEFTIN = "absleftin"; 044 private static final String ID_ABSRIGHTIN = "absrightin"; 045 private static final String ID_LEFTIN = "leftin"; 046 private static final String ID_RIGHTIN = "rightin"; 047 private static final String ID_LEFTOUT = "leftout"; 048 private static final String ID_RIGHTOUT = "rightout"; 049 private static final String ID_INTEGERDATA = "integerdata"; 050 private static final String ID_CANCROSS = "cancross"; 051 052 private double absLeftIn; 053 private double absRightIn; 054 055 private double leftIn; 056 private double rightIn; 057 058 private double leftOut; 059 private double rightOut; 060 061 private double scaler; 062 private double unscaler; 063 064 private boolean integerData; 065 private boolean canCross; 066 private boolean crossed; 067 068 public double scaleLK[]; 069 070 private final EventListenerList listeners; 071 072 /** 073 * internal updater 074 */ 075 private final UpdateEventHandler updater; 076 077 public static int indexOf(Scaler[] scalers, Scaler scaler) 078 { 079 for (int i = 0; i < scalers.length; i++) 080 if (scalers[i].equals(scaler)) 081 return i; 082 083 return -1; 084 } 085 086 public static boolean contains(Scaler[] scalers, Scaler scaler) 087 { 088 return (indexOf(scalers, scaler) != -1); 089 } 090 091 /** 092 * 093 */ 094 public Scaler(double leftIn, double rightIn, double leftOut, double rightOut, boolean integerData) 095 { 096 this(leftIn, rightIn, leftIn, rightIn, leftOut, rightOut, integerData, false); 097 } 098 099 /** 100 * 101 */ 102 public Scaler(double leftIn, double rightIn, double leftOut, double rightOut, boolean integerData, boolean canCross) 103 { 104 this(leftIn, rightIn, leftIn, rightIn, leftOut, rightOut, integerData, canCross); 105 } 106 107 /** 108 * 109 */ 110 public Scaler(double absLeftIn, double absRightIn, double leftIn, double rightIn, double leftOut, double rightOut, 111 boolean integerData, boolean canCross) 112 { 113 super(); 114 115 this.absLeftIn = absLeftIn; 116 this.absRightIn = absRightIn; 117 this.leftIn = leftIn; 118 this.rightIn = rightIn; 119 this.leftOut = leftOut; 120 this.rightOut = rightOut; 121 this.integerData = integerData; 122 this.canCross = canCross; 123 124 crossed = absLeftIn > absRightIn; 125 126 if (crossed && !canCross) 127 throw new IllegalArgumentException("Can't create scaler : left > right and canCross = false"); 128 129 listeners = new EventListenerList(); 130 updater = new UpdateEventHandler(this, false); 131 132 // update scaler 133 updateScaler(false); 134 } 135 136 /** 137 * Refresh the scale lookup table 138 */ 139 private void updateLookup() 140 { 141 scaleLK = null; 142 143 if (integerData) 144 { 145 final boolean rangeOk; 146 147 if (crossed) 148 rangeOk = (absLeftIn <= 65535) && (absRightIn >= 0); 149 else 150 rangeOk = (absLeftIn >= 0) && (absRightIn <= 65535); 151 152 // use lookup table only for integer scalar value in [0..65535] range 153 if (rangeOk) 154 { 155 final int len; 156 157 if (crossed) 158 len = (int) absRightIn; 159 else 160 len = (int) absLeftIn; 161 162 scaleLK = new double[len]; 163 164 // refresh lookup table data 165 for (int i = 0; i < len; i++) 166 scaleLK[i] = scale(i); 167 } 168 } 169 } 170 171 /** 172 * Refresh the scaler value 173 */ 174 private void updateScaler(boolean notify) 175 { 176 final double deltaIn = rightIn - leftIn; 177 final double deltaOut = rightOut - leftOut; 178 179 // delta null 180 if ((deltaIn == 0) || (deltaOut == 0)) 181 scaler = 1; 182 else 183 { 184 scaler = deltaOut / deltaIn; 185 unscaler = deltaIn / deltaOut; 186 } 187 188 // refresh lookup table 189 updateLookup(); 190 191 // notify scaler changed 192 if (notify) 193 changed(); 194 } 195 196 private void checkBounds() 197 { 198 double l = leftIn; 199 double r = rightIn; 200 201 if (crossed) 202 { 203 // check absolute range first 204 if (l > absLeftIn) 205 { 206 l = absLeftIn; 207 if (r > l) 208 r = l - Float.MIN_VALUE; 209 } 210 if (r < absRightIn) 211 { 212 r = absRightIn; 213 if (l < r) 214 l = r + Float.MIN_VALUE; 215 } 216 } 217 else 218 { 219 // check absolute range first 220 if (l < absLeftIn) 221 { 222 l = absLeftIn; 223 if (r < l) 224 r = l + Float.MIN_VALUE; 225 } 226 if (r > absRightIn) 227 { 228 r = absRightIn; 229 if (l > r) 230 l = r - Float.MIN_VALUE; 231 } 232 } 233 234 // set left and right for input value 235 leftIn = l; 236 rightIn = r; 237 } 238 239 /** 240 * Sets the left and right value of specified range. 241 * 242 * @param left 243 * the new left value to set 244 * @param right 245 * the new right value to set 246 * @param range 247 * range to modify 248 * @param leftPrio 249 * priority to left border (to resolve conflict) 250 */ 251 private void setLeftRight(double left, double right, ScalerRange range, boolean leftPrio) 252 { 253 double l = left; 254 double r = right; 255 256 if ((!canCross) && (l > r)) 257 { 258 if (leftPrio) 259 r = l + Float.MIN_VALUE; 260 else 261 l = r - Float.MIN_VALUE; 262 } 263 264 switch (range) 265 { 266 case SR_ABSIN: 267 // nothing to do 268 if ((absLeftIn == l) && (absRightIn == r)) 269 return; 270 271 // update crossed information 272 crossed = l > r; 273 // set absolute left and right for input value 274 absLeftIn = l; 275 absRightIn = r; 276 // adjust current left and right for input value if they are out bounds 277 checkBounds(); 278 break; 279 280 case SR_IN: 281 // nothing to do 282 if ((leftIn == l) && (rightIn == r)) 283 return; 284 285 // update crossed information updated only on absolute 286 // crossed = l > r; 287 // set left and right for input value 288 leftIn = l; 289 rightIn = r; 290 // adjust current left and right for input value if they are out bounds 291 checkBounds(); 292 break; 293 294 case SR_OUT: 295 // nothing to do 296 if ((leftOut == l) && (rightOut == r)) 297 return; 298 299 // set left and right for output value 300 leftOut = l; 301 rightOut = r; 302 break; 303 } 304 305 // update scaler 306 updateScaler(true); 307 } 308 309 /** 310 * Scale the value 311 * 312 * @param value 313 * value to scale 314 * @return scaled output value 315 */ 316 public double scale(double value) 317 { 318 if (crossed) 319 { 320 if (value >= leftIn) 321 return leftOut; 322 else if (value <= rightIn) 323 return rightOut; 324 else 325 return ((value - leftIn) * scaler) + leftOut; 326 } 327 328 if (value <= leftIn) 329 return leftOut; 330 else if (value >= rightIn) 331 return rightOut; 332 else 333 return ((value - leftIn) * scaler) + leftOut; 334 } 335 336 /** 337 * Scale the value 338 * 339 * @param value 340 * value to scale 341 * @return scaled output value 342 */ 343 public double unscale(double value) 344 { 345 if (crossed) 346 { 347 if (value >= leftOut) 348 return leftIn; 349 else if (value <= rightOut) 350 return rightIn; 351 else 352 return ((value - leftOut) * unscaler) + leftIn; 353 } 354 355 if (value <= leftOut) 356 return leftIn; 357 else if (value >= rightOut) 358 return rightIn; 359 else 360 return ((value - leftOut) * unscaler) + leftIn; 361 } 362 363 /** 364 * Scale each value in the "src" array and return result in "dest" array 365 * 366 * @param src 367 * array of byte (unscaled values) 368 * @param srcOffset 369 * offset for src buffer 370 * @param dest 371 * result as array of int (scaled values) 372 * @param destOffset 373 * offset for dest buffer 374 * @param len 375 * length to compute 376 * @param signed 377 * signed/unsigned src data flag 378 */ 379 public void scale(Object src, int srcOffset, int[] dest, int destOffset, int len, boolean signed) 380 { 381 if ((src == null) || (dest == null)) 382 throw new IllegalArgumentException("Parameters 'src' and 'dest' should not be null !"); 383 384 switch (ArrayUtil.getDataType(src)) 385 { 386 case BYTE: 387 scale((byte[]) src, srcOffset, dest, destOffset, len, signed); 388 break; 389 390 case SHORT: 391 scale((short[]) src, srcOffset, dest, destOffset, len, signed); 392 break; 393 394 case INT: 395 scale((int[]) src, srcOffset, dest, destOffset, len, signed); 396 break; 397 398 case LONG: 399 scale((long[]) src, srcOffset, dest, destOffset, len, signed); 400 break; 401 402 case FLOAT: 403 scale((float[]) src, srcOffset, dest, destOffset, len); 404 break; 405 406 case DOUBLE: 407 scale((double[]) src, srcOffset, dest, destOffset, len); 408 break; 409 } 410 } 411 412 /** 413 * Scale each value in the "src" array and return result in "dest" array 414 * 415 * @param src 416 * array of byte (unscaled values) 417 * @param srcOffset 418 * offset for src buffer 419 * @param dest 420 * result as array of int (scaled values) 421 * @param destOffset 422 * offset for dest buffer 423 * @param len 424 * length to compute 425 * @param signed 426 * signed/unsigned src data flag 427 */ 428 public void scale(byte[] src, int srcOffset, int[] dest, int destOffset, int len, boolean signed) 429 { 430 if ((src == null) || (dest == null)) 431 throw new IllegalArgumentException("Parameters 'src' and 'dest' should not be null !"); 432 433 if (signed) 434 { 435 // signed 436 for (int i = 0; i < len; i++) 437 dest[destOffset + i] = (int) scale(src[srcOffset + i]); 438 } 439 else 440 { 441 // unsigned 442 for (int i = 0; i < len; i++) 443 dest[destOffset + i] = (int) scale(TypeUtil.unsign(src[srcOffset + i])); 444 } 445 } 446 447 /** 448 * Scale each value in the "src" array and return result in "dest" array 449 * 450 * @param src 451 * array of short (unscaled values) 452 * @param srcOffset 453 * offset for src buffer 454 * @param dest 455 * result as array of int (scaled values) 456 * @param destOffset 457 * offset for dest buffer 458 * @param len 459 * length to compute 460 * @param signed 461 * signed/unsigned src data flag 462 */ 463 public void scale(short[] src, int srcOffset, int[] dest, int destOffset, int len, boolean signed) 464 { 465 if ((src == null) || (dest == null)) 466 throw new IllegalArgumentException("Parameters 'src' and 'dest' should not be null !"); 467 468 if (signed) 469 { 470 // signed 471 for (int i = 0; i < len; i++) 472 dest[destOffset + i] = (int) scale(src[srcOffset + i]); 473 } 474 else 475 { 476 // unsigned 477 for (int i = 0; i < len; i++) 478 dest[destOffset + i] = (int) scale(TypeUtil.unsign(src[srcOffset + i])); 479 } 480 } 481 482 /** 483 * Scale each value in the "src" array and return result in "dest" array 484 * 485 * @param src 486 * array of int (unscaled values) 487 * @param srcOffset 488 * offset for src buffer 489 * @param dest 490 * result as array of int (scaled values) 491 * @param destOffset 492 * offset for dest buffer 493 * @param len 494 * length to compute 495 * @param signed 496 * signed/unsigned src data flag 497 */ 498 public void scale(int[] src, int srcOffset, int[] dest, int destOffset, int len, boolean signed) 499 { 500 if ((src == null) || (dest == null)) 501 throw new IllegalArgumentException("Parameters 'src' and 'dest' should not be null !"); 502 503 if (signed) 504 { 505 // signed 506 for (int i = 0; i < len; i++) 507 dest[destOffset + i] = (int) scale(src[srcOffset + i]); 508 } 509 else 510 { 511 // unsigned 512 for (int i = 0; i < len; i++) 513 dest[destOffset + i] = (int) scale(TypeUtil.unsign(src[srcOffset + i])); 514 } 515 } 516 517 /** 518 * Scale each value in the "src" array and return result in "dest" array 519 * 520 * @param src 521 * array of long (unscaled values) 522 * @param srcOffset 523 * offset for src buffer 524 * @param dest 525 * result as array of int (scaled values) 526 * @param destOffset 527 * offset for dest buffer 528 * @param len 529 * length to compute 530 * @param signed 531 * signed/unsigned src data flag 532 */ 533 public void scale(long[] src, int srcOffset, int[] dest, int destOffset, int len, boolean signed) 534 { 535 if ((src == null) || (dest == null)) 536 throw new IllegalArgumentException("Parameters 'src' and 'dest' should not be null !"); 537 538 if (signed) 539 { 540 // signed 541 for (int i = 0; i < len; i++) 542 dest[destOffset + i] = (int) scale(src[srcOffset + i]); 543 } 544 else 545 { 546 // unsigned 547 for (int i = 0; i < len; i++) 548 dest[destOffset + i] = (int) scale(TypeUtil.unsign(src[srcOffset + i])); 549 } 550 } 551 552 /** 553 * Scale array 554 * 555 * @param src 556 * array of float (unscaled values) 557 * @param srcOffset 558 * offset for src buffer 559 * @param dest 560 * result as array of int (scaled values) 561 * @param destOffset 562 * offset for dest buffer 563 * @param len 564 * length to compute 565 */ 566 public void scale(float[] src, int srcOffset, int[] dest, int destOffset, int len) 567 { 568 if ((src == null) || (dest == null)) 569 throw new IllegalArgumentException("Parameters 'src' and 'dest' should not be null !"); 570 571 for (int i = 0; i < len; i++) 572 dest[destOffset + i] = (int) scale(src[srcOffset + i]); 573 } 574 575 /** 576 * Scale array 577 * 578 * @param src 579 * array of double (unscaled values) 580 * @param srcOffset 581 * offset for src buffer 582 * @param dest 583 * result as array of int (scaled values) 584 * @param destOffset 585 * offset for dest buffer 586 * @param len 587 * length to compute 588 */ 589 public void scale(double[] src, int srcOffset, int[] dest, int destOffset, int len) 590 { 591 if ((src == null) || (dest == null)) 592 throw new IllegalArgumentException("Parameters 'src' and 'dest' should not be null !"); 593 594 for (int i = 0; i < len; i++) 595 dest[destOffset + i] = (int) scale(src[srcOffset + i]); 596 } 597 598 /** 599 * Scale each value in the "src" array and return result in "dest" array 600 * 601 * @param src 602 * array of byte (unscaled values) 603 * @param srcOffset 604 * offset for src buffer 605 * @param dest 606 * result as array of double (scaled values) 607 * @param destOffset 608 * offset for dest buffer 609 * @param len 610 * length to compute 611 * @param signed 612 * signed/unsigned src data flag 613 */ 614 public void scale(byte[] src, int srcOffset, double[] dest, int destOffset, int len, boolean signed) 615 { 616 if ((src == null) || (dest == null)) 617 throw new IllegalArgumentException("Parameters 'src' and 'dest' should not be null !"); 618 619 if (signed) 620 { 621 // signed 622 for (int i = 0; i < len; i++) 623 dest[destOffset + i] = scale(src[srcOffset + i]); 624 } 625 else 626 { 627 // unsigned 628 for (int i = 0; i < len; i++) 629 dest[destOffset + i] = scale(TypeUtil.unsign(src[srcOffset + i])); 630 } 631 } 632 633 /** 634 * Scale each value in the "src" array and return result in "dest" array 635 * 636 * @param src 637 * array of short (unscaled values) 638 * @param srcOffset 639 * offset for src buffer 640 * @param dest 641 * result as array of double (scaled values) 642 * @param destOffset 643 * offset for dest buffer 644 * @param len 645 * length to compute 646 * @param signed 647 * signed/unsigned src data flag 648 */ 649 public void scale(short[] src, int srcOffset, double[] dest, int destOffset, int len, boolean signed) 650 { 651 if ((src == null) || (dest == null)) 652 throw new IllegalArgumentException("Parameters 'src' and 'dest' should not be null !"); 653 654 if (signed) 655 { 656 // signed 657 for (int i = 0; i < len; i++) 658 dest[destOffset + i] = scale(src[srcOffset + i]); 659 } 660 else 661 { 662 // unsigned 663 for (int i = 0; i < len; i++) 664 dest[destOffset + i] = scale(TypeUtil.unsign(src[srcOffset + i])); 665 } 666 } 667 668 /** 669 * Scale each value in the "src" array and return result in "dest" array 670 * 671 * @param src 672 * array of int (unscaled values) 673 * @param srcOffset 674 * offset for src buffer 675 * @param dest 676 * result as array of double (scaled values) 677 * @param destOffset 678 * offset for dest buffer 679 * @param len 680 * length to compute 681 * @param signed 682 * signed/unsigned src data flag 683 */ 684 public void scale(int[] src, int srcOffset, double[] dest, int destOffset, int len, boolean signed) 685 { 686 if ((src == null) || (dest == null)) 687 throw new IllegalArgumentException("Parameters 'src' and 'dest' should not be null !"); 688 689 if (signed) 690 { 691 // signed 692 for (int i = 0; i < len; i++) 693 dest[destOffset + i] = scale(src[srcOffset + i]); 694 } 695 else 696 { 697 // unsigned 698 for (int i = 0; i < len; i++) 699 dest[destOffset + i] = scale(TypeUtil.unsign(src[srcOffset + i])); 700 } 701 } 702 703 /** 704 * Scale each value in the "src" array and return result in "dest" array 705 * 706 * @param src 707 * array of long (unscaled values) 708 * @param srcOffset 709 * offset for src buffer 710 * @param dest 711 * result as array of double (scaled values) 712 * @param destOffset 713 * offset for dest buffer 714 * @param len 715 * length to compute 716 * @param signed 717 * signed/unsigned src data flag 718 */ 719 public void scale(long[] src, int srcOffset, double[] dest, int destOffset, int len, boolean signed) 720 { 721 if ((src == null) || (dest == null)) 722 throw new IllegalArgumentException("Parameters 'src' and 'dest' should not be null !"); 723 724 if (signed) 725 { 726 // signed 727 for (int i = 0; i < len; i++) 728 dest[destOffset + i] = scale(src[srcOffset + i]); 729 } 730 else 731 { 732 // unsigned 733 for (int i = 0; i < len; i++) 734 dest[destOffset + i] = scale(TypeUtil.unsign(src[srcOffset + i])); 735 } 736 } 737 738 /** 739 * Scale array 740 * 741 * @param src 742 * array of float (unscaled values) 743 * @param srcOffset 744 * offset for src buffer 745 * @param dest 746 * result as array of double (scaled values) 747 * @param destOffset 748 * offset for dest buffer 749 * @param len 750 * length to compute 751 */ 752 public void scale(float[] src, int srcOffset, double[] dest, int destOffset, int len) 753 { 754 if ((src == null) || (dest == null)) 755 throw new IllegalArgumentException("Parameters 'src' and 'dest' should not be null !"); 756 757 for (int i = 0; i < len; i++) 758 dest[destOffset + i] = scale(src[srcOffset + i]); 759 } 760 761 /** 762 * Scale array 763 * 764 * @param src 765 * array of double (unscaled values) 766 * @param srcOffset 767 * offset for src buffer 768 * @param dest 769 * result as array of double (scaled values) 770 * @param destOffset 771 * offset for dest buffer 772 * @param len 773 * length to compute 774 */ 775 public void scale(double[] src, int srcOffset, double[] dest, int destOffset, int len) 776 { 777 if ((src == null) || (dest == null)) 778 throw new IllegalArgumentException("Parameters 'src' and 'dest' should not be null !"); 779 780 for (int i = 0; i < len; i++) 781 dest[destOffset + i] = scale(src[srcOffset + i]); 782 } 783 784 /** 785 * Scale array 786 * 787 * @param data 788 * array of float value to scale 789 * @param offset 790 * offset for buffer 791 * @param len 792 * length to compute 793 */ 794 public void scale(float[] data, int offset, int len) 795 { 796 if (data == null) 797 throw new IllegalArgumentException("Parameters 'data' should not be null !"); 798 799 for (int i = 0; i < len; i++) 800 data[offset + i] = (float) scale(data[i]); 801 } 802 803 /** 804 * Scale array 805 * 806 * @param data 807 * array of double value to scale 808 * @param offset 809 * offset for buffer 810 * @param len 811 * length to compute 812 */ 813 public void scale(double[] data, int offset, int len) 814 { 815 if (data == null) 816 throw new IllegalArgumentException("Parameters 'data' should not be null !"); 817 818 for (int i = 0; i < len; i++) 819 data[offset + i] = scale(data[i]); 820 } 821 822 /** 823 * Scale each value in the "src" array and return result in "dest" array 824 * 825 * @param src 826 * array of byte (unscaled values) 827 * @param dest 828 * result as array of int (scaled values) 829 * @param signed 830 * signed/unsigned src data flag 831 */ 832 public void scale(Object src, int[] dest, boolean signed) 833 { 834 scale(src, 0, dest, 0, ArrayUtil.getTotalLength(src), signed); 835 } 836 837 /** 838 * Scale each value in the "src" array and return result in "dest" array 839 * 840 * @param src 841 * array of byte (unscaled values) 842 * @param dest 843 * result as array of int (scaled values) 844 * @param signed 845 * signed/unsigned src data flag 846 */ 847 public void scale(byte[] src, int[] dest, boolean signed) 848 { 849 scale(src, 0, dest, 0, ArrayUtil.getTotalLength(src), signed); 850 } 851 852 /** 853 * Scale each value in the "src" array and return result in "dest" array 854 * 855 * @param src 856 * array of short (unscaled values) 857 * @param dest 858 * result as array of int (scaled values) 859 * @param signed 860 * signed/unsigned src data flag 861 */ 862 public void scale(short[] src, int[] dest, boolean signed) 863 { 864 scale(src, 0, dest, 0, ArrayUtil.getTotalLength(src), signed); 865 } 866 867 /** 868 * Scale each value in the "src" array and return result in "dest" array 869 * 870 * @param src 871 * array of int (unscaled values) 872 * @param dest 873 * result as array of int (scaled values) 874 * @param signed 875 * signed/unsigned src data flag 876 */ 877 public void scale(int[] src, int[] dest, boolean signed) 878 { 879 scale(src, 0, dest, 0, ArrayUtil.getTotalLength(src), signed); 880 } 881 882 /** 883 * Scale array 884 * 885 * @param src 886 * array of float (unscaled values) 887 * @param dest 888 * result as array of int (scaled values) 889 */ 890 public void scale(float[] src, int[] dest) 891 { 892 scale(src, 0, dest, 0, ArrayUtil.getTotalLength(src)); 893 } 894 895 /** 896 * Scale array 897 * 898 * @param src 899 * array of double (unscaled values) 900 * @param dest 901 * result as array of int (scaled values) 902 */ 903 public void scale(double[] src, int[] dest) 904 { 905 scale(src, 0, dest, 0, ArrayUtil.getTotalLength(src)); 906 } 907 908 /** 909 * Scale each value in the "src" array and return result in "dest" array 910 * 911 * @param src 912 * array of byte (unscaled values) 913 * @param dest 914 * result as array of double (scaled values) 915 * @param signed 916 * signed/unsigned src data flag 917 */ 918 public void scale(byte[] src, double[] dest, boolean signed) 919 { 920 scale(src, 0, dest, 0, ArrayUtil.getTotalLength(src), signed); 921 } 922 923 /** 924 * Scale each value in the "src" array and return result in "dest" array 925 * 926 * @param src 927 * array of short (unscaled values) 928 * @param dest 929 * result as array of double (scaled values) 930 * @param signed 931 * signed/unsigned src data flag 932 */ 933 public void scale(short[] src, double[] dest, boolean signed) 934 { 935 scale(src, 0, dest, 0, ArrayUtil.getTotalLength(src), signed); 936 } 937 938 /** 939 * Scale each value in the "src" array and return result in "dest" array 940 * 941 * @param src 942 * array of int (unscaled values) 943 * @param dest 944 * result as array of double (scaled values) 945 * @param signed 946 * signed/unsigned src data flag 947 */ 948 public void scale(int[] src, double[] dest, boolean signed) 949 { 950 scale(src, 0, dest, 0, ArrayUtil.getTotalLength(src), signed); 951 } 952 953 /** 954 * Scale array 955 * 956 * @param src 957 * array of float (unscaled values) 958 * @param dest 959 * result as array of double (scaled values) 960 */ 961 public void scale(float[] src, double[] dest) 962 { 963 scale(src, 0, dest, 0, ArrayUtil.getTotalLength(src)); 964 } 965 966 /** 967 * Scale array 968 * 969 * @param src 970 * array of double (unscaled values) 971 * @param dest 972 * result as array of double (scaled values) 973 */ 974 public void scale(double[] src, double[] dest) 975 { 976 scale(src, 0, dest, 0, ArrayUtil.getTotalLength(src)); 977 } 978 979 /** 980 * Scale array 981 * 982 * @param data 983 * array of float value to scale 984 */ 985 public void scale(float[] data) 986 { 987 scale(data, 0, data.length); 988 } 989 990 /** 991 * Scale array 992 * 993 * @param data 994 * array of double value to scale 995 */ 996 public void scale(double[] data) 997 { 998 scale(data, 0, data.length); 999 } 1000 1001 /** 1002 * Return the scaler value 1003 * 1004 * @return the scaler value 1005 */ 1006 public double getScaler() 1007 { 1008 return scaler; 1009 } 1010 1011 /** 1012 * @return the integerData 1013 */ 1014 public boolean isIntegerData() 1015 { 1016 return integerData; 1017 } 1018 1019 /** 1020 * @return the crossed flag 1021 */ 1022 public boolean isCrossed() 1023 { 1024 return crossed; 1025 } 1026 1027 /** 1028 * Return true if scaler doesn't change value (input = output) 1029 */ 1030 public boolean isNull() 1031 { 1032 return (leftIn == leftOut) && (rightIn == rightOut); 1033 } 1034 1035 /** 1036 * @return the canCross 1037 */ 1038 public boolean getCanCross() 1039 { 1040 return canCross; 1041 } 1042 1043 /** 1044 * @param canCross 1045 * the canCross to set 1046 */ 1047 public void setCanCross(boolean canCross) 1048 { 1049 if (this.canCross != canCross) 1050 { 1051 // crossed and we can't anymore... 1052 if (!canCross && crossed) 1053 { 1054 final double ali = absLeftIn; 1055 final double ari = absRightIn; 1056 final double li = leftIn; 1057 final double ri = rightIn; 1058 1059 // uncross 1060 setLeftRight(ari, ali, ScalerRange.SR_ABSIN, true); 1061 setLeftRight(ri, li, ScalerRange.SR_IN, true); 1062 } 1063 1064 this.canCross = canCross; 1065 } 1066 } 1067 1068 /** 1069 * @return the absLeftIn 1070 */ 1071 public double getAbsLeftIn() 1072 { 1073 return absLeftIn; 1074 } 1075 1076 /** 1077 * @param absLeftIn 1078 * the absLeftIn to set 1079 */ 1080 public void setAbsLeftIn(double absLeftIn) 1081 { 1082 setLeftRight(absLeftIn, absRightIn, ScalerRange.SR_ABSIN, true); 1083 } 1084 1085 /** 1086 * @return the absRightIn 1087 */ 1088 public double getAbsRightIn() 1089 { 1090 return absRightIn; 1091 } 1092 1093 /** 1094 * @param absRightIn 1095 * the absRightIn to set 1096 */ 1097 public void setAbsRightIn(double absRightIn) 1098 { 1099 setLeftRight(absLeftIn, absRightIn, ScalerRange.SR_ABSIN, false); 1100 } 1101 1102 /** 1103 * @return the leftIn 1104 */ 1105 public double getLeftIn() 1106 { 1107 return leftIn; 1108 } 1109 1110 /** 1111 * @param leftIn 1112 * the leftIn to set 1113 */ 1114 public void setLeftIn(double leftIn) 1115 { 1116 setLeftRight(leftIn, rightIn, ScalerRange.SR_IN, true); 1117 } 1118 1119 /** 1120 * @return the rightIn 1121 */ 1122 public double getRightIn() 1123 { 1124 return rightIn; 1125 } 1126 1127 /** 1128 * @param rightIn 1129 * the rightIn to set 1130 */ 1131 public void setRightIn(double rightIn) 1132 { 1133 setLeftRight(leftIn, rightIn, ScalerRange.SR_IN, false); 1134 } 1135 1136 /** 1137 * @return the leftOut 1138 */ 1139 public double getLeftOut() 1140 { 1141 return leftOut; 1142 } 1143 1144 /** 1145 * @param leftOut 1146 * the leftOut to set 1147 */ 1148 public void setLeftOut(double leftOut) 1149 { 1150 setLeftRight(leftOut, rightOut, ScalerRange.SR_OUT, true); 1151 } 1152 1153 /** 1154 * @return the rightOut 1155 */ 1156 public double getRightOut() 1157 { 1158 return rightOut; 1159 } 1160 1161 /** 1162 * @param rightOut 1163 * the rightOut to set 1164 */ 1165 public void setRightOut(double rightOut) 1166 { 1167 setLeftRight(leftOut, rightOut, ScalerRange.SR_OUT, false); 1168 } 1169 1170 /** 1171 * @param left 1172 * the leftAbsIn to set 1173 * @param right 1174 * the rightAbsIn to set 1175 */ 1176 public void setAbsLeftRightIn(double left, double right) 1177 { 1178 setLeftRight(left, right, ScalerRange.SR_ABSIN, false); 1179 } 1180 1181 /** 1182 * @param left 1183 * the leftIn to set 1184 * @param right 1185 * the rightIn to set 1186 */ 1187 public void setLeftRightIn(double left, double right) 1188 { 1189 setLeftRight(left, right, ScalerRange.SR_IN, false); 1190 } 1191 1192 /** 1193 * @param left 1194 * the leftOut to set 1195 * @param right 1196 * the rightOut to set 1197 */ 1198 public void setLeftRightOut(double left, double right) 1199 { 1200 setLeftRight(left, right, ScalerRange.SR_OUT, false); 1201 } 1202 1203 /** 1204 * fire event 1205 */ 1206 public void fireEvent(ScalerEvent e) 1207 { 1208 for (ScalerListener listener : listeners.getListeners(ScalerListener.class)) 1209 listener.scalerChanged(e); 1210 } 1211 1212 /** 1213 * Add a listener 1214 * 1215 * @param listener 1216 */ 1217 public void addListener(ScalerListener listener) 1218 { 1219 listeners.add(ScalerListener.class, listener); 1220 } 1221 1222 /** 1223 * Remove a listener 1224 * 1225 * @param listener 1226 */ 1227 public void removeListener(ScalerListener listener) 1228 { 1229 listeners.remove(ScalerListener.class, listener); 1230 } 1231 1232 @Override 1233 public void onChanged(CollapsibleEvent compare) 1234 { 1235 final ScalerEvent event = (ScalerEvent) compare; 1236 1237 // notify listener we have changed 1238 fireEvent(event); 1239 } 1240 1241 /** 1242 * process on change 1243 */ 1244 private void changed() 1245 { 1246 // handle changed via updater object 1247 updater.changed(new ScalerEvent(this)); 1248 } 1249 1250 public void beginUpdate() 1251 { 1252 updater.beginUpdate(); 1253 } 1254 1255 public void endUpdate() 1256 { 1257 updater.endUpdate(); 1258 } 1259 1260 public boolean isUpdating() 1261 { 1262 return updater.isUpdating(); 1263 } 1264 1265 @Override 1266 public boolean loadFromXML(Node node) 1267 { 1268 if (node == null) 1269 return false; 1270 1271 beginUpdate(); 1272 try 1273 { 1274 double l, r; 1275 1276 setCanCross(XMLUtil.getElementBooleanValue(node, ID_CANCROSS, false)); 1277 integerData = XMLUtil.getElementBooleanValue(node, ID_INTEGERDATA, false); 1278 1279 l = XMLUtil.getElementDoubleValue(node, ID_ABSLEFTIN, 0d); 1280 r = XMLUtil.getElementDoubleValue(node, ID_ABSRIGHTIN, 0d); 1281 setLeftRight(l, r, ScalerRange.SR_ABSIN, true); 1282 l = XMLUtil.getElementDoubleValue(node, ID_LEFTIN, 0d); 1283 r = XMLUtil.getElementDoubleValue(node, ID_RIGHTIN, 0d); 1284 setLeftRight(l, r, ScalerRange.SR_IN, true); 1285 l = XMLUtil.getElementDoubleValue(node, ID_LEFTOUT, 0d); 1286 r = XMLUtil.getElementDoubleValue(node, ID_RIGHTOUT, 0d); 1287 setLeftRight(l, r, ScalerRange.SR_OUT, true); 1288 } 1289 finally 1290 { 1291 endUpdate(); 1292 } 1293 1294 return true; 1295 } 1296 1297 @Override 1298 public boolean saveToXML(Node node) 1299 { 1300 if (node == null) 1301 return false; 1302 1303 XMLUtil.setElementBooleanValue(node, ID_CANCROSS, getCanCross()); 1304 XMLUtil.setElementBooleanValue(node, ID_INTEGERDATA, isIntegerData()); 1305 1306 XMLUtil.setElementDoubleValue(node, ID_ABSLEFTIN, getAbsLeftIn()); 1307 XMLUtil.setElementDoubleValue(node, ID_ABSRIGHTIN, getAbsRightIn()); 1308 XMLUtil.setElementDoubleValue(node, ID_LEFTIN, getLeftIn()); 1309 XMLUtil.setElementDoubleValue(node, ID_RIGHTIN, getRightIn()); 1310 XMLUtil.setElementDoubleValue(node, ID_LEFTOUT, getLeftOut()); 1311 XMLUtil.setElementDoubleValue(node, ID_RIGHTOUT, getRightOut()); 1312 1313 return true; 1314 } 1315 1316}