Skip to content

Commit

Permalink
Add PlatformPlugin and refine properties resolved for BuildPlugin
Browse files Browse the repository at this point in the history
  • Loading branch information
saudet committed May 25, 2020
1 parent f62d201 commit fb38d56
Show file tree
Hide file tree
Showing 13 changed files with 542 additions and 109 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ before_install:
fi
script:
- gradle build $GRADLE_PUBLISH
- gradle build $GRADLE_PUBLISH --info
61 changes: 41 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Gradle JavaCPP

Introduction
------------
Gradle JavaCPP offers plugins that make it easy to use [JavaCPP](https://github.com/bytedeco/javacpp) as part of the Gradle build system.
Gradle JavaCPP offers plugins that make it easy to use [JavaCPP](https://github.com/bytedeco/javacpp) and [JavaCV](https://github.com/bytedeco/javacv) as part of the Gradle build system.

Please feel free to ask questions on [the mailing list](http://groups.google.com/group/javacpp-project) if you encounter any problems with the software! I am sure it is far from perfect...

Expand All @@ -19,38 +19,36 @@ To use Gradle JavaCPP, you will need to download and install the following softw
* OpenJDK http://openjdk.java.net/install/ or
* Oracle JDK http://www.oracle.com/technetwork/java/javase/downloads/ or
* IBM JDK http://www.ibm.com/developerworks/java/jdk/
* A C++ compiler, out of which these have been tested:
* GNU C/C++ Compiler (Linux, etc.) http://gcc.gnu.org/
* For Windows x86 and x64 http://mingw-w64.org/
* LLVM Clang (Mac OS X, etc.) http://clang.llvm.org/
* Microsoft C/C++ Compiler, part of Visual Studio https://visualstudio.microsoft.com/
* https://docs.microsoft.com/en-us/cpp/build/walkthrough-compiling-a-native-cpp-program-on-the-command-line
* Gradle 5.0 or newer: https://gradle.org/releases/

To produce binary files for Android 4.0 or newer, you will also have to install:

* Android NDK r7 or newer http://developer.android.com/ndk/downloads/
Getting Started
---------------
Gradle JavaCPP comes with 2 plugins:

And similarly to target iOS, you will need to install either:
* [The build plugin](#the-build-plugin) to create new packages containing native libraries using JavaCPP, and
* [The platform plugin](#the-platform-plugin) to select from existing artifacts the ones corresponding to user-specified platforms.

* Gluon VM http://gluonhq.com/products/mobile/vm/ or
* RoboVM 1.x or newer http://robovm.mobidevelop.com/downloads/
Fully functional sample projects are also provided in the [`samples`](samples) subdirectory and can be used as templates.


Getting Started
---------------
### The Build Plugin
To understand how [JavaCPP](https://github.com/bytedeco/javacpp) is meant to be used, one should first take a look at the [Mapping Recipes for C/C++ Libraries](https://github.com/bytedeco/javacpp/wiki/Mapping-Recipes), but a high-level overview of the [Basic Architecture](https://github.com/bytedeco/javacpp/wiki/Basic-Architecture) is also available to understand the bigger picture.

Once comfortable enough with the command line interface, the build plugin for Gradle can be used to integrate easily that workflow as part of `build.gradle` as shown below. By default, it creates a `javacppJar` task that archives the native libraries into a separate JAR file and sets its classifier to `$javacppPlatform`, while excluding those files from the default `jar` task. To customize the behavior, there are properties and extensions that can be modified and whose documentation is available as part of the source code in these files:
* [`BuildTask.java`](src/main/java/org/bytedeco//gradle/javacpp/BuildTask.java)
* [`BuildPlugin.java`](src/main/java/org/bytedeco//gradle/javacpp/BuildPlugin.java)
Once comfortable enough with the command line interface, the build plugin for Gradle can be used to integrate easily that workflow as part of `build.gradle` as shown below. By default, it creates a `javacppJar` task that archives the native libraries into a separate JAR file and sets its classifier to `$javacppPlatform`, while excluding those files from the default `jar` task. To customize the behavior, there are properties that can be modified and whose documentation is available as part of the source code in these files:

Fully functional sample projects are also provided in the [`samples`](samples) subdirectory and can be used as templates.
* [`BuildTask.java`](src/main/java/org/bytedeco/gradle/javacpp/BuildTask.java)
* [`BuildPlugin.java`](src/main/java/org/bytedeco/gradle/javacpp/BuildPlugin.java)

```groovy
plugins {
id 'java-library'
id 'org.bytedeco.gradle-javacpp-build' version "$javacppVersion"
id 'java-library'
id 'org.bytedeco.gradle-javacpp-build' version "$javacppVersion"
}
// We can set this on the command line too this way: -PjavacppPlatform=android-arm64
ext {
javacppPlatorm = 'android-arm64' // or any other platform, defaults to Loader.getPlatform()
}
dependencies {
Expand All @@ -75,6 +73,29 @@ javacppBuildCompiler {
```


### The Platform Plugin
With Maven, we are able to modify dependencies transitively using profiles, and although Gradle doesn't provide such functionality out of the box, it can be emulated via plugins. After adding a single line to the `build.gradle` script as shown below, the platform plugin will filter the dependencies of artifacts whose names contain "-platform" using the comma-separated values given in `$javacppPlatform`. To understand better how this works, it may be worth taking a look at the source code of the plugin:

* [`PlatformRule.java`](src/main/java/org/bytedeco/gradle/javacpp/PlatformRule.java)
* [`PlatformPlugin.java`](src/main/java/org/bytedeco/gradle/javacpp/PlatformPlugin.java)

```groovy
plugins {
id 'java-library'
id 'org.bytedeco.gradle-javacpp-platform' version "$javacppVersion"
}
// We can set this on the command line too this way: -PjavacppPlatform=linux-x86_64,macosx-x86_64,windows-x86_64,etc
ext {
javacppPlatorm = 'linux-x86_64,macosx-x86_64,windows-x86_64,etc' // defaults to Loader.getPlatform()
}
dependencies {
api "org.bytedeco:javacv-platform:$javacvVersion"
}
```


----
Project lead: Samuel Audet [samuel.audet `at` gmail.com](mailto:samuel.audet at gmail.com)
Developer site: https://github.com/bytedeco/gradle-javacpp
Expand Down
13 changes: 9 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ gradlePlugin {
id = 'org.bytedeco.gradle-javacpp-build'
implementationClass = 'org.bytedeco.gradle.javacpp.BuildPlugin'
}
platform {
id = 'org.bytedeco.gradle-javacpp-platform'
implementationClass = 'org.bytedeco.gradle.javacpp.PlatformPlugin'
}
}
}

Expand All @@ -44,6 +48,7 @@ javadoc {
options.links = ['https://docs.oracle.com/javase/8/docs/api',
'https://docs.gradle.org/current/javadoc',
'http://bytedeco.org/javacpp/apidocs',
'http://www.slf4j.org/apidocs',
'http://junit.org/junit4/javadoc/4.12']
}

Expand All @@ -67,10 +72,6 @@ artifacts {
archives sourcesJar
}

signing {
if (!version.endsWith('SNAPSHOT')) sign publishing.publications.mavenJava
}

publishing {
publications {
mavenJava(MavenPublication) {
Expand Down Expand Up @@ -126,3 +127,7 @@ publishing {
}
}

signing {
if (!version.endsWith('SNAPSHOT')) sign publishing.publications.mavenJava
}

28 changes: 28 additions & 0 deletions samples/javacv-demo/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
plugins {
id 'java-library'
id 'org.bytedeco.gradle-javacpp-platform' version '1.5.4-SNAPSHOT'
}

group = 'org.bytedeco'
version = '1.5.3'

repositories {
mavenLocal()
mavenCentral()
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
}

dependencies {
api "org.bytedeco:javacv-platform:$version"
testImplementation 'junit:junit:4.12'
}

// Let's create a standalone "uber JAR" to see what we get in it
jar {
duplicatesStrategy = DuplicatesStrategy.INCLUDE // allow duplicates
manifest.attributes "Main-Class": "org.bytedeco.javacv.samples.Demo"
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
}

11 changes: 11 additions & 0 deletions samples/javacv-demo/settings.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
pluginManagement {
repositories {
mavenLocal()
mavenCentral()
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
}
}

rootProject.name = 'javacv-demo'

gradle.rootProject { ext.javacppVersion = '1.5.4-SNAPSHOT' }
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/*
* Copyright (C) 2009-2018 Samuel Audet
*
* Licensed either under the Apache License, Version 2.0, or (at your option)
* under the terms of the GNU General Public License as published by
* the Free Software Foundation (subject to the "Classpath" exception),
* either version 2, or any later version (collectively, the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.gnu.org/licenses/
* http://www.gnu.org/software/classpath/license.html
*
* or as provided in the LICENSE.txt file that accompanied this code.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.bytedeco.javacv.samples;

import java.io.File;
import java.net.URL;
import org.bytedeco.javacv.*;
import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.indexer.*;
import org.bytedeco.opencv.opencv_core.*;
import org.bytedeco.opencv.opencv_imgproc.*;
import org.bytedeco.opencv.opencv_calib3d.*;
import org.bytedeco.opencv.opencv_objdetect.*;
import static org.bytedeco.opencv.global.opencv_core.*;
import static org.bytedeco.opencv.global.opencv_imgproc.*;
import static org.bytedeco.opencv.global.opencv_calib3d.*;
import static org.bytedeco.opencv.global.opencv_objdetect.*;

public class Demo {
public static void main(String[] args) throws Exception {
String classifierName = null;
if (args.length > 0) {
classifierName = args[0];
} else {
URL url = new URL("https://raw.github.com/opencv/opencv/master/data/haarcascades/haarcascade_frontalface_alt.xml");
File file = Loader.cacheResource(url);
classifierName = file.getAbsolutePath();
}

// We can "cast" Pointer objects by instantiating a new object of the desired class.
CascadeClassifier classifier = new CascadeClassifier(classifierName);
if (classifier == null) {
System.err.println("Error loading classifier file \"" + classifierName + "\".");
System.exit(1);
}

// The available FrameGrabber classes include OpenCVFrameGrabber (opencv_videoio),
// DC1394FrameGrabber, FlyCapture2FrameGrabber, OpenKinectFrameGrabber, OpenKinect2FrameGrabber,
// RealSenseFrameGrabber, RealSense2FrameGrabber, PS3EyeFrameGrabber, VideoInputFrameGrabber, and FFmpegFrameGrabber.
FrameGrabber grabber = FrameGrabber.createDefault(0);
grabber.start();

// CanvasFrame, FrameGrabber, and FrameRecorder use Frame objects to communicate image data.
// We need a FrameConverter to interface with other APIs (Android, Java 2D, JavaFX, Tesseract, OpenCV, etc).
OpenCVFrameConverter.ToMat converter = new OpenCVFrameConverter.ToMat();

// FAQ about IplImage and Mat objects from OpenCV:
// - For custom raw processing of data, createBuffer() returns an NIO direct
// buffer wrapped around the memory pointed by imageData, and under Android we can
// also use that Buffer with Bitmap.copyPixelsFromBuffer() and copyPixelsToBuffer().
// - To get a BufferedImage from an IplImage, or vice versa, we can chain calls to
// Java2DFrameConverter and OpenCVFrameConverter, one after the other.
// - Java2DFrameConverter also has static copy() methods that we can use to transfer
// data more directly between BufferedImage and IplImage or Mat via Frame objects.
Mat grabbedImage = converter.convert(grabber.grab());
int height = grabbedImage.rows();
int width = grabbedImage.cols();

// Objects allocated with `new`, clone(), or a create*() factory method are automatically released
// by the garbage collector, but may still be explicitly released by calling deallocate().
// You shall NOT call cvReleaseImage(), cvReleaseMemStorage(), etc. on objects allocated this way.
Mat grayImage = new Mat(height, width, CV_8UC1);
Mat rotatedImage = grabbedImage.clone();

// The OpenCVFrameRecorder class simply uses the VideoWriter of opencv_videoio,
// but FFmpegFrameRecorder also exists as a more versatile alternative.
FrameRecorder recorder = FrameRecorder.createDefault("output.avi", width, height);
recorder.start();

// CanvasFrame is a JFrame containing a Canvas component, which is hardware accelerated.
// It can also switch into full-screen mode when called with a screenNumber.
// We should also specify the relative monitor/camera response for proper gamma correction.
CanvasFrame frame = new CanvasFrame("Some Title", CanvasFrame.getDefaultGamma()/grabber.getGamma());

// Let's create some random 3D rotation...
Mat randomR = new Mat(3, 3, CV_64FC1),
randomAxis = new Mat(3, 1, CV_64FC1);
// We can easily and efficiently access the elements of matrices and images
// through an Indexer object with the set of get() and put() methods.
DoubleIndexer Ridx = randomR.createIndexer(),
axisIdx = randomAxis.createIndexer();
axisIdx.put(0, (Math.random() - 0.5) / 4,
(Math.random() - 0.5) / 4,
(Math.random() - 0.5) / 4);
Rodrigues(randomAxis, randomR);
double f = (width + height) / 2.0; Ridx.put(0, 2, Ridx.get(0, 2) * f);
Ridx.put(1, 2, Ridx.get(1, 2) * f);
Ridx.put(2, 0, Ridx.get(2, 0) / f); Ridx.put(2, 1, Ridx.get(2, 1) / f);
System.out.println(Ridx);

// We can allocate native arrays using constructors taking an integer as argument.
Point hatPoints = new Point(3);

while (frame.isVisible() && (grabbedImage = converter.convert(grabber.grab())) != null) {
// Let's try to detect some faces! but we need a grayscale image...
cvtColor(grabbedImage, grayImage, CV_BGR2GRAY);
RectVector faces = new RectVector();
classifier.detectMultiScale(grayImage, faces);
long total = faces.size();
for (long i = 0; i < total; i++) {
Rect r = faces.get(i);
int x = r.x(), y = r.y(), w = r.width(), h = r.height();
rectangle(grabbedImage, new Point(x, y), new Point(x + w, y + h), Scalar.RED, 1, CV_AA, 0);

// To access or pass as argument the elements of a native array, call position() before.
hatPoints.position(0).x(x - w / 10 ).y(y - h / 10);
hatPoints.position(1).x(x + w * 11 / 10).y(y - h / 10);
hatPoints.position(2).x(x + w / 2 ).y(y - h / 2 );
fillConvexPoly(grabbedImage, hatPoints.position(0), 3, Scalar.GREEN, CV_AA, 0);
}

// Let's find some contours! but first some thresholding...
threshold(grayImage, grayImage, 64, 255, CV_THRESH_BINARY);

// To check if an output argument is null we may call either isNull() or equals(null).
MatVector contours = new MatVector();
findContours(grayImage, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
long n = contours.size();
for (long i = 0; i < n; i++) {
Mat contour = contours.get(i);
Mat points = new Mat();
approxPolyDP(contour, points, arcLength(contour, true) * 0.02, true);
drawContours(grabbedImage, new MatVector(points), -1, Scalar.BLUE);
}

warpPerspective(grabbedImage, rotatedImage, randomR, rotatedImage.size());

Frame rotatedFrame = converter.convert(rotatedImage);
frame.showImage(rotatedFrame);
recorder.record(rotatedFrame);
}
frame.dispose();
recorder.stop();
grabber.stop();
}
}
5 changes: 3 additions & 2 deletions samples/zlib/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
plugins {
id 'java-library'
id 'org.bytedeco.gradle-javacpp-build' version '1.5.4-SNAPSHOT'
id 'java-library'
id 'org.bytedeco.gradle-javacpp-build' version '1.5.4-SNAPSHOT'
}

group = 'org.bytedeco'
Expand Down Expand Up @@ -29,6 +29,7 @@ javacppBuildCommand {

javacppBuildParser {
classOrPackageNames = ['org.bytedeco.zlib.presets.*']
outputDirectory = file("$buildDir/generated/sources/javacpp/")
}

javacppBuildCompiler {
Expand Down
Loading

0 comments on commit fb38d56

Please sign in to comment.