Git Product home page Git Product logo

ij1-patcher's Introduction

ImageJ

ImageJ is public domain software for processing and analyzing scientific images.

It is written in Java, which allows it to run on many different platforms.

For further information, see:

Using ImageJ as a dependency

To use ImageJ as a library in your Maven project, add the dependency:

<dependency>
  <groupId>net.imagej</groupId>
  <artifactId>ij</artifactId>
  <version>1.53j</version>
</dependency>

Where 1.53j is the version of ImageJ you would like to use:

Building from source

With Ant

The Apache Ant utility will compile and run ImageJ using the build.xml file in this directory. There is a version of Ant at

https://imagej.nih.gov/ij/download/tools/ant/ant.zip

set up to use the JVM distributed with the Windows version of ImageJ. The README included in the ZIP archive has more information.

With Maven

You can compile and run ImageJ using the Maven build tool:

Command Action
mvn Compile and package ImageJ into a JAR file in the target directory.
mvn -Pexec Compile and then run ImageJ.
mvn javadoc:javadoc Generate the project Javadoc in the target/apidocs directory.

ij1-patcher's People

Contributors

awalter17 avatar ctrueden avatar dscho avatar gselzer avatar hinerm avatar imagejan avatar joehsiao avatar mkitti avatar skalarproduktraum avatar stelfrich avatar y3nr1ng avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ij1-patcher's Issues

VerifyError thrown when ij.jar is built targeting Java 1.8

Even though ij1-patcher now successfully applies all its patches as of ImageJ 1.51p, the bytecode verifier still throws VerifyError if the ij.jar targets bytecode version 52 (i.e. Java 8) or later. This is discussed in #50. To avoid the problem, all releases of ij.jar are built targeting Java 6 bytecode, which is fine for now since ImageJ does not use any Java >6 APIs. But it restricts ImageJ from ever updating to a Java 8 minimum and using things like lambdas or the streaming API, which is unfortunate.

The proper thing would be to dig into why the bytecode verifier still dislikes the patched ImageJ classes, and address it, so that ImageJ patched by ij1-patcher + imagej-legacy is still considered valid by the Java runtime without needing a workaround like -Xverify:none.

Allow disabling the LegacyInitializer, fix the PluginClassLoader and disable Help>Refresh Menus

For the LegacyUI to be called within an ImageJ context (rather than constructed after ImageJ 1.x started up), we will want to reverse the direction of the initialization: instead of letting the LegacyEnvironment start up an ImageJ 1.x instance that then initializes the context via the LegacyInitializer, let's also have a way to let the LegacyUI start up a LegacyEnvironment that disallows overriding the PlugInClassLoader and instead insists on the current class loader.

Avoid inconsistent macro option string handling when headless

People keep stumbling over inconsistencies in option string parsing between ImageJ 1.x and the headless mode. While both "key=variable" and "key=&variable" seem to work in the ImageJ GUI, headless mode requires proper string concatenation: "key=" + variable + "".

See also this forum thread.

If things cannot be kept consistent, there should at least be a more informative message for users.

Support refresh menus

This is a useful function of ImageJ and it is unfortunate that we have had to drop its support to perform class modification magic.

It would be nice to restore this functionality.

Verify that version detection works with Java 10 in all situations

Attempting to launch Fiji with a snapshot of Java 10 dies with:

java.lang.ExceptionInInitializerError
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at net.imagej.patcher.LegacyEnvironment.isImageJ1Initialized(LegacyEnvironment.java:553)
	... 22 more
Caused by: java.lang.StringIndexOutOfBoundsException: begin 0, end 3, length 2
	at java.base/java.lang.String.checkBoundsBeginEnd(String.java:3107)
	at java.base/java.lang.String.substring(String.java:1873)
	at ij.IJ.<clinit>(IJ.java:76)
	... 27 more

Launching with $J10/bin/java -jar ij-1.51u.jar works, however, as does:

$J10/bin/java -cp '*':bio-formats/'*':../plugins/'*' net.imagej.Main

Intercept editor also when using drag 'n drop to open scripts

From Martin Höhne:

One thing I noticed (I assume you know that this happens, just in case you don´t): when I drag and drop the test marco it does not open in the Fiji script editor (as it does usually), but in the ImageJ editor.
When I go File>New>Script the Fiji Script editor opens with all languages (including ImageJ Macro Language) availabel.

Patch in sane window handling in multi-screen setup

It is a good idea to pop up a dialog on the same screen as the foreground window.

The best idea is probably to

  1. determine which window is focused (we should iterate through IJ.getInstance(), IJ.getImage().getWindow() and all the WindowManager.getNonImageWindows() and test via isFocused() whether they are in the foreground
  2. get their GraphicsConfiguration
  3. inject that configuration as last parameter to the Dialog constructor instead of the one that is actually defined by ImageJ 1.x.

Of course, this can be done only as long as we're not about to activate headless mode.

It is highly likely that ImageJ 1.x will adopt a slightly divergent version of what I wrote up above; We will need to watch out for that and fix as necessary.

This issue is based on imagej/ImageJ#32.

Create a Jenkins job

Right now, Jenkins does not build ij1-patcher when things change. Hence, the compilation is not tested, unit tests are not run, and no SNAPSHOTs are deployed.

Add a Jenkins job bound to the Windows node

This Jenkins job will serve two purposes:

  1. make sure that ij1-patcher works with Windows (because Windows is notorious for causing problems by which no other platform is affected)
  2. run the non-headless unit tests (that are disabled in headless mode via assumeTrue()

Refactor opener intercepts

Right now we have a lot of instanceof checks and we're really using the DefaultLegacyOpener in two different ways.

If we come from an open path where we are given a String source, then if the LegacyOpener fails we want to continue to IJ1 with our given source.

If we come from an open path where we weren't given a String source and one is chosen during IJ2 execution, which then fails, we want to continue to IJ1 with the source selected in IJ2.

In the second case we ALWAYS want to return the path from IJ2. In the first case, we don't care about the String and it's effectively the same as a null value.

Avoid confusion between ij.Macro class and ij.macro package

The following exception is emitted at startup of ImageJ2:

java.lang.IllegalArgumentException: Cannot handle replace call to show in ij.gui.StackWindow's public <init>(ij.ImagePlus imp, ij.gui.ImageCanvas ic)
    at net.imagej.patcher.CodeHacker.replaceCallInMethod(CodeHacker.java:725)
    at net.imagej.patcher.CodeHacker.replaceCallInMethod(CodeHacker.java:650)
    at net.imagej.patcher.LegacyInjector.inject(LegacyInjector.java:320)
    at net.imagej.patcher.LegacyInjector.injectHooks(LegacyInjector.java:109)
    at net.imagej.patcher.LegacyEnvironment.initialize(LegacyEnvironment.java:101)
    at net.imagej.patcher.LegacyEnvironment.applyPatches(LegacyEnvironment.java:495)
    at net.imagej.patcher.LegacyInjector.preinit(LegacyInjector.java:397)
    at net.imagej.patcher.LegacyInjector.preinit(LegacyInjector.java:376)
    at net.imagej.legacy.LegacyService.<clinit>(LegacyService.java:130)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at java.lang.Class.newInstance0(Class.java:357)
    at java.lang.Class.newInstance(Class.java:310)
    at org.scijava.service.ServiceHelper.createServiceRecursively(ServiceHelper.java:302)
    at org.scijava.service.ServiceHelper.createExactService(ServiceHelper.java:269)
    at org.scijava.service.ServiceHelper.loadService(ServiceHelper.java:231)
    at org.scijava.service.ServiceHelper.createServiceRecursively(ServiceHelper.java:340)
    at org.scijava.service.ServiceHelper.createExactService(ServiceHelper.java:269)
    at org.scijava.service.ServiceHelper.loadService(ServiceHelper.java:231)
    at org.scijava.service.ServiceHelper.loadService(ServiceHelper.java:194)
    at org.scijava.service.ServiceHelper.loadServices(ServiceHelper.java:166)
    at org.scijava.Context.<init>(Context.java:267)
    at org.scijava.Context.<init>(Context.java:224)
    at org.scijava.Context.<init>(Context.java:163)
    at org.scijava.Context.<init>(Context.java:119)
    at org.scijava.Context.<init>(Context.java:107)
    at net.imagej.ImageJ.<init>(ImageJ.java:78)
    at net.imagej.Main.launch(Main.java:61)
    at net.imagej.Main.main(Main.java:73)
Caused by: java.lang.RuntimeException: cannot find ij.macro: ij.Macro found in ij/macro.class
    at javassist.CtClassType.getClassFile2(CtClassType.java:196)
    at javassist.CtClassType.makeFieldCache(CtClassType.java:867)
    at javassist.CtClassType.getMembers(CtClassType.java:858)
    at javassist.CtClassType.getDeclaredField2(CtClassType.java:992)
    at javassist.CtClassType.getField2(CtClassType.java:946)
    at javassist.CtClassType.getField(CtClassType.java:927)
    at javassist.CtClass.getField(CtClass.java:819)
    at javassist.compiler.MemberResolver.lookupFieldByJvmName2(MemberResolver.java:283)
    at javassist.compiler.TypeChecker.fieldAccess2(TypeChecker.java:913)
    at javassist.compiler.TypeChecker.fieldAccess(TypeChecker.java:870)
    at javassist.compiler.TypeChecker.atFieldRead(TypeChecker.java:803)
    at javassist.compiler.TypeChecker.atExpr(TypeChecker.java:578)
    at javassist.compiler.ast.Expr.accept(Expr.java:68)
    at javassist.compiler.TypeChecker.fieldAccess(TypeChecker.java:860)
    at javassist.compiler.TypeChecker.atFieldRead(TypeChecker.java:803)
    at javassist.compiler.TypeChecker.atExpr(TypeChecker.java:578)
    at javassist.compiler.ast.Expr.accept(Expr.java:68)
    at javassist.compiler.TypeChecker.booleanExpr(TypeChecker.java:523)
    at javassist.compiler.TypeChecker.atExpr(TypeChecker.java:592)
    at javassist.compiler.ast.Expr.accept(Expr.java:68)
    at javassist.compiler.CodeGen.doTypeCheck(CodeGen.java:242)
    at javassist.compiler.CodeGen.compileBooleanExpr(CodeGen.java:236)
    at javassist.compiler.CodeGen.atIfStmnt(CodeGen.java:384)
    at javassist.compiler.CodeGen.atStmnt(CodeGen.java:355)
    at javassist.compiler.ast.Stmnt.accept(Stmnt.java:50)
    at javassist.compiler.Javac.compileStmnt(Javac.java:569)
    at javassist.expr.MethodCall.replace(MethodCall.java:235)
    at net.imagej.patcher.CodeHacker$7.edit(CodeHacker.java:686)
    at javassist.expr.ExprEditor.loopBody(ExprEditor.java:192)
    at javassist.expr.ExprEditor.doit(ExprEditor.java:91)
    at javassist.CtBehavior.instrument(CtBehavior.java:712)
    at net.imagej.patcher.CodeHacker$EagerExprEditor.instrument(CodeHacker.java:1278)
    at net.imagej.patcher.CodeHacker.replaceCallInMethod(CodeHacker.java:670)
    ... 30 more

I think the offending line is here. Maybe it's a bug in Javassist; I'm not sure. Regardless, we can probably fix it by avoiding a hard reference on the ij.macro package in favor of using reflection or indirection (perhaps a LegacyHooks#isBatchMode() method?).

Make HeadlessGenericDialog more robust

We already have a unit test that makes sure that we override all methods in the HeadlessGenericDialog, in particular those that might have been added to the GenericDialog class in new ImageJ 1.x versions.

However, this test can only catch things after the fact, after a new ImageJ version was released (and picked up in Mavenized form by ImageJA).

Let's be more proactive and add code that inserts dummy methods in the HeadlessGenericDialog for every unhandled method. This might need to be switched off for the unit test in question, but it should make the headless mode a lot more robust.

Split event handling from status/progress updates

At the moment, imagej-legacy uses the ij1-patcher to patch IJ.showStatus() and IJ.showProgress() to do two things: forward events to the EventService and update the UI elements.

However, this leads to an infinite loop when a status update triggers an update of the status bar and an event that triggers exactly the same again.

We should really split these two code paths so that the LegacyStatusBar can ask ImageJ 1.x' status bar to show the update, without sending out another event.

Reactivate support for writing `misc/headless.jar` files

When the predecessor of ij1-patcher was living in Fiji, there was support for writing out misc/headless.jar files for use in restricted environments disallowing runtime patching (the misc/headless.jar file simply needs to be prepended to the class path to activate the headless mode).

Let's reinstate that support and add another goodie: support writing out not only the patched classes but instead all ImageJ 1.x classes. That provides stand-alone auto-generated drop-in replacement for ij.jar in headless environments.

Support bare HandleExtraFileTypes.class again

Since we switched away from the PluginClassLoader, the plugins/directory only gets added to the class loader on demand. When ImageJ 1.x calls HandleExtraFileTypes, this is such a demand, too...

Make Help > Update ImageJ show a warning

http://forum.imagej.net/t/help-update-imagej-triggers-there-are-locally-modified-files-warning-when-running-help-update/8898/4?u=stelfrich:

That’s an interesting suggestion. In practice, people use Help > Update ImageJ to checkout nightly builds of ImageJ after being asked by Wayne Rasband to see if his changes solve their issue. So we can’t completely remove the menu entry. But we could patch a warning into the command when a user runs it, saying that within Fiji (or an environment where ImageJ1 gets patched) you might not want to use this command.

Provide more robust ways to debug *unpacked* plugin .jar files

When developing plugin in an Integrated Development Environment, it is really, really, really rare to have bundled .jar files. Rather than having some magic code to bundle up classes on-the-fly or worse: forcing the developer to jar up the files, let's add a patch via ij1-patcher that forces ImageJ 1.x to parse directories containing plugins.config files understanding that they are simply unpacked .jar files when they are added via the ij1.plugin.dirs system property.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.