├── .github
└── workflows
│ └── maven.yml
├── .gitignore
├── .mvn
├── enforcer-extension.xml
├── extensions.xml
└── readme.txt
├── CODE_OF_CONDUCT.md
├── LICENSE.md
├── PUBLISHING.md
├── README.md
├── docs
├── README.md
├── _config.yml
├── apidocs
│ ├── allclasses-index.html
│ ├── allpackages-index.html
│ ├── copy.svg
│ ├── element-list
│ ├── help-doc.html
│ ├── index-all.html
│ ├── index.html
│ ├── io.github.stanio.xbrz.awt
│ │ ├── io
│ │ │ └── github
│ │ │ │ └── stanio
│ │ │ │ └── xbrz
│ │ │ │ └── awt
│ │ │ │ ├── AwtXbrz.html
│ │ │ │ ├── ImageData.html
│ │ │ │ ├── XbrzFilter.html
│ │ │ │ ├── XbrzImage.html
│ │ │ │ ├── XbrzOp.html
│ │ │ │ ├── class-use
│ │ │ │ ├── AwtXbrz.html
│ │ │ │ ├── ImageData.html
│ │ │ │ ├── XbrzFilter.html
│ │ │ │ ├── XbrzImage.html
│ │ │ │ └── XbrzOp.html
│ │ │ │ ├── package-summary.html
│ │ │ │ ├── package-tree.html
│ │ │ │ ├── package-use.html
│ │ │ │ └── util
│ │ │ │ ├── BaseMultiResolutionImage.html
│ │ │ │ ├── ChainFilterOp.html
│ │ │ │ ├── MultiResolutionCachedImage.html
│ │ │ │ ├── SmoothResizeOp.html
│ │ │ │ ├── class-use
│ │ │ │ ├── BaseMultiResolutionImage.html
│ │ │ │ ├── ChainFilterOp.html
│ │ │ │ ├── MultiResolutionCachedImage.html
│ │ │ │ └── SmoothResizeOp.html
│ │ │ │ ├── package-summary.html
│ │ │ │ ├── package-tree.html
│ │ │ │ └── package-use.html
│ │ └── module-summary.html
│ ├── io.github.stanio.xbrz.core
│ │ ├── io
│ │ │ └── github
│ │ │ │ └── stanio
│ │ │ │ └── xbrz
│ │ │ │ ├── ColorDistance.html
│ │ │ │ ├── Xbrz.ScalerCfg.html
│ │ │ │ ├── Xbrz.html
│ │ │ │ ├── class-use
│ │ │ │ ├── ColorDistance.html
│ │ │ │ ├── Xbrz.ScalerCfg.html
│ │ │ │ └── Xbrz.html
│ │ │ │ ├── package-summary.html
│ │ │ │ ├── package-tree.html
│ │ │ │ └── package-use.html
│ │ └── module-summary.html
│ ├── io.github.stanio.xbrz.tool
│ │ ├── io
│ │ │ └── github
│ │ │ │ └── stanio
│ │ │ │ └── xbrz
│ │ │ │ └── tool
│ │ │ │ ├── ScalerTool.html
│ │ │ │ ├── class-use
│ │ │ │ └── ScalerTool.html
│ │ │ │ ├── package-summary.html
│ │ │ │ ├── package-tree.html
│ │ │ │ └── package-use.html
│ │ └── module-summary.html
│ ├── legal
│ │ ├── ADDITIONAL_LICENSE_INFO
│ │ ├── ASSEMBLY_EXCEPTION
│ │ ├── LICENSE
│ │ ├── jquery.md
│ │ └── jqueryUI.md
│ ├── link.svg
│ ├── member-search-index.js
│ ├── module-search-index.js
│ ├── overview-summary.html
│ ├── overview-tree.html
│ ├── package-search-index.js
│ ├── resources
│ │ ├── glass.png
│ │ └── x.png
│ ├── script-dir
│ │ ├── jquery-3.6.1.min.js
│ │ ├── jquery-ui.min.css
│ │ └── jquery-ui.min.js
│ ├── script.js
│ ├── search-page.js
│ ├── search.html
│ ├── search.js
│ ├── sitemap.xml
│ ├── stylesheet.css
│ ├── tag-search-index.js
│ └── type-search-index.js
├── googlef1bf138e44956fd2.html
├── icons-demo1.png
├── icons-demo1@2x.png
├── icons-demo2.png
└── icons-demo2@2x.png
├── link-jdk-sources.cmd
├── pom.xml
├── src
└── main
│ └── javadoc
│ └── overview.html
├── xbrz-awt
├── README.md
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── io
│ │ │ └── github
│ │ │ └── stanio
│ │ │ └── xbrz
│ │ │ └── awt
│ │ │ ├── AwtXbrz.java
│ │ │ ├── ImageData.java
│ │ │ ├── ScalerPool.java
│ │ │ ├── SuspendableFilteredSource.java
│ │ │ ├── XbrzFilter.java
│ │ │ ├── XbrzOp.java
│ │ │ └── util
│ │ │ ├── ChainFilterOp.java
│ │ │ └── SmoothResizeOp.java
│ └── java9
│ │ ├── io
│ │ └── github
│ │ │ └── stanio
│ │ │ └── xbrz
│ │ │ └── awt
│ │ │ ├── AnimatedMultiResolutionImage.java
│ │ │ ├── XbrzImage.java
│ │ │ └── util
│ │ │ ├── BaseMultiResolutionImage.java
│ │ │ └── MultiResolutionCachedImage.java
│ │ └── module-info.java
│ └── test
│ ├── java
│ └── io
│ │ └── github
│ │ └── stanio
│ │ └── xbrz
│ │ └── awt
│ │ ├── AbstractAwtXbrzTest.java
│ │ ├── AwtXbrzFindFactorTest.java
│ │ ├── AwtXbrzTest.java
│ │ ├── ImageDataTest.java
│ │ ├── XbrzImageTest.java
│ │ ├── XbrzOpTest.java
│ │ └── demo
│ │ ├── AnimDemo.java
│ │ └── IconsDemo.java
│ └── resources
│ └── io
│ └── github
│ └── stanio
│ └── xbrz
│ └── awt
│ ├── demo
│ ├── editbookmarks.png
│ ├── editbookmarks2-16.png
│ ├── editbookmarks2-32.png
│ ├── horizon-1.gif
│ ├── kirby-1.gif
│ ├── kirby-2.gif
│ ├── loading.gif
│ ├── sbreng-1.gif
│ ├── write_obj-16.png
│ └── write_obj-32.png
│ └── images
│ ├── gbamockup-indexcolor-part@6xbrz.png
│ ├── gbamockup-indexcolor.png
│ ├── gbamockup-truecolor.png
│ ├── gbamockup@3xbrz.png
│ ├── loading-frame1.png
│ ├── loading-frame2.png
│ ├── loading-frame3.png
│ ├── loading-frame4.png
│ ├── loading-frame5.png
│ ├── loading-frame6.png
│ ├── loading-frame7.png
│ ├── loading-frame8.png
│ ├── loading-frame9.png
│ ├── loading.gif
│ ├── open-folder.png
│ └── open-folder@3xbrz.png
├── xbrz-core
├── LICENSE
├── README.md
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── io
│ │ │ └── github
│ │ │ └── stanio
│ │ │ └── xbrz
│ │ │ ├── Color.java
│ │ │ ├── ColorDistance.java
│ │ │ ├── OutputMatrix.java
│ │ │ ├── RotationDegree.java
│ │ │ ├── Scaler.java
│ │ │ └── Xbrz.java
│ └── java9
│ │ └── module-info.java
│ └── test
│ ├── java
│ └── io
│ │ └── github
│ │ └── stanio
│ │ └── xbrz
│ │ ├── AbstractScalerTest.java
│ │ ├── ColorDistanceBufferedTest.java
│ │ ├── ColorDistanceTest.java
│ │ ├── ColorDistanceYCbCrIntegerTest.java
│ │ ├── Kernel_3x3Test.java
│ │ ├── Kernel_4x4Test.java
│ │ ├── MatrixRotationTest.java
│ │ ├── OutputMatrixTest.java
│ │ ├── Scaler2xTest.java
│ │ ├── Scaler3xTest.java
│ │ ├── Scaler4xTest.java
│ │ ├── Scaler5xTest.java
│ │ └── Scaler6xTest.java
│ └── resources
│ └── io
│ └── github
│ └── stanio
│ └── xbrz
│ └── test
│ ├── basic-shapes.png
│ ├── basic-shapes@2xbrz.png
│ ├── basic-shapes@3xbrz.png
│ ├── basic-shapes@4xbrz.png
│ ├── basic-shapes@5xbrz.png
│ ├── basic-shapes@6xbrz.png
│ ├── down-arrow.png
│ ├── down-arrow@2xbrz.png
│ ├── down-arrow@3xbrz.png
│ ├── down-arrow@4xbrz.png
│ ├── down-arrow@5xbrz.png
│ ├── down-arrow@6xbrz.png
│ ├── gbamockup.png
│ ├── gbamockup@2xbrz.png
│ ├── gbamockup@3xbrz.png
│ ├── gbamockup@4xbrz.png
│ ├── gbamockup@5xbrz.png
│ ├── gbamockup@6xbrz.png
│ ├── open-folder.png
│ ├── open-folder@2xbrz.png
│ ├── open-folder@3xbrz.png
│ ├── open-folder@4xbrz.png
│ ├── open-folder@5xbrz.png
│ └── open-folder@6xbrz.png
└── xbrz-tool
├── README.md
├── pom.xml
└── src
└── main
├── java
└── io
│ └── github
│ └── stanio
│ └── xbrz
│ └── tool
│ └── ScalerTool.java
├── java9
└── module-info.java
└── scripts
├── xbrz-boot.cmd
└── xbrz-boot.sh
/.github/workflows/maven.yml:
--------------------------------------------------------------------------------
1 | # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven
3 |
4 | # This workflow uses actions that are not certified by GitHub.
5 | # They are provided by a third-party and are governed by
6 | # separate terms of service, privacy policy, and support
7 | # documentation.
8 |
9 | name: Java CI with Maven
10 |
11 | on:
12 | push:
13 | branches: [ "master" ]
14 | pull_request:
15 | branches: [ "master" ]
16 |
17 | jobs:
18 | build:
19 |
20 | runs-on: ubuntu-latest
21 |
22 | steps:
23 | - uses: actions/checkout@v4
24 | - name: Set up JDK 21
25 | uses: actions/setup-java@v4
26 | with:
27 | java-version: '21'
28 | distribution: 'temurin'
29 | cache: maven
30 | - name: Build with Maven
31 | run: mvn --batch-mode --show-version --no-transfer-progress verify -P release -Dgpg.skip=true
32 |
33 | # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive
34 | - name: Update dependency graph
35 | uses: advanced-security/maven-dependency-submission-action@v4
36 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .flattened-pom.xml
2 | pom.xml.versionsBackup
3 | /target/
4 | /xbrz-core/target/
5 | /xbrz-awt/target/
6 | /xbrz-tool/target/
7 |
--------------------------------------------------------------------------------
/.mvn/enforcer-extension.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 3.8.8
8 |
9 |
10 | 11
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/.mvn/extensions.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 | org.apache.maven.extensions
8 | maven-enforcer-extension
9 | 3.4.1
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.mvn/readme.txt:
--------------------------------------------------------------------------------
1 | The .mvn directory is needed to be able to use the ${maven.multiModuleProjectDirectory} property.
2 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Code of Conduct
2 |
3 | This project adheres to No Code of Conduct. We are all adults. We accept anyone's contributions. Nothing else matters.
4 |
5 | For more information please visit the [No Code of Conduct](https://nocodeofconduct.com) homepage.
6 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | [BSD Zero Clause License](https://spdx.org/licenses/0BSD),
2 | except for [xbrz-core](xbrz-core/LICENSE).
3 |
4 | Copyright (C) 2020 by Stanio <stanio AT yahoo DOT com>
5 |
6 | Permission to use, copy, modify, and/or distribute this software for
7 | any purpose with or without fee is hereby granted.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 | WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
11 | OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE
12 | FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
13 | DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
14 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15 | OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 |
--------------------------------------------------------------------------------
/PUBLISHING.md:
--------------------------------------------------------------------------------
1 | ## [Publishing By Using the Maven Plugin](https://central.sonatype.org/publish/publish-portal-maven/)
2 |
3 | mvn versions:set -DnewVersion=1.2.3
4 | mvn versions:set-scm-tag -DnewTag=1.2.3
5 | git commit -m "Set stable 1.2.3 version for release"
6 |
7 | # Update site Apidocs
8 |
9 | mvn clean
10 | link-jdk-sources
11 | mvn package -P apidoc javadoc:aggregate-jar -DskipTests
12 |
13 | rm -rf docs/apidocs/
14 | cp -r target/reports/apidocs/ docs/
15 | git add docs/apidocs/
16 | git commit -m "Update the site apidocs for the 1.2.3 release"
17 |
18 | # Tag sources, deploy, and push upstream
19 |
20 | git tag 1.2.3 -m "Release 1.2.3 to Maven Central"
21 |
22 | mvn deploy -P release
23 |
24 | git push origin 1.2.3 master
25 |
26 | ## [Publishing Your Components – Component Validation](https://central.sonatype.org/publish/publish-portal-guide/#component-validation)
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # xBRZ in Java
2 |
3 | [xBRZ](https://sourceforge.net/projects/xbrz/): "Scale by rules" - high quality image upscaling filter by Zenju.
4 |
5 | Java port of xBRZ 1.8 by Stanio.
6 |
7 | ## Modules
8 |
9 | - [xbrz-core](xbrz-core)
10 | - [xbrz-awt](xbrz-awt)
11 | - [xbrz-tool](xbrz-tool)
12 |
13 | ## Demo
14 |
15 | The following is just an approximation due to viewing conditions such as screen
16 | resolution and browser image interpolation.
17 |
18 | The highlighted column is the base (no scaling applied) image:
19 |
20 |
21 |
22 | xBRZ upscaling provides crisp edges and reconstructed detail. Images are
23 | upscaled to an integral factor producing a resultion ≥ target resolution. They
24 | may be then downscaled to the exact target resolution as necessary using a
25 | smooth interpolation.
26 |
27 |
28 |
29 | One may notice downscaling a hires base image using a smooth algorithm (bilinear, bicubic) generally produces better, more detailed results vs. upscaling a lores
30 | base image. Having a source hires variant could make xBRZ unnecessary.
31 |
32 | ## License
33 |
34 | Except for [xbrz-core](xbrz-core), this project, source code and
35 | documentation is released under
36 | [BSD Zero Clause License](https://spdx.org/licenses/0BSD).
37 | See [LICENSE](LICENSE.md).
38 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | ## Core Usage
2 |
3 | ```java
4 | import io.github.stanio.xbrz.Xbrz;
5 | import java.awt.image.BufferedImage;
6 |
7 | BufferedImage source = ...;
8 | int srcWidth = source.getWidth();
9 | int srcHeight = source.getHeight();
10 | int[] srcPixels = source.getRGB(0, 0, srcWidth, srcHeight, null, 0, srcWidth);
11 |
12 | int factor = 2;
13 | int destWidth = srcWidth * factor;
14 | int destHeight = srcHeight * factor;
15 | boolean hasAlpha = source.getColorModel().hasAlpha();
16 | int[] destPixels = Xbrz.scaleImage(factor, hasAlpha, srcPixels, null, srcWidth, srcHeight);
17 |
18 | BufferedImage scaled = new BufferedImage(destWidth, destHeight,
19 | hasAlpha ? BufferedImage.TYPE_INT_ARGB
20 | : BufferedImage.TYPE_INT_RGB);
21 | scaled.setRGB(0, 0, destWidth, destHeight, destPixels, 0, destWidth);
22 | ```
23 |
24 | The given example uses Java AWT `BufferedImage` source just to demonstrate the
25 | input to and the output from the
26 | [`Xbrz`](apidocs/io.github.stanio.xbrz.core/io/github/stanio/xbrz/Xbrz.html)
27 | scaler is 32-bit packed ARGB
28 | pixels. The scaler itself is not dependent on any particular graphics toolkit.
29 |
30 | ## AWT and Swing
31 |
32 | Using [`XbrzImage`](apidocs/io.github.stanio.xbrz.awt/io/github/stanio/xbrz/awt/XbrzImage.html)
33 | one may derive a [`MultiResolutionImage`](https://docs.oracle.com/en/java/javase/21/docs/api/java.desktop/java/awt/image/MultiResolutionImage.html)
34 | from an `Image` source:
35 |
36 | ```java
37 | import java.awt.Image;
38 | import io.github.stanio.xbrz.awt.XbrzImage;
39 |
40 | Image loResImage;
41 | ...
42 | Image xbrzImage = XbrzImage.mrImage(loResImage);
43 | ```
44 |
45 | and/or apply directly to an
46 | [`ImageIcon`](https://docs.oracle.com/en/java/javase/21/docs/api/java.desktop/javax/swing/ImageIcon.html):
47 |
48 | ```java
49 | import javax.swing.ImageIcon;
50 | import io.github.stanio.xbrz.awt.XbrzImage;
51 |
52 | ImageIcon icon;
53 | ...
54 | XbrzImage.apply(icon);
55 | ```
56 |
57 | See the full [API-docs](apidocs).
58 |
--------------------------------------------------------------------------------
/docs/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-slate
--------------------------------------------------------------------------------
/docs/apidocs/allpackages-index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | All Packages (xBRZ for Java 1.8.2)
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
20 |
21 | JavaScript is disabled on your browser.
22 |
23 |
24 |
51 |
52 |
53 |
56 | Package Summary
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | Public domain 2020, 2023
73 |
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/docs/apidocs/copy.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
27 |
28 |
29 |
31 |
33 |
34 |
--------------------------------------------------------------------------------
/docs/apidocs/element-list:
--------------------------------------------------------------------------------
1 | module:io.github.stanio.xbrz.awt
2 | io.github.stanio.xbrz.awt
3 | io.github.stanio.xbrz.awt.util
4 | module:io.github.stanio.xbrz.core
5 | io.github.stanio.xbrz
6 | module:io.github.stanio.xbrz.tool
7 | io.github.stanio.xbrz.tool
8 |
--------------------------------------------------------------------------------
/docs/apidocs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Overview (xBRZ for Java 1.8.2)
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
20 |
21 | JavaScript is disabled on your browser.
22 |
23 |
24 |
51 |
52 |
53 |
56 | xBRZ Java port by Stanio.
57 |
58 |
See Also:
59 |
63 |
64 |
Modules
65 |
66 |
67 |
68 |
69 |
70 |
Provides classes and interfaces for scaling Java AWT Images using xBRZ.
71 |
72 |
73 |
74 |
Provides a Java implementation of the xBRZ algorithm ("Scale by rules" –
75 | high quality image upscaling filter by Zenju).
76 |
77 |
78 |
79 |
Provides the command-line entry point of the (Java) xBRZ scaler tool.
80 |
81 |
82 |
83 |
84 |
85 |
86 | Public domain 2020, 2023
87 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/docs/apidocs/io.github.stanio.xbrz.awt/io/github/stanio/xbrz/awt/class-use/AwtXbrz.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Uses of Class io.github.stanio.xbrz.awt.AwtXbrz (xBRZ for Java 1.8.2)
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
20 |
21 | JavaScript is disabled on your browser.
22 |
23 |
24 |
51 |
52 |
53 |
56 | No usage of io.github.stanio.xbrz.awt.AwtXbrz
57 |
58 |
59 | Public domain 2020, 2023
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/docs/apidocs/io.github.stanio.xbrz.awt/io/github/stanio/xbrz/awt/class-use/XbrzFilter.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Uses of Class io.github.stanio.xbrz.awt.XbrzFilter (xBRZ for Java 1.8.2)
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
20 |
21 | JavaScript is disabled on your browser.
22 |
23 |
24 |
51 |
52 |
53 |
56 |
57 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | Public domain 2020, 2023
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/docs/apidocs/io.github.stanio.xbrz.awt/io/github/stanio/xbrz/awt/class-use/XbrzImage.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Uses of Class io.github.stanio.xbrz.awt.XbrzImage (xBRZ for Java 1.8.2)
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
20 |
21 | JavaScript is disabled on your browser.
22 |
23 |
24 |
51 |
52 |
53 |
56 | No usage of io.github.stanio.xbrz.awt.XbrzImage
57 |
58 |
59 | Public domain 2020, 2023
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/docs/apidocs/io.github.stanio.xbrz.awt/io/github/stanio/xbrz/awt/class-use/XbrzOp.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Uses of Class io.github.stanio.xbrz.awt.XbrzOp (xBRZ for Java 1.8.2)
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
20 |
21 | JavaScript is disabled on your browser.
22 |
23 |
24 |
51 |
52 |
53 |
56 | No usage of io.github.stanio.xbrz.awt.XbrzOp
57 |
58 |
59 | Public domain 2020, 2023
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/docs/apidocs/io.github.stanio.xbrz.awt/io/github/stanio/xbrz/awt/package-tree.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | io.github.stanio.xbrz.awt Class Hierarchy (xBRZ for Java 1.8.2)
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
20 |
21 | JavaScript is disabled on your browser.
22 |
23 |
24 |
51 |
52 |
53 |
56 | Package Hierarchies:
57 |
60 |
61 | Class Hierarchy
62 |
63 | java.lang.Object
64 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | Public domain 2020, 2023
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/docs/apidocs/io.github.stanio.xbrz.awt/io/github/stanio/xbrz/awt/package-use.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Uses of Package io.github.stanio.xbrz.awt (xBRZ for Java 1.8.2)
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
20 |
21 | JavaScript is disabled on your browser.
22 |
23 |
24 |
51 |
52 |
53 |
56 |
57 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
Encapsulates packed image data in a convenient form for input to Xbrz
.
74 |
75 |
76 |
77 |
xBRZ filter for the Image Producer/Consumer paradigm.
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 | Public domain 2020, 2023
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/docs/apidocs/io.github.stanio.xbrz.awt/io/github/stanio/xbrz/awt/util/class-use/SmoothResizeOp.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Uses of Class io.github.stanio.xbrz.awt.util.SmoothResizeOp (xBRZ for Java 1.8.2)
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
20 |
21 | JavaScript is disabled on your browser.
22 |
23 |
24 |
51 |
52 |
53 |
56 | No usage of io.github.stanio.xbrz.awt.util.SmoothResizeOp
57 |
58 |
59 | Public domain 2020, 2023
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/docs/apidocs/io.github.stanio.xbrz.awt/io/github/stanio/xbrz/awt/util/package-use.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Uses of Package io.github.stanio.xbrz.awt.util (xBRZ for Java 1.8.2)
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
20 |
21 | JavaScript is disabled on your browser.
22 |
23 |
24 |
51 |
52 |
53 |
56 |
57 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
Convenience base MultiResolutionImage
implementation...
74 |
75 |
76 |
77 |
Combines multiple filters.
78 |
79 |
80 |
81 |
A MultiResolutionImage
that caches resolution variants as they
82 | get produced.
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 | Public domain 2020, 2023
93 |
94 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/docs/apidocs/io.github.stanio.xbrz.core/io/github/stanio/xbrz/package-tree.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | io.github.stanio.xbrz Class Hierarchy (xBRZ for Java 1.8.2)
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
20 |
21 | JavaScript is disabled on your browser.
22 |
23 |
24 |
51 |
52 |
53 |
56 | Package Hierarchies:
57 |
60 |
61 | Class Hierarchy
62 |
63 | java.lang.Object
64 |
68 |
69 |
70 |
71 |
72 | Interface Hierarchy
73 |
76 |
77 |
78 |
79 |
80 | Public domain 2020, 2023
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/docs/apidocs/io.github.stanio.xbrz.core/module-summary.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | io.github.stanio.xbrz.core (xBRZ for Java 1.8.2)
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
20 |
21 | JavaScript is disabled on your browser.
22 |
23 |
24 |
70 |
71 |
72 |
75 |
76 | module io.github.stanio.xbrz.core
77 |
78 |
79 | Provides a Java implementation of the xBRZ algorithm ("Scale by rules" –
80 | high quality image upscaling filter by Zenju).
81 |
82 |
83 |
84 |
85 |
86 |
87 | Packages
88 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 | Public domain 2020, 2023
105 |
106 |
107 |
108 |
109 |
110 |
--------------------------------------------------------------------------------
/docs/apidocs/io.github.stanio.xbrz.tool/io/github/stanio/xbrz/tool/class-use/ScalerTool.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Uses of Class io.github.stanio.xbrz.tool.ScalerTool (xBRZ for Java 1.8.2)
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
20 |
21 | JavaScript is disabled on your browser.
22 |
23 |
24 |
51 |
52 |
53 |
56 | No usage of io.github.stanio.xbrz.tool.ScalerTool
57 |
58 |
59 | Public domain 2020, 2023
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/docs/apidocs/io.github.stanio.xbrz.tool/io/github/stanio/xbrz/tool/package-tree.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | io.github.stanio.xbrz.tool Class Hierarchy (xBRZ for Java 1.8.2)
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
20 |
21 | JavaScript is disabled on your browser.
22 |
23 |
24 |
51 |
52 |
53 |
56 | Package Hierarchies:
57 |
60 |
61 | Class Hierarchy
62 |
63 | java.lang.Object
64 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | Public domain 2020, 2023
74 |
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/docs/apidocs/io.github.stanio.xbrz.tool/io/github/stanio/xbrz/tool/package-use.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Uses of Package io.github.stanio.xbrz.tool (xBRZ for Java 1.8.2)
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
20 |
21 | JavaScript is disabled on your browser.
22 |
23 |
24 |
51 |
52 |
53 |
56 | No usage of io.github.stanio.xbrz.tool
57 |
58 |
59 | Public domain 2020, 2023
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/docs/apidocs/io.github.stanio.xbrz.tool/module-summary.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | io.github.stanio.xbrz.tool (xBRZ for Java 1.8.2)
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
20 |
21 | JavaScript is disabled on your browser.
22 |
23 |
24 |
70 |
71 |
72 |
75 |
76 | module io.github.stanio.xbrz.tool
77 |
78 |
79 | Provides the command-line entry point of the (Java) xBRZ scaler tool.
80 |
81 |
82 |
83 |
84 |
85 |
86 | Packages
87 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 | Public domain 2020, 2023
104 |
105 |
106 |
107 |
108 |
109 |
--------------------------------------------------------------------------------
/docs/apidocs/legal/ADDITIONAL_LICENSE_INFO:
--------------------------------------------------------------------------------
1 | Please see ..\java.base\ADDITIONAL_LICENSE_INFO
2 |
--------------------------------------------------------------------------------
/docs/apidocs/legal/ASSEMBLY_EXCEPTION:
--------------------------------------------------------------------------------
1 | Please see ..\java.base\ASSEMBLY_EXCEPTION
2 |
--------------------------------------------------------------------------------
/docs/apidocs/legal/LICENSE:
--------------------------------------------------------------------------------
1 | Please see ..\java.base\LICENSE
2 |
--------------------------------------------------------------------------------
/docs/apidocs/legal/jquery.md:
--------------------------------------------------------------------------------
1 | ## jQuery v3.6.1
2 |
3 | ### jQuery License
4 | ```
5 | jQuery v 3.6.1
6 | Copyright OpenJS Foundation and other contributors, https://openjsf.org/
7 |
8 | Permission is hereby granted, free of charge, to any person obtaining
9 | a copy of this software and associated documentation files (the
10 | "Software"), to deal in the Software without restriction, including
11 | without limitation the rights to use, copy, modify, merge, publish,
12 | distribute, sublicense, and/or sell copies of the Software, and to
13 | permit persons to whom the Software is furnished to do so, subject to
14 | the following conditions:
15 |
16 | The above copyright notice and this permission notice shall be
17 | included in all copies or substantial portions of the Software.
18 |
19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 |
27 | ******************************************
28 |
29 | The jQuery JavaScript Library v3.6.1 also includes Sizzle.js
30 |
31 | Sizzle.js includes the following license:
32 |
33 | Copyright JS Foundation and other contributors, https://js.foundation/
34 |
35 | This software consists of voluntary contributions made by many
36 | individuals. For exact contribution history, see the revision history
37 | available at https://github.com/jquery/sizzle
38 |
39 | The following license applies to all parts of this software except as
40 | documented below:
41 |
42 | ====
43 |
44 | Permission is hereby granted, free of charge, to any person obtaining
45 | a copy of this software and associated documentation files (the
46 | "Software"), to deal in the Software without restriction, including
47 | without limitation the rights to use, copy, modify, merge, publish,
48 | distribute, sublicense, and/or sell copies of the Software, and to
49 | permit persons to whom the Software is furnished to do so, subject to
50 | the following conditions:
51 |
52 | The above copyright notice and this permission notice shall be
53 | included in all copies or substantial portions of the Software.
54 |
55 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
56 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
57 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
58 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
59 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
60 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
61 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
62 |
63 | ====
64 |
65 | All files located in the node_modules and external directories are
66 | externally maintained libraries used by this software which have their
67 | own licenses; we recommend you read them, as their terms may differ from
68 | the terms above.
69 |
70 | *********************
71 |
72 | ```
73 |
--------------------------------------------------------------------------------
/docs/apidocs/legal/jqueryUI.md:
--------------------------------------------------------------------------------
1 | ## jQuery UI v1.13.2
2 |
3 | ### jQuery UI License
4 | ```
5 | Copyright jQuery Foundation and other contributors, https://jquery.org/
6 |
7 | This software consists of voluntary contributions made by many
8 | individuals. For exact contribution history, see the revision history
9 | available at https://github.com/jquery/jquery-ui
10 |
11 | The following license applies to all parts of this software except as
12 | documented below:
13 |
14 | ====
15 |
16 | Permission is hereby granted, free of charge, to any person obtaining
17 | a copy of this software and associated documentation files (the
18 | "Software"), to deal in the Software without restriction, including
19 | without limitation the rights to use, copy, modify, merge, publish,
20 | distribute, sublicense, and/or sell copies of the Software, and to
21 | permit persons to whom the Software is furnished to do so, subject to
22 | the following conditions:
23 |
24 | The above copyright notice and this permission notice shall be
25 | included in all copies or substantial portions of the Software.
26 |
27 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 |
35 | ====
36 |
37 | Copyright and related rights for sample code are waived via CC0. Sample
38 | code is defined as all source code contained within the demos directory.
39 |
40 | CC0: http://creativecommons.org/publicdomain/zero/1.0/
41 |
42 | ====
43 |
44 | All files located in the node_modules and external directories are
45 | externally maintained libraries used by this software which have their
46 | own licenses; we recommend you read them, as their terms may differ from
47 | the terms above.
48 |
49 | ```
50 |
--------------------------------------------------------------------------------
/docs/apidocs/link.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/docs/apidocs/module-search-index.js:
--------------------------------------------------------------------------------
1 | moduleSearchIndex = [{"l":"io.github.stanio.xbrz.awt"},{"l":"io.github.stanio.xbrz.core"},{"l":"io.github.stanio.xbrz.tool"}];updateSearchResults();
--------------------------------------------------------------------------------
/docs/apidocs/overview-summary.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | xBRZ for Java 1.8.2
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | JavaScript is disabled on your browser.
22 |
23 | index.html
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/docs/apidocs/package-search-index.js:
--------------------------------------------------------------------------------
1 | packageSearchIndex = [{"l":"All Packages","u":"allpackages-index.html"},{"m":"io.github.stanio.xbrz.core","l":"io.github.stanio.xbrz"},{"m":"io.github.stanio.xbrz.awt","l":"io.github.stanio.xbrz.awt"},{"m":"io.github.stanio.xbrz.awt","l":"io.github.stanio.xbrz.awt.util"},{"m":"io.github.stanio.xbrz.tool","l":"io.github.stanio.xbrz.tool"}];updateSearchResults();
--------------------------------------------------------------------------------
/docs/apidocs/resources/glass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/docs/apidocs/resources/glass.png
--------------------------------------------------------------------------------
/docs/apidocs/resources/x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/docs/apidocs/resources/x.png
--------------------------------------------------------------------------------
/docs/apidocs/script-dir/jquery-ui.min.css:
--------------------------------------------------------------------------------
1 | /*! jQuery UI - v1.13.2 - 2023-02-27
2 | * http://jqueryui.com
3 | * Includes: core.css, autocomplete.css, menu.css
4 | * Copyright jQuery Foundation and other contributors; Licensed MIT */
5 |
6 | .ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;-ms-filter:"alpha(opacity=0)"}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:0}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{margin:0;cursor:pointer;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-item-wrapper{position:relative;padding:3px 1em 3px .4em}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item-wrapper{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}
--------------------------------------------------------------------------------
/docs/apidocs/search.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Search (xBRZ for Java 1.8.2)
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
20 |
21 | JavaScript is disabled on your browser.
22 |
23 |
24 |
47 |
48 |
49 | Search
50 |
51 |
52 |
53 |
54 | Additional resources
55 |
56 |
57 |
58 |
The help page provides an introduction to the scope and syntax of JavaDoc search.
59 |
You can use the <ctrl> or <cmd> keys in combination with the left and right arrow keys to switch between result tabs in this page.
60 |
The URL template below may be used to configure this page as a search engine in browsers that support this feature. It has been tested to work in Google Chrome and Mozilla Firefox. Note that other browsers may not support this feature or require a different URL format.
61 |
link Copy
62 |
63 |
64 | Redirect to first result
65 |
66 | Loading search index...
67 |
71 |
72 |
73 |
74 | Public domain 2020, 2023
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/docs/apidocs/tag-search-index.js:
--------------------------------------------------------------------------------
1 | tagSearchIndex = [];updateSearchResults();
--------------------------------------------------------------------------------
/docs/apidocs/type-search-index.js:
--------------------------------------------------------------------------------
1 | typeSearchIndex = [{"l":"All Classes and Interfaces","u":"allclasses-index.html"},{"p":"io.github.stanio.xbrz.awt","l":"AwtXbrz"},{"p":"io.github.stanio.xbrz.awt.util","l":"BaseMultiResolutionImage"},{"p":"io.github.stanio.xbrz.awt.util","l":"ChainFilterOp"},{"p":"io.github.stanio.xbrz","l":"ColorDistance"},{"p":"io.github.stanio.xbrz.awt","l":"ImageData"},{"p":"io.github.stanio.xbrz.awt.util","l":"MultiResolutionCachedImage"},{"p":"io.github.stanio.xbrz","l":"Xbrz.ScalerCfg"},{"p":"io.github.stanio.xbrz.tool","l":"ScalerTool"},{"p":"io.github.stanio.xbrz.awt.util","l":"SmoothResizeOp"},{"p":"io.github.stanio.xbrz","l":"Xbrz"},{"p":"io.github.stanio.xbrz.awt","l":"XbrzFilter"},{"p":"io.github.stanio.xbrz.awt","l":"XbrzImage"},{"p":"io.github.stanio.xbrz.awt","l":"XbrzOp"}];updateSearchResults();
--------------------------------------------------------------------------------
/docs/googlef1bf138e44956fd2.html:
--------------------------------------------------------------------------------
1 | google-site-verification: googlef1bf138e44956fd2.html
--------------------------------------------------------------------------------
/docs/icons-demo1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/docs/icons-demo1.png
--------------------------------------------------------------------------------
/docs/icons-demo1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/docs/icons-demo1@2x.png
--------------------------------------------------------------------------------
/docs/icons-demo2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/docs/icons-demo2.png
--------------------------------------------------------------------------------
/docs/icons-demo2@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/docs/icons-demo2@2x.png
--------------------------------------------------------------------------------
/link-jdk-sources.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | rem # mvn clean
3 | rem # link-jdk-sources
4 | rem # mvn package -P apidoc javadoc:aggregate-jar -DskipTests
5 | rem # mvn verify -P release -Dgpg.skip=true
6 |
7 | setlocal
8 | set BASE_DIR=%~dp0
9 | if "%BASE_DIR%" == "%CD%\" set BASE_DIR=
10 |
11 | set apidocs_src=target\reports\apidocs\src
12 |
13 | if "%JDK_HOME%" == "" set JDK_HOME=%JAVA_HOME%
14 | if "%JDK_HOME%" == "" (
15 | echo Set JDK_HOME or JAVA_HOME to the JDK home directory
16 | exit /b 2
17 | )
18 |
19 | if not exist "%JDK_HOME%\lib\src\" (
20 | if exist "%JDK_HOME%\lib\src.zip" (
21 | echo Unzip "%JDK_HOME%\lib\src.zip" as "%JDK_HOME%\lib\src" directory
22 | exit /b 3
23 | )
24 | echo JDK sources not found: %JDK_HOME%\lib\src\
25 | exit /b 3
26 | )
27 |
28 | for %%M in (. xbrz-core xbrz-awt xbrz-tool) do (
29 | mkdir %BASE_DIR%%%M\%apidocs_src%
30 | )
31 |
32 | for /d %%D in (%JDK_HOME%\lib\src\*) do (
33 | for %%M in (. xbrz-core xbrz-awt xbrz-tool) do (
34 | mklink /d "%BASE_DIR%%%M\%apidocs_src%\%%~nxD" %%D
35 | )
36 | )
37 |
--------------------------------------------------------------------------------
/src/main/javadoc/overview.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | xBRZ Java port by Stanio.
9 |
10 | See Also:
11 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/xbrz-awt/README.md:
--------------------------------------------------------------------------------
1 | # xBRZ for Java AWT Images
2 |
3 | [](https://central.sonatype.com/artifact/io.github.stanio/xbrz-awt)
4 |
5 | Depends on [xbrz-core](../xbrz-core).
6 |
7 | JPMS name: `io.github.stanio.xbrz.awt` (Java 8 compatible Multi-Release JAR)
8 |
9 | ## API
10 |
11 | - `AwtXbrz` – supports animated (`java.awt.Toolkit` created) images
12 | - `XbrzOp` – single-input/single-output
13 |
14 | Example:
15 |
16 | import io.github.stanio.xbrz.awt.AwtXbrz;
17 | import java.awt.Image;
18 |
19 | Image source;
20 | int factor = 2;
21 | ...
22 | Image scaled = AwtXbrz.scaleImage(image, factor);
23 |
24 | ## Java 9+
25 |
26 | - `XbrzImage.apply(ImageIcon)` – applies xBRZ to existing (lores) `ImageIcon`s
27 | to dynamically produce quality upscaled variants on hires screens;
28 | - `MultiResolutionCachedImage` – general purpose `java.awt.MultiResolutionImage`
29 | implementation.
30 |
--------------------------------------------------------------------------------
/xbrz-awt/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 | 4.0.0
7 |
8 |
9 | io.github.stanio
10 | xbrz-java
11 | 1.8.3-SNAPSHOT
12 |
13 | xbrz-awt
14 |
15 | xBRZ for Java AWT Images
16 | Scaling Java AWT images with xBRZ
17 |
18 |
19 | io.github.stanio.xbrz.awt
20 | false
21 | false
22 | false
23 | io.github.stanio.xbrz.awt.demo.IconsDemo
24 |
25 |
26 |
27 |
28 | ${project.groupId}
29 | xbrz-core
30 | ${project.version}
31 |
32 |
33 |
34 |
35 |
36 |
37 | maven-jar-plugin
38 |
39 |
40 |
41 | true
42 |
43 |
44 |
45 |
46 |
47 | org.codehaus.mojo
48 | exec-maven-plugin
49 |
50 |
51 | demo
52 |
53 | java
54 |
55 |
56 | false
57 | ${exec.mainClass}
58 | test
59 |
60 | ${project.build.outputDirectory}/META-INF/versions/9
61 |
62 |
63 |
64 |
65 |
66 |
67 | org.sonatype.central
68 | central-publishing-maven-plugin
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/xbrz-awt/src/main/java/io/github/stanio/xbrz/awt/ImageData.java:
--------------------------------------------------------------------------------
1 | package io.github.stanio.xbrz.awt;
2 |
3 | import static io.github.stanio.xbrz.Xbrz.targetArraySize;
4 |
5 | import java.awt.Image;
6 | import java.awt.color.ColorSpace;
7 | import java.awt.image.BufferedImage;
8 | import java.awt.image.ColorModel;
9 | import java.awt.image.DataBufferInt;
10 | import java.awt.image.ImageObserver;
11 | import java.awt.image.PixelGrabber;
12 | import java.awt.image.Raster;
13 | import java.util.concurrent.atomic.AtomicReference;
14 |
15 | /**
16 | * Encapsulates packed image data in a convenient form for input to {@code Xbrz}.
17 | */
18 | public final class ImageData {
19 |
20 | private static final int[] ANIMATED_PIXELS = new int[0];
21 |
22 | private static final ColorSpace CS_LINEAR_RGB =
23 | ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB);
24 |
25 | private static final boolean DEBUG = false;
26 |
27 | public final int width;
28 | public final int height;
29 | public final boolean hasAlpha;
30 | final int[] pixels;
31 |
32 | ImageData(BufferedImage image) {
33 | this(image, false);
34 | }
35 |
36 | ImageData(BufferedImage image, boolean untracked) {
37 | width = image.getWidth();
38 | height = image.getHeight();
39 | hasAlpha = image.getColorModel().hasAlpha();
40 | pixels = getRGB(image, untracked);
41 | }
42 |
43 | ImageData(PixelGrabber image, boolean transparency) {
44 | width = image.getWidth();
45 | height = image.getHeight();
46 | //hasAlpha = image.getColorModel().hasAlpha();
47 | hasAlpha = transparency;
48 | pixels = (image.getStatus() & ImageObserver.ALLBITS) != 0
49 | ? (int[]) image.getPixels()
50 | : ANIMATED_PIXELS;
51 | }
52 |
53 | ImageData(ImageData source, int factor) {
54 | width = source.width * factor;
55 | height = source.height * factor;
56 | hasAlpha = source.hasAlpha;
57 | pixels = new int[targetArraySize(source.width, source.height, factor)];
58 | }
59 |
60 | private static int[] getRGB(BufferedImage image, boolean untracked) {
61 | int width = image.getWidth();
62 | int height = image.getHeight();
63 | int imageType = image.getType();
64 | ColorSpace colorSpace = image.getColorModel().getColorSpace();
65 | if ((imageType == BufferedImage.TYPE_INT_ARGB
66 | || imageType == BufferedImage.TYPE_INT_RGB)
67 | && (colorSpace.isCS_sRGB() || colorSpace == CS_LINEAR_RGB)) {
68 | Raster raster = image.getRaster();
69 | if (untracked && raster.getDataBuffer().getNumBanks() == 1) {
70 | return ((DataBufferInt) raster.getDataBuffer()).getData();
71 | }
72 | return (int[]) raster.getDataElements(0, 0, width, height, null);
73 | }
74 | return image.getRGB(0, 0, width, height, null, 0, width);
75 | }
76 |
77 | /**
78 | * Obtains image-data from the given source.
79 | *
80 | * Note, the returned data may indicate {@code animated == true} in which case
81 | * the instance doesn't contain pixel data and can't be used as argument to
82 | * methods that otherwise accept image-data as input.
83 | *
84 | * @param image source image to obtain image-data from
85 | * @return image-data of the given source, or {@code null} if error occurs
86 | * @see #isAnimated()
87 | */
88 | public static ImageData get(Image image) {
89 | if (image instanceof BufferedImage) {
90 | return new ImageData((BufferedImage) image);
91 | }
92 |
93 | AtomicReference hasTranslucency = new AtomicReference<>();
94 | PixelGrabber grabber = new PixelGrabber(image, 0, 0, -1, -1, true) {
95 | @Override public void setColorModel(ColorModel model) {
96 | if (model != ColorModel.getRGBdefault()) {
97 | hasTranslucency.set(model.hasAlpha());
98 | }
99 | }
100 | @Override public void setPixels(int srcX, int srcY, int srcW, int srcH,
101 | ColorModel model, int[] pixels, int srcOff, int srcScan) {
102 | super.setPixels(srcX, srcY, srcW, srcH, model, pixels, srcOff, srcScan);
103 | if (hasTranslucency.get() == null) {
104 | if (!model.hasAlpha()) {
105 | hasTranslucency.set(false);
106 | return;
107 | }
108 | for (int i = 0, len = pixels.length; i < len; i++) {
109 | if (model.getAlpha(pixels[i]) < 255) {
110 | hasTranslucency.set(true);
111 | break;
112 | }
113 | }
114 | }
115 | }
116 | };
117 |
118 | try {
119 | if (grabber.grabPixels(60_000L)) {
120 | return new ImageData(grabber, Boolean.TRUE.equals(hasTranslucency.get()));
121 | }
122 | } catch (InterruptedException e) {
123 | Thread.currentThread().interrupt();
124 | if (DEBUG) {
125 | e.printStackTrace();
126 | }
127 | }
128 | if (DEBUG) {
129 | System.out.println("Pixel grabber status: " + grabber.getStatus());
130 | }
131 | return null;
132 | }
133 |
134 | public boolean isAnimated() {
135 | return pixels == ANIMATED_PIXELS;
136 | }
137 |
138 | }
139 |
--------------------------------------------------------------------------------
/xbrz-awt/src/main/java/io/github/stanio/xbrz/awt/ScalerPool.java:
--------------------------------------------------------------------------------
1 | package io.github.stanio.xbrz.awt;
2 |
3 | import java.util.Map;
4 | import java.util.concurrent.ConcurrentHashMap;
5 |
6 | import io.github.stanio.xbrz.Xbrz;
7 |
8 | class ScalerPool {
9 |
10 |
11 | private static final class ScalerKey {
12 |
13 | final int scale;
14 | final boolean hasAlpha;
15 | private final int hash;
16 |
17 | private ScalerKey(int scale, boolean hasAlpha) {
18 | this.scale = scale;
19 | this.hasAlpha = hasAlpha;
20 |
21 | final int prime = 31;
22 | int hashCode = 1;
23 | hashCode = prime * hashCode + (hasAlpha ? 1231 : 1237);
24 | hashCode = prime * hashCode + scale;
25 | this.hash = hashCode;
26 | }
27 |
28 | static ScalerKey of(int scale, boolean hasAlpha) {
29 | return new ScalerKey(scale, hasAlpha);
30 | }
31 |
32 | @Override
33 | public int hashCode() {
34 | return hash;
35 | }
36 |
37 | @Override
38 | public boolean equals(Object obj) {
39 | if (obj instanceof ScalerKey) {
40 | ScalerKey other = (ScalerKey) obj;
41 | return scale == other.scale && hasAlpha == other.hasAlpha;
42 | }
43 | return false;
44 | }
45 |
46 | }
47 |
48 |
49 | private static Map scalers = new ConcurrentHashMap<>();
50 |
51 | static Xbrz getScaler(int factor, boolean withAlpha) {
52 | return scalers.computeIfAbsent(ScalerKey.of(factor, withAlpha),
53 | key -> new Xbrz(key.scale, key.hasAlpha));
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/xbrz-awt/src/main/java/io/github/stanio/xbrz/awt/SuspendableFilteredSource.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 by Stanio
3 | * Released under BSD Zero Clause License: https://spdx.org/licenses/0BSD
4 | */
5 | package io.github.stanio.xbrz.awt;
6 |
7 | import java.lang.ref.WeakReference;
8 | import java.util.Hashtable;
9 | import java.util.WeakHashMap;
10 | import java.util.function.Consumer;
11 |
12 | import java.awt.image.ColorModel;
13 | import java.awt.image.ImageConsumer;
14 | import java.awt.image.ImageFilter;
15 | import java.awt.image.ImageProducer;
16 |
17 | /**
18 | * Allows to stop production to currently registered consumers. The main
19 | * use-case is for filtered animation sources. When a filtered (animation)
20 | * image needs to be replaced with a differently configured filtered source,
21 | * one may invoke {@code removeAllConsumers()} on a previous source to stop
22 | * filtering.
23 | *
24 | * This filter also registers weak {@code ImageConsumer} proxies with the
25 | * original producer, so they may get discarded/unregistered automatically
26 | * when not reachable from other sources.
27 | */
28 | class SuspendableFilteredSource implements ImageProducer {
29 |
30 | final ImageProducer imageSource;
31 | final ImageFilter filterFactory;
32 |
33 | final WeakHashMap proxies;
34 |
35 | SuspendableFilteredSource(ImageProducer source, ImageFilter filter) {
36 | imageSource = source;
37 | filterFactory = filter;
38 | proxies = new WeakHashMap<>(1);
39 | }
40 |
41 | private WeakConsumerProxy addFilterProxy(ImageConsumer consumer) {
42 | WeakConsumerProxy proxy = new WeakConsumerProxy(consumer);
43 | proxies.put(consumer, proxy);
44 | return proxy;
45 | }
46 |
47 | @Override
48 | public synchronized void addConsumer(ImageConsumer consumer) {
49 | WeakConsumerProxy proxy = proxies.get(consumer);
50 | if (proxy == null) {
51 | proxy = addFilterProxy(consumer);
52 | imageSource.addConsumer(proxy.filter);
53 | }
54 | }
55 |
56 | @Override
57 | public synchronized boolean isConsumer(ImageConsumer consumer) {
58 | return proxies.containsKey(consumer);
59 | }
60 |
61 | @Override
62 | public synchronized void removeConsumer(ImageConsumer consumer) {
63 | WeakConsumerProxy proxy = proxies.remove(consumer);
64 | if (proxy != null) {
65 | imageSource.removeConsumer(proxy.filter);
66 | }
67 | }
68 |
69 | @Override
70 | public synchronized void startProduction(ImageConsumer consumer) {
71 | WeakConsumerProxy proxy = proxies.get(consumer);
72 | if (proxy == null) {
73 | proxy = addFilterProxy(consumer);
74 | }
75 | imageSource.startProduction(proxy.filter);
76 | }
77 |
78 | @Override
79 | public synchronized void requestTopDownLeftRightResend(ImageConsumer consumer) {
80 | WeakConsumerProxy proxy = proxies.get(consumer);
81 | if (proxy != null) {
82 | proxy.filter.resendTopDownLeftRight(imageSource);
83 | }
84 | }
85 |
86 | synchronized void stopProduction() {
87 | suspendProduction();
88 | proxies.clear();
89 | }
90 |
91 | synchronized void suspendProduction() {
92 | proxies.forEach((k, proxy) ->
93 | imageSource.removeConsumer(proxy.filter));
94 | }
95 |
96 | synchronized void resumeProduction() {
97 | proxies.forEach((k, proxy) ->
98 | imageSource.startProduction(proxy.filter));
99 | }
100 |
101 |
102 | class WeakConsumerProxy
103 | extends WeakReference
104 | implements ImageConsumer {
105 |
106 | final ImageFilter filter;
107 |
108 | WeakConsumerProxy(ImageConsumer referent) {
109 | super(referent);
110 | filter = filterFactory.getFilterInstance(this);
111 | }
112 |
113 | void nullSafe(Consumer task) {
114 | ImageConsumer consumer = get();
115 | if (consumer == null) {
116 | imageSource.removeConsumer(filter);
117 | } else {
118 | task.accept(consumer);
119 | }
120 | }
121 |
122 | @Override
123 | public void setDimensions(int width, int height) {
124 | nullSafe(consumer -> consumer.setDimensions(width, height));
125 | }
126 |
127 | @Override
128 | public void setProperties(Hashtable, ?> props) {
129 | nullSafe(consumer -> consumer.setProperties(props));
130 | }
131 |
132 | @Override
133 | public void setColorModel(ColorModel model) {
134 | nullSafe(consumer -> consumer.setColorModel(model));
135 | }
136 |
137 | @Override
138 | public void setHints(int hintflags) {
139 | nullSafe(consumer -> consumer.setHints(hintflags));
140 | }
141 |
142 | @Override
143 | public void setPixels(int x, int y, int w, int h,
144 | ColorModel model, byte[] pixels, int off, int scansize) {
145 | nullSafe(consumer -> consumer
146 | .setPixels(x, y, w, h, model, pixels, off, scansize));
147 | }
148 |
149 | @Override
150 | public void setPixels(int x, int y, int w, int h,
151 | ColorModel model, int[] pixels, int off, int scansize) {
152 | nullSafe(consumer -> consumer
153 | .setPixels(x, y, w, h, model, pixels, off, scansize));
154 | }
155 |
156 | @Override
157 | public void imageComplete(int status) {
158 | nullSafe(consumer -> consumer.imageComplete(status));
159 | }
160 |
161 | } // class WeakConsumerProxy
162 |
163 |
164 | }
165 |
--------------------------------------------------------------------------------
/xbrz-awt/src/main/java/io/github/stanio/xbrz/awt/XbrzOp.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This module, both source code and documentation,
3 | * is in the Public Domain, and comes with NO WARRANTY.
4 | */
5 | package io.github.stanio.xbrz.awt;
6 |
7 | import java.awt.Graphics2D;
8 | import java.awt.Rectangle;
9 | import java.awt.RenderingHints;
10 | import java.awt.geom.Point2D;
11 | import java.awt.geom.Rectangle2D;
12 | import java.awt.image.BufferedImage;
13 | import java.awt.image.BufferedImageOp;
14 | import java.awt.image.ColorModel;
15 | import java.awt.image.DataBufferInt;
16 | import java.util.Objects;
17 |
18 | /**
19 | * Single-input/single-output xBRZ operation.
20 | */
21 | public class XbrzOp implements BufferedImageOp {
22 |
23 | private final int factor;
24 |
25 | private final RenderingHints hints;
26 |
27 | private final boolean directBuffer;
28 |
29 | public XbrzOp(int factor) {
30 | this(factor, null);
31 | }
32 |
33 | public XbrzOp(int factor, RenderingHints hints) {
34 | this(factor, false, hints);
35 | }
36 |
37 | XbrzOp(int factor, boolean direct, RenderingHints hints) {
38 | this.factor = factor;
39 | this.directBuffer = direct;
40 | this.hints = hints;
41 | }
42 |
43 | @Override
44 | public RenderingHints getRenderingHints() {
45 | return hints;
46 | }
47 |
48 | @Override
49 | public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
50 | Point2D point = (dstPt == null) ? new Point2D.Double() : dstPt;
51 | point.setLocation(srcPt.getX() * factor, srcPt.getY() * factor);
52 | return point;
53 | }
54 |
55 | @Override
56 | public Rectangle2D getBounds2D(BufferedImage src) {
57 | return new Rectangle2D.Double(0, 0, (double) src.getWidth() * factor,
58 | (double) src.getHeight() * factor);
59 | }
60 |
61 | @Override
62 | public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM) {
63 | Rectangle bounds = getBounds2D(src).getBounds();
64 | if (destCM == null) {
65 | return new BufferedImage(bounds.width, bounds.height,
66 | src.getColorModel().hasAlpha()
67 | ? BufferedImage.TYPE_INT_ARGB
68 | : BufferedImage.TYPE_INT_RGB);
69 | }
70 | return new BufferedImage(destCM,
71 | destCM.createCompatibleWritableRaster(bounds.width, bounds.height),
72 | destCM.isAlphaPremultiplied(), null);
73 | }
74 |
75 | @Override
76 | public BufferedImage filter(BufferedImage src, BufferedImage dst) {
77 | Objects.requireNonNull(src, "src image is null");
78 | if (src == dst) {
79 | throw new IllegalArgumentException("src image cannot be the same as the dst image");
80 | }
81 | return filter(new ImageData(src, directBuffer), dst);
82 | }
83 |
84 | BufferedImage filter(ImageData src, BufferedImage dst) {
85 | BufferedImage xbrz = AwtXbrz.scaleImage(src, factor, directBuffer);
86 | if (dst == null) {
87 | return xbrz;
88 | }
89 |
90 | if (hints == null) {
91 | int[] rgb = ((DataBufferInt) xbrz.getRaster().getDataBuffer()).getData();
92 | int w = Math.min(xbrz.getWidth(), dst.getWidth());
93 | int h = Math.min(xbrz.getHeight(), dst.getHeight());
94 | dst.setRGB(0, 0, w, h, rgb, 0, xbrz.getWidth());
95 | } else {
96 | Graphics2D g = dst.createGraphics();
97 | try {
98 | g.setRenderingHints(hints);
99 | g.drawImage(xbrz, 0, 0, null);
100 | } finally {
101 | g.dispose();
102 | }
103 | }
104 | return dst;
105 | }
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/xbrz-awt/src/main/java/io/github/stanio/xbrz/awt/util/ChainFilterOp.java:
--------------------------------------------------------------------------------
1 | package io.github.stanio.xbrz.awt.util;
2 |
3 | import java.awt.Rectangle;
4 | import java.awt.RenderingHints;
5 | import java.awt.geom.Point2D;
6 | import java.awt.geom.Rectangle2D;
7 | import java.awt.image.BufferedImage;
8 | import java.awt.image.BufferedImageOp;
9 | import java.awt.image.ColorModel;
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 | /**
14 | * Combines multiple filters.
15 | */
16 | public class ChainFilterOp implements BufferedImageOp {
17 |
18 | private List filterChain;
19 |
20 | public ChainFilterOp() {
21 | filterChain = new ArrayList<>();
22 | }
23 |
24 | public static ChainFilterOp first(BufferedImageOp first) {
25 | return new ChainFilterOp().next(first);
26 | }
27 |
28 | public ChainFilterOp next(BufferedImageOp next) {
29 | filterChain.add(next);
30 | return this;
31 | }
32 |
33 | private List filterChain() {
34 | if (filterChain.isEmpty()) {
35 | throw new IllegalStateException("No filters added to the chain");
36 | }
37 | return filterChain;
38 | }
39 |
40 | @Override
41 | public RenderingHints getRenderingHints() {
42 | BufferedImageOp lastOp = filterChain().get(filterChain.size() - 1);
43 | return lastOp.getRenderingHints();
44 | }
45 |
46 | @Override
47 | public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
48 | Point2D current = srcPt;
49 | Point2D result = dstPt;
50 | List chain = filterChain();
51 | for (int i = 0, len = chain.size(); i < len; i++) {
52 | result = current = chain.get(i).getPoint2D(current, result);
53 | }
54 | return result;
55 | }
56 |
57 | @Override
58 | public Rectangle2D getBounds2D(BufferedImage src) {
59 | BufferedImage dest = createCompatibleDestImage(src, null);
60 | return new Rectangle(dest.getWidth(), dest.getHeight());
61 | }
62 |
63 | @Override
64 | public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM) {
65 | BufferedImage result = src;
66 | List chain = filterChain();
67 | for (int i = 0, len = chain.size(); i < len; i++) {
68 | result = chain.get(i).createCompatibleDestImage(result, destCM);
69 | }
70 | return result;
71 | }
72 |
73 | @Override
74 | public BufferedImage filter(BufferedImage src, BufferedImage dest) {
75 | BufferedImage current = src;
76 | List chain = filterChain();
77 | for (int i = 0, len = chain.size() - 1; i < len; i++) {
78 | current = chain.get(i).filter(current, null);
79 | }
80 | return chain.get(chain.size() - 1).filter(current, dest);
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/xbrz-awt/src/main/java/io/github/stanio/xbrz/awt/util/SmoothResizeOp.java:
--------------------------------------------------------------------------------
1 | package io.github.stanio.xbrz.awt.util;
2 |
3 | import java.awt.Graphics2D;
4 | import java.awt.Rectangle;
5 | import java.awt.RenderingHints;
6 | import java.awt.geom.Point2D;
7 | import java.awt.geom.Rectangle2D;
8 | import java.awt.image.BufferedImage;
9 | import java.awt.image.BufferedImageOp;
10 | import java.awt.image.ColorModel;
11 | import java.awt.image.DirectColorModel;
12 |
13 | /**
14 | * Smoother downscale result for factors > 2x.
15 | *
16 | * @see The Perils of Image.getScaledInstance() by Chris Campbell (archived from
18 | * <https://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html>)
19 | * @see Downscaling images in Java by Morten Nobel-Jørgensen
21 | */
22 | public class SmoothResizeOp implements BufferedImageOp {
23 |
24 | private static final ColorModel RGB_OPAQUE =
25 | new DirectColorModel(24, 0x00FF0000, 0x0000FF00, 0x000000FF, 0);
26 |
27 | private final int destWidth;
28 | private final int destHeight;
29 |
30 | public SmoothResizeOp(int destWidth, int destHeight) {
31 | this.destWidth = destWidth;
32 | this.destHeight = destHeight;
33 | }
34 |
35 | @Override
36 | public RenderingHints getRenderingHints() {
37 | return null;
38 | }
39 |
40 | @Override
41 | public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
42 | Point2D result = (dstPt == null) ? (Point2D) srcPt.clone() : dstPt;
43 | result.setLocation(Math.min(srcPt.getX(), destWidth),
44 | Math.min(srcPt.getY(), destHeight));
45 | return result;
46 | }
47 |
48 | @Override
49 | public Rectangle2D getBounds2D(BufferedImage src) {
50 | return new Rectangle(destWidth, destHeight);
51 | }
52 |
53 | @Override
54 | public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM) {
55 | ColorModel colorModel = destCM;
56 | if (colorModel == null) {
57 | colorModel = src.getColorModel().hasAlpha() ? ColorModel.getRGBdefault()
58 | : RGB_OPAQUE;
59 | }
60 | return new BufferedImage(colorModel,
61 | colorModel.createCompatibleWritableRaster(destWidth, destHeight),
62 | colorModel.isAlphaPremultiplied(), null);
63 | }
64 |
65 | @Override
66 | public BufferedImage filter(BufferedImage src, BufferedImage dest) {
67 | BufferedImage target = dest;
68 | if (target == null) {
69 | target = createCompatibleDestImage(src, null);
70 | }
71 | return resizeSmooth(src, target, destWidth, destHeight);
72 | }
73 |
74 | private BufferedImage resizeSmooth(BufferedImage src,
75 | BufferedImage dest,
76 | int targetWidth,
77 | int targetHeight) {
78 | int halfWidth = (int) Math.ceil(src.getWidth() / 2);
79 | int halfHeight = (int) Math.ceil(src.getHeight() / 2);
80 |
81 | BufferedImage source = src;
82 | if (targetWidth < halfWidth
83 | || targetHeight < halfHeight) {
84 | int w = (targetWidth < halfWidth) ? targetWidth * 2 : targetWidth;
85 | int h = (targetHeight < halfHeight) ? targetHeight * 2 : targetHeight;
86 | source = resizeSmooth(src, null, w, h);
87 | }
88 |
89 | BufferedImage target = dest;
90 | if (target == null) {
91 | int imageType = src.getColorModel().hasAlpha()
92 | ? BufferedImage.TYPE_INT_ARGB
93 | : BufferedImage.TYPE_INT_RGB;
94 | target = new BufferedImage(targetWidth, targetHeight, imageType);
95 | }
96 | Graphics2D g = target.createGraphics();
97 | if (getRenderingHints() == null) {
98 | setSmoothHints(g);
99 | } else {
100 | g.setRenderingHints(getRenderingHints());
101 | }
102 | try {
103 | g.drawImage(source, 0, 0, targetWidth, targetHeight, null);
104 | } finally {
105 | g.dispose();
106 | }
107 | return target;
108 | }
109 |
110 | private static void setSmoothHints(Graphics2D g) {
111 | g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
112 | RenderingHints.VALUE_INTERPOLATION_BICUBIC);
113 | g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,
114 | RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/xbrz-awt/src/main/java9/io/github/stanio/xbrz/awt/AnimatedMultiResolutionImage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2023 by Stanio
3 | * Released under BSD Zero Clause License: https://spdx.org/licenses/0BSD
4 | */
5 | package io.github.stanio.xbrz.awt;
6 |
7 | import java.util.Map;
8 | import java.util.concurrent.ConcurrentHashMap;
9 |
10 | import java.awt.Image;
11 | import java.awt.image.ImageProducer;
12 |
13 | import io.github.stanio.xbrz.ColorDistance;
14 | import io.github.stanio.xbrz.Xbrz;
15 | import io.github.stanio.xbrz.Xbrz.ScalerCfg;
16 | import io.github.stanio.xbrz.awt.util.BaseMultiResolutionImage;
17 |
18 | class AnimatedMultiResolutionImage extends BaseMultiResolutionImage {
19 |
20 | private final Image baseImage;
21 |
22 | private int lastFactor;
23 | private Image lastVariant;
24 |
25 | AnimatedMultiResolutionImage(Image baseImage) {
26 | super(preloadDimensions(baseImage).getWidth(null),
27 | baseImage.getHeight(null));
28 | this.baseImage = baseImage;
29 | }
30 |
31 | @Override
32 | protected Image getBaseImage() {
33 | return baseImage;
34 | }
35 |
36 | @Override
37 | public Image getResolutionVariant(double destWidth, double destHeight) {
38 | int width = (int) Math.ceil(destWidth);
39 | int height = (int) Math.ceil(destHeight);
40 | int factor = AwtXbrz.findFactor(baseWidth, baseHeight, width, height);
41 | if (factor == lastFactor) {
42 | return lastVariant;
43 | }
44 |
45 | ImageProducer lastSource = (lastVariant == null) ? null
46 | : lastVariant.getSource();
47 | if (lastSource instanceof SuspendableFilteredSource) {
48 | ((SuspendableFilteredSource) lastSource).stopProduction();
49 | }
50 |
51 | lastFactor = factor;
52 | if (factor == 1) {
53 | return (lastVariant = baseImage);
54 | }
55 | Xbrz scaler = scalers.computeIfAbsent(factor, k ->
56 | new Xbrz(k, true, new ScalerCfg(), ColorDistance.bufferedYCbCr(5)));
57 | return lastVariant = preloadDimensions(
58 | XbrzFilter.createScaledImage(baseImage, scaler));
59 | }
60 |
61 | private static final Map scalers = new ConcurrentHashMap<>();
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/xbrz-awt/src/main/java9/io/github/stanio/xbrz/awt/XbrzImage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This module, both source code and documentation,
3 | * is in the Public Domain, and comes with NO WARRANTY.
4 | */
5 | package io.github.stanio.xbrz.awt;
6 |
7 | import java.util.Objects;
8 |
9 | import java.awt.Image;
10 | import java.awt.image.MultiResolutionImage;
11 |
12 | import javax.swing.ImageIcon;
13 |
14 | import io.github.stanio.xbrz.awt.util.MultiResolutionCachedImage;
15 |
16 | /**
17 | * xBRZ scaled icons.
18 | *
19 | * {@code new ImageIcon(...)} → {@code XbrzImage.apply(new ImageIcon(...))}
20 | */
21 | public final class XbrzImage {
22 |
23 | private XbrzImage() {/* no instances */}
24 |
25 | /**
26 | * Sets up the given icon with a {@code MultiResolutionImage} deriving
27 | * resolution variants by applying xBRZ to the icon's current image.
28 | * Replaces the given icon's image with a multi-resolution one that uses
29 | * the current icon's image to produce resolution variants as requested.
30 | *
31 | * @param icon image icon to set up
32 | * @return The given {@code ImageIcon} with image updated to a
33 | * {@code MultiResolutionImage} deriving resolution variants by
34 | * applying xBRZ to the icon's current image
35 | */
36 | public static ImageIcon apply(ImageIcon icon) {
37 | Image baseImage = Objects.requireNonNull(icon.getImage(), "icon.image");
38 | ImageData imageData = ImageData.get(baseImage);
39 | Image mrImage;
40 | if (imageData.isAnimated()) {
41 | mrImage = new AnimatedMultiResolutionImage(baseImage);
42 | } else {
43 | mrImage = MultiResolutionCachedImage
44 | .withProducer(icon.getIconWidth(), icon.getIconHeight(),
45 | (w, h) -> AwtXbrz.scaleImage(imageData, null, w, h));
46 | }
47 | icon.setImage(mrImage);
48 | return icon;
49 | }
50 |
51 | /**
52 | * Creates a {@code MultiResolutionImage} deriving resolution variants by
53 | * applying xBRZ to the given image.
54 | *
55 | * @param an {@code Image} subclass that implements {@code MultiResolutionImage}
56 | * @param image base image to derive resolution variants from
57 | * @return A {@code MultiResolutionImage} dynamically producing xBRZ variants
58 | * @see MultiResolutionCachedImage
59 | */
60 | public static M mrImage(Image image) {
61 | @SuppressWarnings("unchecked")
62 | M mrImage = (M) apply(new ImageIcon(image)).getImage();
63 | return mrImage;
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/xbrz-awt/src/main/java9/module-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This module, both source code and documentation,
3 | * is in the Public Domain, and comes with NO WARRANTY.
4 | */
5 |
6 | /**
7 | * Provides classes and interfaces for scaling Java AWT Images using xBRZ.
8 | */
9 | module io.github.stanio.xbrz.awt {
10 |
11 | exports io.github.stanio.xbrz.awt;
12 | exports io.github.stanio.xbrz.awt.util;
13 |
14 | requires transitive io.github.stanio.xbrz.core;
15 | requires transitive java.desktop;
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/xbrz-awt/src/test/java/io/github/stanio/xbrz/awt/AbstractAwtXbrzTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This module, both source code and documentation,
3 | * is in the Public Domain, and comes with NO WARRANTY.
4 | */
5 | package io.github.stanio.xbrz.awt;
6 |
7 | import static org.junit.Assert.assertEquals;
8 | import static org.junit.Assert.assertTrue;
9 |
10 | import java.awt.Toolkit;
11 | import java.awt.image.BufferedImage;
12 | import java.io.IOException;
13 | import java.net.URL;
14 |
15 | import javax.imageio.ImageIO;
16 |
17 | import org.junit.Rule;
18 | import org.junit.rules.TestName;
19 |
20 | public abstract class AbstractAwtXbrzTest {
21 |
22 | @Rule
23 | public TestName testName = new TestName();
24 |
25 | protected static Toolkit toolkit() {
26 | return Toolkit.getDefaultToolkit();
27 | }
28 |
29 | protected void assertEqualPixels(BufferedImage actual, String expected) throws IOException {
30 | assertEqualPixels(testName.getMethodName(), actual, expected);
31 | }
32 |
33 | protected static void assertEqualPixels(String name, BufferedImage actual, String expected) throws IOException {
34 | assertPixels(name, getPixels(actual), getPixels(ImageIO.read(resource(expected))), 0.0001);
35 | }
36 |
37 | private static void assertPixels(String name, int[] destPixels, int[] refPixels, double deviation) {
38 | assertEquals("pixels size", refPixels.length, destPixels.length);
39 | int mismatch = 0;
40 | for (int i = 0, len = refPixels.length; i < len; i++) {
41 | if (destPixels[i] != refPixels[i]) {
42 | mismatch += 1;
43 | }
44 | }
45 | double percent = mismatch * 100.0 / destPixels.length;
46 | String message = String.format("Pixel mismatch: %d (%.3f%%)", mismatch, percent);
47 | System.out.printf("%s [%s]%n", message, name);
48 | assertTrue(message, percent <= deviation);
49 | }
50 |
51 | private static int[] getPixels(BufferedImage image) {
52 | return image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, image.getWidth());
53 | }
54 |
55 | protected static URL resource(String name) {
56 | return AbstractAwtXbrzTest.class.getResource("images/" + name);
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/xbrz-awt/src/test/java/io/github/stanio/xbrz/awt/AwtXbrzFindFactorTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This module, both source code and documentation,
3 | * is in the Public Domain, and comes with NO WARRANTY.
4 | */
5 | package io.github.stanio.xbrz.awt;
6 |
7 | import static org.junit.Assert.assertEquals;
8 |
9 | import org.junit.Test;
10 | import org.junit.runner.RunWith;
11 | import org.junit.runners.Parameterized;
12 | import org.junit.runners.Parameterized.Parameters;
13 |
14 | @RunWith(Parameterized.class)
15 | public class AwtXbrzFindFactorTest {
16 |
17 | private static final int sourceWidth = 25;
18 | private static final int sourceHeight = 15;
19 |
20 | private int destWidth;
21 | private int destHeight;
22 | private int expectedFactor;
23 |
24 | public AwtXbrzFindFactorTest(int destWidth, int destHeight, int expectedFactor) {
25 | this.destWidth = destWidth;
26 | this.destHeight = destHeight;
27 | this.expectedFactor = expectedFactor;
28 | }
29 |
30 | @Parameters(name = "{index}: {0} x {1} => {2}")
31 | public static Object[][] parameters() {
32 | return new Object[][] {
33 | { sourceWidth, sourceHeight, 1 },
34 | { sourceWidth - 5, sourceHeight - 5, 1 },
35 | { (int) (sourceWidth * 1.2), (int) (sourceHeight * 1.2), 2 },
36 | { (int) (sourceWidth * 1.2), sourceHeight - 10, 2 },
37 | { (int) (sourceWidth * 1.8), (int) (sourceHeight * 1.8), 2 },
38 | { sourceWidth * 2, sourceHeight * 2, 2 },
39 | { (int) (sourceWidth * 2.2), (int) (sourceHeight * 2.2), 3 },
40 | { sourceWidth - 10, (int) (sourceHeight * 2.2), 3 },
41 | { (int) (sourceWidth * 2.8), (int) (sourceHeight * 2.8), 3 },
42 | { sourceWidth * 3, sourceHeight * 3, 3 },
43 | { (int) (sourceWidth * 3.2), (int) (sourceHeight * 3.2), 4 },
44 | { sourceWidth - 10, (int) (sourceHeight * 3.8), 4 },
45 | { (int) (sourceWidth * 3.8), (int) (sourceHeight * 3.8), 4 },
46 | { sourceWidth * 4, sourceHeight * 4, 4 },
47 | { (int) (sourceWidth * 4.2), (int) (sourceHeight * 4.2), 5 },
48 | { (int) (sourceWidth * 4.8), sourceHeight - 10, 5 },
49 | { (int) (sourceWidth * 4.8), (int) (sourceHeight * 4.8), 5 },
50 | { sourceWidth * 5, sourceHeight * 5, 5 },
51 | { (int) (sourceWidth * 5.2), (int) (sourceHeight * 5.8), 6 },
52 | { sourceWidth * 6, sourceHeight * 6, 6 },
53 | { (int) (sourceWidth * 6.2), (int) (sourceHeight * 5.8), 6 },
54 | { (int) (sourceWidth * 5.2), (int) (sourceHeight * 6.8), 6 },
55 | { sourceWidth * 16, sourceHeight * 16, 6 },
56 | { sourceWidth * 33, sourceHeight * 33, 6 },
57 | };
58 | }
59 |
60 | @Test
61 | public void findFactor() {
62 | assertEquals("Scale factor", expectedFactor, AwtXbrz
63 | .findFactor(sourceWidth, sourceHeight, destWidth, destHeight));
64 | }
65 |
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/xbrz-awt/src/test/java/io/github/stanio/xbrz/awt/AwtXbrzTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This module, both source code and documentation,
3 | * is in the Public Domain, and comes with NO WARRANTY.
4 | */
5 | package io.github.stanio.xbrz.awt;
6 |
7 | import static org.junit.Assert.assertEquals;
8 | import static org.junit.Assert.assertTrue;
9 |
10 | import java.awt.Image;
11 | import java.awt.image.BufferedImage;
12 | import java.awt.image.PixelGrabber;
13 | import java.io.IOException;
14 | import java.util.ArrayList;
15 | import java.util.Collections;
16 | import java.util.List;
17 | import javax.imageio.ImageIO;
18 |
19 | import org.junit.Test;
20 |
21 | public class AwtXbrzTest extends AbstractAwtXbrzTest {
22 |
23 | private void assertEqualPixels(Image actual, String expected) throws IOException {
24 | assertTrue("result not a BufferedImage", actual instanceof BufferedImage);
25 | assertEqualPixels((BufferedImage) actual, expected);
26 | }
27 |
28 | @Test
29 | public void toolkitSourceWithoutAlpha() throws Exception {
30 | Image source = toolkit().createImage(resource("gbamockup-indexcolor.png"));
31 |
32 | Image scaled = AwtXbrz.scaleImage(source, 3);
33 |
34 | assertEqualPixels(scaled, "gbamockup@3xbrz.png");
35 | }
36 |
37 | @Test
38 | public void toolkitSourceWithAlpha() throws Exception {
39 | Image source = toolkit().createImage(resource("open-folder.png"));
40 |
41 | Image scaled = AwtXbrz.scaleImage(source, 3);
42 |
43 | assertEqualPixels(scaled, "open-folder@3xbrz.png");
44 | }
45 |
46 | @Test
47 | public void bufferedSourceWithoutAlpha() throws Exception {
48 | Image source = ImageIO.read(resource("gbamockup-indexcolor.png"));
49 |
50 | Image scaled = AwtXbrz.scaleImage(source, 3);
51 |
52 | assertEqualPixels(scaled, "gbamockup@3xbrz.png");
53 | }
54 |
55 | @Test
56 | public void bufferedSourceWithAlpha() throws Exception {
57 | Image source = ImageIO.read(resource("open-folder.png"));
58 |
59 | Image scaled = AwtXbrz.scaleImage(source, 3);
60 |
61 | assertEqualPixels(scaled, "open-folder@3xbrz.png");
62 | }
63 |
64 | @Test
65 | public void nearestResolutionVariant() throws Exception {
66 | BufferedImage source = ImageIO.read(resource("open-folder.png"));
67 | int targetWidth = Math.round(source.getWidth() * 2.5f);
68 | int targetHeight = Math.round(source.getHeight() * 2.5f);
69 |
70 | Image scaled = AwtXbrz.scaleImage(source, targetWidth, targetHeight);
71 |
72 | //assertEqualPixels(scaled, "open-folder@3xbrz.png");
73 | assertEquals("scaled.width", targetWidth, scaled.getWidth(null));
74 | assertEquals("scaled.height", targetHeight, scaled.getHeight(null));
75 | }
76 |
77 | @Test
78 | public void animatedSource() throws Exception {
79 | Image source = toolkit().createImage(resource("loading.gif"));
80 |
81 | Image scaled = AwtXbrz.scaleImage(source, 3);
82 |
83 | List frames = captureFrames(scaled);
84 | for (int i = 0; i < frames.size(); i++) {
85 | assertEqualPixels("animatedSource-frame" + (i + 1), frames.get(i), "loading-frame" + (i + 1) + ".png");
86 | }
87 | }
88 |
89 | private static List captureFrames(Image scaled) throws InterruptedException {
90 | List frames = Collections.synchronizedList(new ArrayList<>());
91 | PixelGrabber grabber = new PixelGrabber(scaled, 0, 0, -1, -1, true) {
92 | @Override
93 | public synchronized void imageComplete(int status) {
94 | if (status == SINGLEFRAMEDONE) {
95 | BufferedImage aframe = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
96 | aframe.setRGB(0, 0, aframe.getWidth(), aframe.getHeight(), (int[]) getPixels(), 0, aframe.getWidth());
97 | frames.add(aframe);
98 | if (frames.size() < 9) {
99 | return;
100 | }
101 | }
102 | super.imageComplete(status);
103 | }
104 | };
105 | if (!grabber.grabPixels(10_000L)) {
106 | throw new IllegalStateException("status: " + grabber.status());
107 | } else if (frames.size() < 9) {
108 | throw new IllegalStateException("frame count < 9: " + frames.size());
109 | }
110 | return frames;
111 | }
112 |
113 | }
114 |
--------------------------------------------------------------------------------
/xbrz-awt/src/test/java/io/github/stanio/xbrz/awt/ImageDataTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This module, both source code and documentation,
3 | * is in the Public Domain, and comes with NO WARRANTY.
4 | */
5 | package io.github.stanio.xbrz.awt;
6 |
7 | import static org.junit.Assert.assertEquals;
8 |
9 | import java.awt.Image;
10 | import javax.imageio.ImageIO;
11 |
12 | import org.junit.Test;
13 |
14 | public class ImageDataTest extends AbstractAwtXbrzTest {
15 |
16 | @Test
17 | public void toolkitRGBSourceWithoutAlpha() {
18 | Image source = toolkit().createImage(resource("gbamockup-truecolor.png"));
19 |
20 | ImageData sourceData = ImageData.get(source);
21 |
22 | assertEquals("ImageData.hasAlpha", false, sourceData.hasAlpha);
23 | }
24 |
25 | @Test
26 | public void toolkitIndexedSourceWithoutAlpha() {
27 | Image source = toolkit().createImage(resource("gbamockup-indexcolor.png"));
28 |
29 | ImageData sourceData = ImageData.get(source);
30 |
31 | assertEquals("ImageData.hasAlpha", false, sourceData.hasAlpha);
32 | }
33 |
34 | @Test
35 | public void toolkitSourceWithAlpha() {
36 | Image source = toolkit().createImage(resource("open-folder.png"));
37 |
38 | ImageData sourceData = ImageData.get(source);
39 |
40 | assertEquals("ImageData.hasAlpha", true, sourceData.hasAlpha);
41 | }
42 |
43 | @Test
44 | public void bufferedSourceWithoutAlpha() throws Exception {
45 | Image source = ImageIO.read(resource("gbamockup-truecolor.png"));
46 |
47 | ImageData sourceData = ImageData.get(source);
48 |
49 | assertEquals("ImageData.hasAlpha", false, sourceData.hasAlpha);
50 | }
51 |
52 | @Test
53 | public void bufferedSourceWithAlpha() throws Exception {
54 | Image source = ImageIO.read(resource("open-folder.png"));
55 |
56 | ImageData sourceData = ImageData.get(source);
57 |
58 | assertEquals("ImageData.hasAlpha", true, sourceData.hasAlpha);
59 | }
60 |
61 | @Test
62 | public void animatedSource() {
63 | Image source = toolkit().createImage(resource("loading.gif"));
64 |
65 | ImageData sourceData = ImageData.get(source);
66 |
67 | assertEquals("ImageData.isAnimated", true, sourceData.isAnimated());
68 | }
69 |
70 | @Test
71 | public void nonAnimatedSource() {
72 | Image source = toolkit().createImage(resource("open-folder.png"));
73 |
74 | ImageData sourceData = ImageData.get(source);
75 |
76 | assertEquals("ImageData.isAnimated", false, sourceData.isAnimated());
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/xbrz-awt/src/test/java/io/github/stanio/xbrz/awt/XbrzImageTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This module, both source code and documentation,
3 | * is in the Public Domain, and comes with NO WARRANTY.
4 | */
5 | package io.github.stanio.xbrz.awt;
6 |
7 | import static org.junit.Assert.*;
8 |
9 | import java.awt.Image;
10 |
11 | import javax.swing.ImageIcon;
12 |
13 | import org.junit.Test;
14 |
15 | public class XbrzImageTest {
16 |
17 | @Test
18 | public void mrImageVariant() throws Exception {
19 | Image image = loadImage("demo/editbookmarks.png");
20 |
21 | Image scaled = XbrzImage.mrImage(image).getResolutionVariant(32, 48);
22 |
23 | assertEquals("scaled.width", 32, scaled.getWidth(null));
24 | assertEquals("scaled.height", 48, scaled.getHeight(null));
25 | }
26 |
27 | private static Image loadImage(String name) {
28 | return new ImageIcon(XbrzImageTest.class.getResource(name)).getImage();
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/xbrz-awt/src/test/java/io/github/stanio/xbrz/awt/XbrzOpTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This module, both source code and documentation,
3 | * is in the Public Domain, and comes with NO WARRANTY.
4 | */
5 | package io.github.stanio.xbrz.awt;
6 |
7 | import java.awt.image.BufferedImage;
8 | import java.awt.image.ColorModel;
9 | import java.awt.image.WritableRaster;
10 | import javax.imageio.ImageIO;
11 |
12 | import org.junit.Before;
13 | import org.junit.Test;
14 |
15 | public class XbrzOpTest extends AbstractAwtXbrzTest {
16 |
17 | private XbrzOp xbrzOp;
18 |
19 | @Before
20 | public void setUp() {
21 | xbrzOp = new XbrzOp(6);
22 | }
23 |
24 | @Test
25 | public void indexColorDestination() throws Exception {
26 | // Given
27 | BufferedImage source = ImageIO.read(resource("gbamockup-indexcolor.png"));
28 |
29 | ColorModel indexModel = source.getColorModel();
30 | WritableRaster indexRaster = indexModel.createCompatibleWritableRaster(source.getWidth() * 3, source.getHeight() * 3);
31 | BufferedImage result = new BufferedImage(indexModel, indexRaster, false, null);
32 |
33 | // When
34 | xbrzOp.filter(source, result);
35 |
36 | // Then
37 | assertEqualPixels(result, "gbamockup-indexcolor-part@6xbrz.png");
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/xbrz-awt/src/test/java/io/github/stanio/xbrz/awt/demo/AnimDemo.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This module, both source code and documentation,
3 | * is in the Public Domain, and comes with NO WARRANTY.
4 | */
5 | package io.github.stanio.xbrz.awt.demo;
6 |
7 | import java.awt.Dimension;
8 | import java.awt.Graphics;
9 | import java.awt.Graphics2D;
10 | import java.awt.Image;
11 | import java.awt.Insets;
12 | import java.awt.RenderingHints;
13 | import java.awt.Toolkit;
14 | import java.awt.event.ActionEvent;
15 | import java.awt.event.KeyEvent;
16 | import java.awt.event.WindowEvent;
17 |
18 | import javax.swing.AbstractAction;
19 | import javax.swing.ImageIcon;
20 | import javax.swing.JComponent;
21 | import javax.swing.JFrame;
22 | import javax.swing.KeyStroke;
23 | import javax.swing.SwingUtilities;
24 |
25 | import io.github.stanio.xbrz.awt.XbrzImage;
26 |
27 | @SuppressWarnings("serial")
28 | public class AnimDemo extends JFrame {
29 |
30 | public AnimDemo() {
31 | this("kirby-2.gif");
32 | }
33 |
34 | public AnimDemo(String animName) {
35 | super("Xbrz Animation");
36 | super.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
37 | super.getRootPane().getActionMap().put("exit", new AbstractAction() {
38 | @Override public void actionPerformed(ActionEvent event) {
39 | dispatchEvent(new WindowEvent(AnimDemo.this, WindowEvent.WINDOW_CLOSING));
40 | dispose();
41 | }
42 | });
43 | super.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
44 | .put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false), "exit");
45 | initUI(animName);
46 | }
47 |
48 | private static Image loadImage(String name) {
49 | return new ImageIcon(Toolkit.getDefaultToolkit()
50 | .createImage(AnimDemo.class.getResource(name))).getImage();
51 | }
52 |
53 | private void initUI(String imageName) {
54 | Image baseImage = loadImage(imageName);
55 | super.add(dynamicCanvas(XbrzImage.mrImage(baseImage), true));
56 | }
57 |
58 | private static JComponent dynamicCanvas(Image image, boolean smooth) {
59 | return new JComponent() {
60 | private final Insets tmpInsets = new Insets(0, 0, 0, 0);
61 | private final int baseWidth = image.getWidth(null);
62 | private final int baseHeight = image.getHeight(null);
63 | {
64 | setPreferredSize(new Dimension(baseWidth, baseHeight));
65 | }
66 |
67 | @Override
68 | public void paint(Graphics g) {
69 | Insets insets = getInsets(tmpInsets);
70 | int availableWidth = getWidth() - insets.left - insets.right;
71 | int availableHeight = getHeight() - insets.top - insets.bottom;
72 | if (availableWidth <= 0 || availableHeight <= 0) {
73 | return;
74 | }
75 |
76 | Graphics2D g2 = null;
77 | if (g instanceof Graphics2D && smooth) {
78 | g2 = (Graphics2D) g.create();
79 | g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
80 | RenderingHints.VALUE_INTERPOLATION_BILINEAR);
81 | g = g2;
82 | }
83 |
84 | double scaleWidth = (double) availableWidth / baseWidth;
85 | double scaleHeight = (double) availableHeight / baseHeight;
86 | int targetWidth, targetHeight;
87 | if (scaleWidth < scaleHeight) {
88 | targetWidth = availableWidth;
89 | targetHeight = (int) Math.round(baseHeight * scaleWidth);
90 | } else {
91 | targetWidth = (int) Math.round(baseWidth * scaleHeight);
92 | targetHeight = availableHeight;
93 | }
94 |
95 | int x = (availableWidth - targetWidth) / 2 + insets.left;
96 | int y = (availableHeight - targetHeight) / 2 + insets.top;
97 | g.drawImage(image, x, y, targetWidth, targetHeight, this);
98 | //g.drawImage(mrImage, x, y, x + targetWidth, y + targetHeight,
99 | // 0, 0, baseWidth, baseHeight, this);
100 |
101 | if (g2 != null) {
102 | g2.dispose();
103 | }
104 | }
105 | };
106 | }
107 |
108 | public static void main(String[] args) {
109 | // kirby-1.gif
110 | // kirby-2.gif
111 | // horizon-1.gif
112 | // sbreng-1.gif
113 | final String animName = (args.length == 1) ? args[0] : "kirby-1.gif";
114 | SwingUtilities.invokeLater(() -> {
115 | try {
116 | javax.swing.UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
117 | } catch (Exception e) {
118 | System.err.println(e);
119 | }
120 | AnimDemo frame = new AnimDemo(animName);
121 | frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
122 | frame.pack();
123 | frame.setLocationRelativeTo(null);
124 | frame.setVisible(true);
125 | });
126 | }
127 |
128 | }
129 |
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/demo/editbookmarks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/demo/editbookmarks.png
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/demo/editbookmarks2-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/demo/editbookmarks2-16.png
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/demo/editbookmarks2-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/demo/editbookmarks2-32.png
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/demo/horizon-1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/demo/horizon-1.gif
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/demo/kirby-1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/demo/kirby-1.gif
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/demo/kirby-2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/demo/kirby-2.gif
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/demo/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/demo/loading.gif
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/demo/sbreng-1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/demo/sbreng-1.gif
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/demo/write_obj-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/demo/write_obj-16.png
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/demo/write_obj-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/demo/write_obj-32.png
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/gbamockup-indexcolor-part@6xbrz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/gbamockup-indexcolor-part@6xbrz.png
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/gbamockup-indexcolor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/gbamockup-indexcolor.png
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/gbamockup-truecolor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/gbamockup-truecolor.png
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/gbamockup@3xbrz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/gbamockup@3xbrz.png
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/loading-frame1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/loading-frame1.png
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/loading-frame2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/loading-frame2.png
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/loading-frame3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/loading-frame3.png
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/loading-frame4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/loading-frame4.png
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/loading-frame5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/loading-frame5.png
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/loading-frame6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/loading-frame6.png
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/loading-frame7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/loading-frame7.png
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/loading-frame8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/loading-frame8.png
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/loading-frame9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/loading-frame9.png
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/loading.gif
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/open-folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/open-folder.png
--------------------------------------------------------------------------------
/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/open-folder@3xbrz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-awt/src/test/resources/io/github/stanio/xbrz/awt/images/open-folder@3xbrz.png
--------------------------------------------------------------------------------
/xbrz-core/LICENSE:
--------------------------------------------------------------------------------
1 | xBRZ project is distributed under
2 | GNU General Public License: https://www.gnu.org/licenses/gpl-3.0
3 | Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved
4 |
5 | Additionally and as a special exception, the author gives permission
6 | to link the code of this program with the following libraries
7 | (or with modified versions that use the same licenses), and distribute
8 | linked combinations including the two: MAME, FreeFileSync, Snes9x, ePSXe
9 | You must obey the GNU General Public License in all respects for all of
10 | the code used other than MAME, FreeFileSync, Snes9x, ePSXe.
11 | If you modify this file, you may extend this exception to your version
12 | of the file, but you are not obligated to do so. If you do not wish to
13 | do so, delete this exception statement from your version.
14 |
15 | Java port of xBRZ 1.8 by Stanio (stanio AT yahoo DOT com)
16 |
17 | As a special exception the author of this port gives you
18 | permission to link this library with independent modules to produce an
19 | executable, regardless of the license terms of these independent modules,
20 | and to copy and distribute the resulting executable under terms of your
21 | choice, provided that you also meet, for each linked independent module,
22 | the terms and conditions of the license of that module. An independent
23 | module is a module which is not derived from or based on this library.
24 | If you modify this library, you may extend this exception to your version
25 | of the library, but you are not obliged to do so. If you do not wish to
26 | do so, delete this exception statement from your version.
27 |
--------------------------------------------------------------------------------
/xbrz-core/README.md:
--------------------------------------------------------------------------------
1 | # xBRZ for Java Core Library
2 |
3 | [](https://central.sonatype.com/artifact/io.github.stanio/xbrz-core)
4 |
5 | Self-contained (no dependencies). For using with Java AWT images one may consider [xbrz-awt](../xbrz-awt).
6 |
7 | JPMS name: `io.github.stanio.xbrz.core` (Java 8 compatible Multi-Release JAR)
8 |
9 | ## License
10 |
11 | This module is distributed under the GNU General Public License v3, with the
12 | [Classpath Exception](https://en.wikipedia.org/wiki/GPL_linking_exception#The_Classpath_exception).
13 | See [LICENSE](LICENSE).
14 |
15 | ## API
16 |
17 | Example using `java.awt.image.BufferedImage`:
18 |
19 | import io.github.stanio.xbrz.Xbrz;
20 | import java.awt.image.BufferedImage;
21 |
22 | BufferedImage source = ...;
23 | int srcWidth = source.getWidth();
24 | int srcHeight = source.getHeight();
25 | int[] srcPixels = source.getRGB(0, 0, srcWidth, srcHeight, null, 0, srcWidth);
26 |
27 | int factor = 2;
28 | int destWidth = srcWidth * factor;
29 | int destHeight = srcHeight * factor;
30 | boolean hasAlpha = source.getColorModel().hasAlpha();
31 | int[] destPixels = Xbrz.scaleImage(factor, hasAlpha, srcPixels, null, srcWidth, srcHeight);
32 |
33 | BufferedImage scaled = new BufferedImage(destWidth, destHeight,
34 | hasAlpha ? BufferedImage.TYPE_INT_ARGB
35 | : BufferedImage.TYPE_INT_RGB);
36 | scaled.setRGB(0, 0, destWidth, destHeight, destPixels, 0, destWidth);
37 |
38 | One may reuse preconfigured `Xbrz` instance for multiple scale operations:
39 |
40 | int factor = 3;
41 | Xbrz xbrz = new Xbrz(factor);
42 | xbrz.scaleImage(src, trg, srcWidth, srcHeight);
43 |
44 | The slowest part of the scaling currently is the calculation of the default `ColorDistance`. If more speed (over quality) is required, one may configure
45 | the `Xbrz` instance like:
46 |
47 | Xbrz xbrz = new Xbrz(factor, withAlpha, new ScalerCfg(),
48 | ColorDistance.bufferedYCbCr(5));
49 |
50 | or provide his/her own implementation:
51 |
52 | Xbrz xbrz = new Xbrz(factor, withAlpha, new ScalerCfg(),
53 | (pix1, pix2) -> Math.abs(pix1 - pix2));
54 |
55 | Note:
56 |
57 | - `ColorDistance.bufferedYCbCr(5)` allocates 128 KB lookup buffer
58 | - `ColorDistance.bufferedYCbCr(8)` allocates 64 MB lookup buffer
59 |
--------------------------------------------------------------------------------
/xbrz-core/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 | 4.0.0
7 |
8 |
9 | io.github.stanio
10 | xbrz-java
11 | 1.8.3-SNAPSHOT
12 |
13 | xbrz-core
14 |
15 | xBRZ for Java Core Library
16 | xBRZ: "Scale by rules" - high quality image upscaling filter by Zenju,
17 | Java port by Stanio
18 |
19 |
20 | GPL-3.0-only WITH Classpath-exception-2.0
21 | https://spdx.org/licenses/GPL-3.0-only
22 | https://spdx.org/licenses/Classpath-exception-2.0.html
23 |
24 |
25 |
26 |
27 | io.github.stanio.xbrz.core
28 | false
29 | false
30 | false
31 |
32 |
33 |
34 |
35 |
36 | META-INF
37 | ${basedir}
38 |
39 | LICENSE
40 |
41 |
42 |
43 |
44 |
45 | maven-jar-plugin
46 |
47 |
48 |
49 | xBRZ: "Scale by rules" by Zenju
50 | 1.8
51 | true
52 |
53 |
54 |
55 |
56 |
57 | maven-javadoc-plugin
58 |
59 | Copyleft {inceptionYear}, {currentYear}
60 |
61 |
62 |
63 | org.sonatype.central
64 | central-publishing-maven-plugin
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/xbrz-core/src/main/java/io/github/stanio/xbrz/Color.java:
--------------------------------------------------------------------------------
1 | package io.github.stanio.xbrz;
2 |
3 | class Color {
4 |
5 | static int getAlpha(int pix) { return (pix >> 24) & 0xFF; }
6 | static int getRed (int pix) { return (pix >> 16) & 0xFF; }
7 | static int getGreen(int pix) { return (pix >> 8) & 0xFF; }
8 | static int getBlue (int pix) { return (pix >> 0) & 0xFF; }
9 |
10 | static int makePixel(int a, int r, int g, int b) { return (a << 24) | (r << 16) | (g << 8) | b; }
11 | static int makePixel( int r, int g, int b) { return (0xFF << 24) | (r << 16) | (g << 8) | b; }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/xbrz-core/src/main/java/io/github/stanio/xbrz/OutputMatrix.java:
--------------------------------------------------------------------------------
1 | package io.github.stanio.xbrz;
2 |
3 | import static io.github.stanio.xbrz.MatrixRotation.HALF_BYTE;
4 | import static io.github.stanio.xbrz.RotationDegree.*;
5 |
6 | import java.util.concurrent.ConcurrentHashMap;
7 | import java.util.concurrent.ConcurrentMap;
8 |
9 | //access matrix area, top-left at current position
10 | final class OutputMatrix {
11 |
12 | private int N;
13 | private int[] out;
14 | private int outWidth;
15 |
16 | private int offset;
17 | private RotationDegree rotDeg = ROT_0;
18 | private MatrixRotation rot;
19 |
20 | private OutputMatrix() {}
21 |
22 | private static final ThreadLocal instance = new ThreadLocal<>();
23 |
24 | static OutputMatrix instance(int N, int[] out, int outWidth) {
25 | OutputMatrix matrix = instance.get();
26 | if (matrix == null) {
27 | matrix = new OutputMatrix();
28 | instance.set(matrix);
29 | }
30 | matrix.N = N;
31 | matrix.out = out;
32 | matrix.outWidth = outWidth;
33 | matrix.rot = MatrixRotation.of(N);
34 | return matrix;
35 | }
36 |
37 | final void positionY(int y) {
38 | offset = N * y * outWidth;
39 | }
40 |
41 | final void incrementX() {
42 | offset += N;
43 | }
44 |
45 | final void rotDeg(RotationDegree deg) {
46 | this.rotDeg = deg;
47 | }
48 |
49 | private final int position(final int I, final int J) {
50 | final byte IJ_old = rot.calc(rotDeg, I, J);
51 | final int I_old = IJ_old >> HALF_BYTE & 0xF;
52 | final int J_old = IJ_old & 0xF;
53 | return offset + J_old + I_old * outWidth;
54 | }
55 |
56 | final void set(int I, int J, int val) {
57 | out[position(I, J)] = val;
58 | }
59 |
60 | final void set(int I, int J, IntFunction func) {
61 | final int pos = position(I, J);
62 | out[pos] = func.apply(out[pos]);
63 | }
64 |
65 | //fill block of size scale * scale with the given color
66 | final void fillBlock(int col) {
67 | fillBlock(col, N, N);
68 | }
69 |
70 | final void fillBlock(int col, int blockWidth, int blockHeight) {
71 | for (int y = 0, trg = y * outWidth + offset; y < blockHeight; ++y, trg += outWidth)
72 | for (int x = 0; x < blockWidth; ++x)
73 | out[trg + x] = col;
74 | }
75 |
76 |
77 | @FunctionalInterface interface IntFunction {
78 | int apply(int a);
79 | }
80 |
81 |
82 | }
83 |
84 |
85 | final class MatrixRotation {
86 |
87 | static final int HALF_BYTE = Byte.SIZE / 2;
88 |
89 | private final int N;
90 | private final int Nsq;
91 | private final byte[] lookup;
92 |
93 | private MatrixRotation(int N) {
94 | this.N = N;
95 | this.Nsq = N * N;
96 | if (N <= 0 || N >= 16) {
97 | throw new IllegalArgumentException("N should be > 0 and < 16");
98 | }
99 |
100 | byte[] lookup = new byte[4 * Nsq];
101 | for (int rotDeg = 0; rotDeg < 4; rotDeg++) {
102 | int offset = rotDeg * Nsq;
103 | for (int I = 0; I < N; I++) {
104 | for (int J = 0; J < N; J++) {
105 | lookup[offset + I * N + J] =
106 | calc(rotDeg, (byte) ((I << HALF_BYTE) | J));
107 | }
108 | }
109 | }
110 | this.lookup = lookup;
111 | }
112 |
113 | private static final
114 | ConcurrentMap instance = new ConcurrentHashMap<>();
115 |
116 | static MatrixRotation of(int N) {
117 | return instance.computeIfAbsent(N, MatrixRotation::new);
118 | }
119 |
120 | private final byte calc(int rotDeg, byte IJ) {
121 | if (rotDeg == 0) {
122 | return IJ;
123 | }
124 | byte IJ_old = calc(rotDeg - 1, IJ);
125 | int J_old = IJ_old & 0xF;
126 | int I_old = IJ_old >> HALF_BYTE & 0xF;
127 |
128 | int rot_I = N - 1 - J_old;
129 | int rot_J = I_old;
130 | return (byte) (rot_I << HALF_BYTE | rot_J);
131 | }
132 |
133 | final byte calc(RotationDegree rotDeg, int I, int J) {
134 | final int offset = rotDeg.ordinal() * Nsq;
135 | return lookup[offset + I * N + J];
136 | }
137 |
138 | }
139 |
--------------------------------------------------------------------------------
/xbrz-core/src/main/java/io/github/stanio/xbrz/RotationDegree.java:
--------------------------------------------------------------------------------
1 | package io.github.stanio.xbrz;
2 |
3 | enum RotationDegree { //clock-wise
4 | ROT_0,
5 | ROT_90,
6 | ROT_180,
7 | ROT_270
8 | }
9 |
--------------------------------------------------------------------------------
/xbrz-core/src/main/java9/module-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This module, both source code and documentation,
3 | * is in the Public Domain, and comes with NO WARRANTY.
4 | */
5 |
6 | /**
7 | * Provides a Java implementation of the xBRZ algorithm ("Scale by rules" –
8 | * high quality image upscaling filter by Zenju).
9 | */
10 | module io.github.stanio.xbrz.core {
11 |
12 | exports io.github.stanio.xbrz;
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/xbrz-core/src/test/java/io/github/stanio/xbrz/AbstractScalerTest.java:
--------------------------------------------------------------------------------
1 | package io.github.stanio.xbrz;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertTrue;
5 |
6 | import java.awt.image.BufferedImage;
7 | import java.io.IOException;
8 |
9 | import javax.imageio.ImageIO;
10 |
11 | import org.junit.Rule;
12 | import org.junit.Test;
13 | import org.junit.rules.TestName;
14 |
15 | import io.github.stanio.xbrz.Xbrz.ScalerCfg;
16 |
17 | public abstract class AbstractScalerTest {
18 |
19 | private static class BufferedYCbCr {
20 | static ColorDistance colorDistance = ColorDistance.bufferedYCbCr(5);
21 | }
22 |
23 | @Rule
24 | public TestName testName = new TestName();
25 |
26 | protected abstract Xbrz xbrz();
27 |
28 | @Test
29 | public void basicShapes() throws Exception {
30 | testImage("test/basic-shapes");
31 | }
32 |
33 | @Test
34 | public void fullPicture() throws Exception {
35 | // Reference images generated by the original ScalerTest tool
36 | // appear to differ slightly - likely the YCbCr color distance
37 | // calculation varies between Java and C++.
38 | //testImage("test/gbamockup", 1.0);
39 | testImage(new Xbrz(xbrz().scale(), false), "test/gbamockup", 0.001);
40 | }
41 |
42 | @Test
43 | public void someAlpha() throws Exception {
44 | testImage("test/down-arrow");
45 | }
46 |
47 | @Test
48 | public void alphaAtImageBoundary() throws Exception {
49 | testImage("test/open-folder");
50 | }
51 |
52 | @Test
53 | public void colorDistanceRGB() throws Exception {
54 | // Expected result differences around some edges.
55 | testImage(new Xbrz(xbrz().scale(), false,
56 | new ScalerCfg(), ColorDistance.rgb()), "test/gbamockup", 3.0);
57 | }
58 |
59 | @Test
60 | public void colorDistanceYCbCrBuffered() throws Exception {
61 | // Expected result differences around some edges.
62 | testImage(new Xbrz(xbrz().scale(), false,
63 | new ScalerCfg(), BufferedYCbCr.colorDistance), "test/gbamockup", 3.0);
64 | }
65 |
66 | @Test
67 | public void alhpaNoAlpha() throws Exception {
68 | BufferedImage source = ImageIO.read(AbstractScalerTest.class.getResource("test/gbamockup.png"));
69 | int srcWidth = source.getWidth();
70 | int srcHeight = source.getHeight();
71 | int[] srcPixels = new int[srcWidth * srcHeight];
72 | source.getRGB(0, 0, srcWidth, srcHeight, srcPixels, 0, srcWidth);
73 |
74 | int factor = xbrz().scale();
75 | int destWidth = srcWidth * factor;
76 | int destHeight = srcHeight * factor;
77 | int[] destPixels = new int[destWidth * destHeight];
78 | new Xbrz(factor, true).scaleImage(srcPixels, destPixels, srcWidth, srcHeight);
79 |
80 | int[] dest2Pixels = new int[destWidth * destHeight];
81 | new Xbrz(factor, false).scaleImage(srcPixels, dest2Pixels, srcWidth, srcHeight);
82 |
83 | // Differences on image borders expected.
84 | assertPixels(testName.getMethodName()
85 | + "-" + factor + "x", destPixels, dest2Pixels, 1.0);
86 | }
87 |
88 | private void testImage(String name) throws IOException {
89 | testImage(name, 0.0001);
90 | }
91 |
92 | private void testImage(String name, double deviation) throws IOException {
93 | testImage(xbrz(), name, deviation);
94 | }
95 |
96 | private void testImage(Xbrz xbrz, String imageName, double deviation) throws IOException {
97 | final int factor = xbrz.scale();
98 |
99 | BufferedImage source = ImageIO.read(AbstractScalerTest.class.getResource(imageName + ".png"));
100 | int srcWidth = source.getWidth();
101 | int srcHeight = source.getHeight();
102 | int[] srcPixels = new int[srcWidth * srcHeight];
103 | source.getRGB(0, 0, srcWidth, srcHeight, srcPixels, 0, srcWidth);
104 |
105 | int destWidth = srcWidth * factor;
106 | int destHeight = srcHeight * factor;
107 | int[] destPixels = new int[destWidth * destHeight];
108 | xbrz.scaleImage(srcPixels, destPixels, srcWidth, srcHeight);
109 |
110 | BufferedImage reference = ImageIO.read(AbstractScalerTest.class.getResource(imageName + "@" + factor + "xbrz.png"));
111 | int[] refPixels = new int[reference.getWidth() * reference.getHeight()];
112 | reference.getRGB(0, 0, reference.getWidth(), reference.getHeight(), refPixels, 0, reference.getWidth());
113 | assertPixels(testName.getMethodName()
114 | + "-" + factor + "x", destPixels, refPixels, deviation);
115 | }
116 |
117 | private static void assertPixels(String name, int[] destPixels, int[] refPixels, double deviation) {
118 | assertEquals("pixels size", refPixels.length, destPixels.length);
119 | int mismatch = 0;
120 | for (int i = 0, len = refPixels.length; i < len; i++) {
121 | if (destPixels[i] != refPixels[i]) {
122 | mismatch += 1;
123 | }
124 | }
125 | double percent = mismatch * 100.0 / destPixels.length;
126 | String message = String.format("Pixel mismatch: %d (%.3f%%)", mismatch, percent);
127 | System.out.printf("%s [%s]%n", message, name);
128 | assertTrue(message, percent <= deviation);
129 | }
130 |
131 | }
132 |
--------------------------------------------------------------------------------
/xbrz-core/src/test/java/io/github/stanio/xbrz/ColorDistanceBufferedTest.java:
--------------------------------------------------------------------------------
1 | package io.github.stanio.xbrz;
2 |
3 | import org.junit.BeforeClass;
4 | import org.junit.runners.Parameterized.Parameters;
5 |
6 | public class ColorDistanceBufferedTest extends ColorDistanceTest {
7 |
8 | private static Double defaultDelta = 8.0; // full 8 bits - 5 bits = 3 bits
9 |
10 | static ColorDistance colorDistance;
11 |
12 | @BeforeClass
13 | public static void setUpSuite() {
14 | colorDistance = new ColorDistanceYCbCrBuffered(5);
15 | }
16 |
17 | @Parameters(name = "{index}: {0} - {1}")
18 | public static Object[][] data() {
19 | Object[][] params = ColorDistanceTest.data();
20 | for (Object[] row : params) {
21 | row[3] = defaultDelta;
22 | }
23 | return params;
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/xbrz-core/src/test/java/io/github/stanio/xbrz/ColorDistanceTest.java:
--------------------------------------------------------------------------------
1 | package io.github.stanio.xbrz;
2 |
3 | import static org.hamcrest.MatcherAssert.assertThat;
4 | import static org.hamcrest.Matchers.closeTo;
5 |
6 | import java.awt.Color;
7 |
8 | import org.junit.BeforeClass;
9 | import org.junit.Test;
10 | import org.junit.runner.RunWith;
11 | import org.junit.runners.Parameterized;
12 | import org.junit.runners.Parameterized.Parameter;
13 | import org.junit.runners.Parameterized.Parameters;
14 |
15 | @RunWith(Parameterized.class)
16 | public class ColorDistanceTest {
17 |
18 | static final Double defaultDelta = 0.000005;
19 |
20 | static ColorDistance colorDistance;
21 |
22 | @Parameter(0)
23 | public String pix1;
24 |
25 | @Parameter(1)
26 | public String pix2;
27 |
28 | @Parameter(2)
29 | public double expectedDistance;
30 |
31 | @Parameter(3)
32 | public double floatDelta;
33 |
34 | @BeforeClass
35 | public static void setUpSuite() {
36 | colorDistance = new ColorDistanceYCbCr(1);
37 | }
38 |
39 | @Parameters(name = "{index}: {0} - {1}")
40 | public static Object[][] data() {
41 | return new Object[][] {
42 | { "#000000", "#000000", 0.0, defaultDelta },
43 | { "#000000", "#404040", 64.0, defaultDelta },
44 | { "#000000", "#808080", 128.0, defaultDelta },
45 | { "#000000", "#C0C0C0", 192.0, defaultDelta },
46 | { "#000000", "#FFFFFF", 255.0, defaultDelta },
47 | { "#403050", "#000000", 56.226890, defaultDelta },
48 | { "#403050", "#404040", 18.236254, defaultDelta },
49 | { "#403050", "#808080", 75.469587, defaultDelta },
50 | { "#403050", "#C0B0D0", 128.0, defaultDelta },
51 | { "#403050", "#FFFFFF", 201.482146, defaultDelta },
52 | { "#808080", "#000000", 128.0, defaultDelta },
53 | { "#808080", "#404040", 64.0, defaultDelta },
54 | { "#808080", "#808080", 0.0, defaultDelta },
55 | { "#808080", "#C0C0C0", 64.0, defaultDelta },
56 | { "#808080", "#FFFFFF", 127.0, defaultDelta },
57 | { "#C0D0B0", "#000000", 202.479267, defaultDelta },
58 | { "#C0D0B0", "#405030", 128.0, defaultDelta },
59 | { "#C0D0B0", "#808080", 75.469587, defaultDelta },
60 | { "#C0D0B0", "#C0C0C0", 18.236254, defaultDelta },
61 | { "#C0D0B0", "#FFFFFF", 55.265375, defaultDelta },
62 | { "#FFFFFF", "#000000", 255.0, defaultDelta },
63 | { "#FFFFFF", "#404040", 191.0, defaultDelta },
64 | { "#FFFFFF", "#808080", 127.0, defaultDelta },
65 | { "#FFFFFF", "#C0C0C0", 63.0, defaultDelta },
66 | { "#FFFFFF", "#FFFFFF", 0.0, defaultDelta },
67 | };
68 | }
69 |
70 | protected ColorDistance colorDistance() {
71 | try {
72 | return (ColorDistance) getClass()
73 | .getDeclaredField("colorDistance")
74 | .get(this);
75 | } catch (ReflectiveOperationException e) {
76 | throw new IllegalStateException(e);
77 | }
78 | }
79 |
80 | @Test
81 | public void calc() {
82 | assertThat("color distance",
83 | colorDistance().calc(Color.decode(pix1).getRGB(),
84 | Color.decode(pix2).getRGB()),
85 | closeTo(expectedDistance, floatDelta));
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/xbrz-core/src/test/java/io/github/stanio/xbrz/ColorDistanceYCbCrIntegerTest.java:
--------------------------------------------------------------------------------
1 | package io.github.stanio.xbrz;
2 |
3 | import org.junit.BeforeClass;
4 | import org.junit.runners.Parameterized.Parameters;
5 |
6 | public class ColorDistanceYCbCrIntegerTest extends ColorDistanceTest {
7 |
8 | static ColorDistance colorDistance;
9 |
10 | @BeforeClass
11 | public static void setUpSuite() {
12 | colorDistance = new ColorDistanceYCbCrInteger(1);
13 | }
14 |
15 | @Parameters(name = "{index}: {0} - {1}")
16 | public static Object[][] data() {
17 | Double[] deltas = {
18 | defaultDelta,
19 | defaultDelta,
20 | defaultDelta,
21 | defaultDelta,
22 | defaultDelta,
23 | 0.014,
24 | 0.043,
25 | 0.005,
26 | defaultDelta,
27 | 0.003,
28 | defaultDelta,
29 | defaultDelta,
30 | defaultDelta,
31 | defaultDelta,
32 | defaultDelta,
33 | 0.003,
34 | defaultDelta,
35 | 0.005,
36 | 0.043,
37 | 0.012,
38 | defaultDelta,
39 | defaultDelta,
40 | defaultDelta,
41 | defaultDelta,
42 | defaultDelta
43 | };
44 |
45 | Object[][] params = ColorDistanceTest.data();
46 | for (int i = 0; i < params.length; i++) {
47 | Object[] row = params[i];
48 | row[3] = deltas[i];
49 | }
50 | return params;
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/xbrz-core/src/test/java/io/github/stanio/xbrz/Kernel_3x3Test.java:
--------------------------------------------------------------------------------
1 | package io.github.stanio.xbrz;
2 |
3 | public class Kernel_3x3Test {
4 |
5 | // TODO: ...
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/xbrz-core/src/test/java/io/github/stanio/xbrz/Kernel_4x4Test.java:
--------------------------------------------------------------------------------
1 | package io.github.stanio.xbrz;
2 |
3 | public class Kernel_4x4Test {
4 |
5 | // TODO: ...
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/xbrz-core/src/test/java/io/github/stanio/xbrz/MatrixRotationTest.java:
--------------------------------------------------------------------------------
1 | package io.github.stanio.xbrz;
2 |
3 | import static org.junit.Assert.assertEquals;
4 |
5 | import org.junit.BeforeClass;
6 | import org.junit.Test;
7 |
8 | public class MatrixRotationTest {
9 |
10 | private static final int N = 4;
11 | private static MatrixRotation m4x4;
12 |
13 | @BeforeClass
14 | public static void setUpSuite() {
15 | m4x4 = MatrixRotation.of(4);
16 | }
17 |
18 | @Test
19 | public void matrix4rotation0() throws Exception {
20 | final RotationDegree rot0 = RotationDegree.ROT_0;
21 |
22 | for (int i = 0; i < N; i++) {
23 | for (int j = 0; j < N; j++) {
24 | assertEquals(i + ", " + j,
25 | (i << 4 | j), m4x4.calc(rot0, i, j) & 0xFF);
26 | }
27 | }
28 | }
29 |
30 | @Test
31 | public void matrix4rotation90() throws Exception {
32 | final RotationDegree rot90 = RotationDegree.ROT_90;
33 | int[] expected = new int[] {
34 | 0x30, 0x20, 0x10, 0x00,
35 | 0x31, 0x21, 0x11, 0x01,
36 | 0x32, 0x22, 0x12, 0x02,
37 | 0x33, 0x23, 0x13, 0x03
38 | };
39 |
40 | for (int i = 0; i < N; i++) {
41 | for (int j = 0; j < N; j++) {
42 | assertEquals(i + ", " + j,
43 | expected[i * N + j], m4x4.calc(rot90, i, j) & 0xFF);
44 | }
45 | }
46 | }
47 |
48 | @Test
49 | public void matrix4rotation180() throws Exception {
50 | final RotationDegree rot180 = RotationDegree.ROT_180;
51 | int[] expected = new int[] {
52 | 0x33, 0x32, 0x31, 0x30,
53 | 0x23, 0x22, 0x21, 0x20,
54 | 0x13, 0x12, 0x11, 0x10,
55 | 0x03, 0x02, 0x01, 0x00
56 | };
57 |
58 | for (int i = 0; i < N; i++) {
59 | for (int j = 0; j < N; j++) {
60 | assertEquals(i + ", " + j,
61 | expected[i * N + j], m4x4.calc(rot180, i, j) & 0xFF);
62 | }
63 | }
64 | }
65 |
66 | @Test
67 | public void matrix4rotation270() throws Exception {
68 | final RotationDegree rot270 = RotationDegree.ROT_270;
69 | int[] expected = new int[] {
70 | 0x03, 0x13, 0x23, 0x33,
71 | 0x02, 0x12, 0x22, 0x32,
72 | 0x01, 0x11, 0x21, 0x31,
73 | 0x00, 0x10, 0x20, 0x30
74 | };
75 |
76 | for (int i = 0; i < N; i++) {
77 | for (int j = 0; j < N; j++) {
78 | assertEquals(i + ", " + j,
79 | expected[i * 4 + j], m4x4.calc(rot270, i, j) & 0xFF);
80 | }
81 | }
82 | }
83 |
84 | @Test
85 | public void matrix3rotation270() throws Exception {
86 | final int N = 3;
87 | MatrixRotation m3x3 = MatrixRotation.of(N);
88 | final RotationDegree rot270 = RotationDegree.ROT_270;
89 | int[] expected = new int[] {
90 | 0x2, 0x12, 0x22,
91 | 0x1, 0x11, 0x21,
92 | 0x0, 0x10, 0x20
93 | };
94 |
95 | for (int i = 0; i < N; i++) {
96 | for (int j = 0; j < N; j++) {
97 | assertEquals(i + ", " + j,
98 | expected[i * N + j], m3x3.calc(rot270, i, j) & 0xFF);
99 | }
100 | }
101 | }
102 |
103 | }
104 |
--------------------------------------------------------------------------------
/xbrz-core/src/test/java/io/github/stanio/xbrz/OutputMatrixTest.java:
--------------------------------------------------------------------------------
1 | package io.github.stanio.xbrz;
2 |
3 | public class OutputMatrixTest {
4 |
5 | // TODO: ...
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/xbrz-core/src/test/java/io/github/stanio/xbrz/Scaler2xTest.java:
--------------------------------------------------------------------------------
1 | package io.github.stanio.xbrz;
2 |
3 | import org.junit.BeforeClass;
4 |
5 | public class Scaler2xTest extends AbstractScalerTest {
6 |
7 | private static Xbrz xbrz2;
8 |
9 | @BeforeClass
10 | public static void suiteSetUp() {
11 | xbrz2 = new Xbrz(2);
12 | }
13 |
14 | @Override
15 | protected Xbrz xbrz() {
16 | return xbrz2;
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/xbrz-core/src/test/java/io/github/stanio/xbrz/Scaler3xTest.java:
--------------------------------------------------------------------------------
1 | package io.github.stanio.xbrz;
2 |
3 | import org.junit.BeforeClass;
4 |
5 | public class Scaler3xTest extends AbstractScalerTest {
6 |
7 | private static Xbrz xbrz3;
8 |
9 | @BeforeClass
10 | public static void suiteSetUp() {
11 | xbrz3 = new Xbrz(3);
12 | }
13 |
14 | @Override
15 | protected Xbrz xbrz() {
16 | return xbrz3;
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/xbrz-core/src/test/java/io/github/stanio/xbrz/Scaler4xTest.java:
--------------------------------------------------------------------------------
1 | package io.github.stanio.xbrz;
2 |
3 | import org.junit.BeforeClass;
4 |
5 | public class Scaler4xTest extends AbstractScalerTest {
6 |
7 | private static Xbrz xbrz4;
8 |
9 | @BeforeClass
10 | public static void suiteSetUp() {
11 | xbrz4 = new Xbrz(4);
12 | }
13 |
14 | @Override
15 | protected Xbrz xbrz() {
16 | return xbrz4;
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/xbrz-core/src/test/java/io/github/stanio/xbrz/Scaler5xTest.java:
--------------------------------------------------------------------------------
1 | package io.github.stanio.xbrz;
2 |
3 | import org.junit.BeforeClass;
4 |
5 | public class Scaler5xTest extends AbstractScalerTest {
6 |
7 | private static Xbrz xbrz5;
8 |
9 | @BeforeClass
10 | public static void suiteSetUp() {
11 | xbrz5 = new Xbrz(5);
12 | }
13 |
14 | @Override
15 | protected Xbrz xbrz() {
16 | return xbrz5;
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/xbrz-core/src/test/java/io/github/stanio/xbrz/Scaler6xTest.java:
--------------------------------------------------------------------------------
1 | package io.github.stanio.xbrz;
2 |
3 | import org.junit.BeforeClass;
4 |
5 | public class Scaler6xTest extends AbstractScalerTest {
6 |
7 | private static Xbrz xbrz6;
8 |
9 | @BeforeClass
10 | public static void suiteSetUp() {
11 | xbrz6 = new Xbrz(6);
12 | }
13 |
14 | @Override
15 | protected Xbrz xbrz() {
16 | return xbrz6;
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/basic-shapes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/basic-shapes.png
--------------------------------------------------------------------------------
/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/basic-shapes@2xbrz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/basic-shapes@2xbrz.png
--------------------------------------------------------------------------------
/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/basic-shapes@3xbrz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/basic-shapes@3xbrz.png
--------------------------------------------------------------------------------
/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/basic-shapes@4xbrz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/basic-shapes@4xbrz.png
--------------------------------------------------------------------------------
/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/basic-shapes@5xbrz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/basic-shapes@5xbrz.png
--------------------------------------------------------------------------------
/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/basic-shapes@6xbrz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/basic-shapes@6xbrz.png
--------------------------------------------------------------------------------
/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/down-arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/down-arrow.png
--------------------------------------------------------------------------------
/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/down-arrow@2xbrz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/down-arrow@2xbrz.png
--------------------------------------------------------------------------------
/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/down-arrow@3xbrz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/down-arrow@3xbrz.png
--------------------------------------------------------------------------------
/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/down-arrow@4xbrz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/down-arrow@4xbrz.png
--------------------------------------------------------------------------------
/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/down-arrow@5xbrz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/down-arrow@5xbrz.png
--------------------------------------------------------------------------------
/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/down-arrow@6xbrz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/down-arrow@6xbrz.png
--------------------------------------------------------------------------------
/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/gbamockup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/gbamockup.png
--------------------------------------------------------------------------------
/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/gbamockup@2xbrz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/gbamockup@2xbrz.png
--------------------------------------------------------------------------------
/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/gbamockup@3xbrz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/gbamockup@3xbrz.png
--------------------------------------------------------------------------------
/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/gbamockup@4xbrz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/gbamockup@4xbrz.png
--------------------------------------------------------------------------------
/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/gbamockup@5xbrz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/gbamockup@5xbrz.png
--------------------------------------------------------------------------------
/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/gbamockup@6xbrz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/gbamockup@6xbrz.png
--------------------------------------------------------------------------------
/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/open-folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/open-folder.png
--------------------------------------------------------------------------------
/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/open-folder@2xbrz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/open-folder@2xbrz.png
--------------------------------------------------------------------------------
/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/open-folder@3xbrz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/open-folder@3xbrz.png
--------------------------------------------------------------------------------
/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/open-folder@4xbrz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/open-folder@4xbrz.png
--------------------------------------------------------------------------------
/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/open-folder@5xbrz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/open-folder@5xbrz.png
--------------------------------------------------------------------------------
/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/open-folder@6xbrz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stanio/xbrz-java/4284e65a8d0c48fc4d65de506288df2131ed8da1/xbrz-core/src/test/resources/io/github/stanio/xbrz/test/open-folder@6xbrz.png
--------------------------------------------------------------------------------
/xbrz-tool/README.md:
--------------------------------------------------------------------------------
1 | # xBRZ Tool
2 |
3 | Command-line tool for applying xBRZ on image files.
4 |
5 | Packages both of [xbrz-core](../xbrz-core) and [xbrz-awt](../xbrz-awt). The
6 | tool itself uses [`javax.imageio.ImageIO`](https://docs.oracle.com/javase/8/docs/api/javax/imageio/ImageIO.html)
7 | for reading and writing the files.
8 |
9 | ## Command-line
10 |
11 | Usage: java -jar xbrz-tool.jar [scaling_factor]
12 |
13 | ## Making Really Executable Jar
14 |
15 | https://skife.org/java/unix/2011/06/20/really_executable_jars.html
16 |
17 | ### Linux
18 |
19 | Create `xbrz` shell script like:
20 |
21 | #!/bin/sh
22 | exec java -jar $0 "$@"
23 |
24 | Then:
25 |
26 | $ cat xbrz-tool.jar >> xbrz
27 | $ chmod +x xbrz
28 | $ ./xbrz [scaling_factor]
29 |
30 | ### Windows
31 |
32 | Create a `xbrz.cmd` batch file like:
33 |
34 | @echo off
35 | java -jar "%~f0" %*
36 | exit /b
37 |
38 | Then:
39 |
40 | > copy /b xbrz.cmd + xbrz-tool.jar xbrz.cmd
41 | > xbrz [scaling_factor]
42 |
--------------------------------------------------------------------------------
/xbrz-tool/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 | 4.0.0
7 |
8 |
9 | io.github.stanio
10 | xbrz-java
11 | 1.8.3-SNAPSHOT
12 |
13 | xbrz-tool
14 |
15 | xBRZ for Java Tool
16 |
17 |
18 | io.github.stanio.xbrz.tool
19 | io.github.stanio.xbrz.tool.ScalerTool
20 | false
21 |
22 | false
23 |
24 |
25 |
26 |
27 | ${project.groupId}
28 | xbrz-awt
29 | ${project.version}
30 |
31 |
32 |
33 |
34 | ${project.artifactId}
35 |
36 |
37 | maven-jar-plugin
38 |
39 |
40 |
41 | true
42 |
43 |
44 |
45 |
46 |
47 | org.codehaus.mojo
48 | flatten-maven-plugin
49 |
50 | fatjar
51 |
52 |
53 |
54 | maven-shade-plugin
55 | 3.6.0
56 |
57 | ${shade.skip}
58 | false
59 | ${shade.attached}
60 | fat
61 |
62 |
63 | *:*
64 |
65 | META-INF/MANIFEST.MF
66 |
67 |
68 |
69 | io.github.stanio:xbrz-core
70 |
71 | META-INF/versions/*/module-info.class
72 |
73 |
74 |
75 | io.github.stanio:xbrz-awt
76 |
77 | META-INF/versions/*/module-info.class
78 |
79 |
80 |
81 |
82 |
83 |
84 | ${app.main.class}
85 |
86 |
87 |
88 |
89 |
90 | package
91 |
92 | shade
93 |
94 |
95 |
96 |
97 |
98 | maven-javadoc-plugin
99 |
100 |
101 |
102 |
103 |
104 |
105 | apidoc
106 |
107 |
113 | true
114 |
115 |
116 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/xbrz-tool/src/main/java/io/github/stanio/xbrz/tool/ScalerTool.java:
--------------------------------------------------------------------------------
1 | package io.github.stanio.xbrz.tool;
2 |
3 | import java.awt.image.BufferedImage;
4 | import java.io.Closeable;
5 | import java.io.File;
6 | import java.io.FileInputStream;
7 | import java.io.IOException;
8 | import java.io.InputStream;
9 | import java.io.UncheckedIOException;
10 | import java.util.Iterator;
11 | import java.util.NoSuchElementException;
12 |
13 | import javax.imageio.IIOException;
14 | import javax.imageio.ImageIO;
15 | import javax.imageio.ImageReader;
16 | import javax.imageio.stream.ImageInputStream;
17 |
18 | import io.github.stanio.xbrz.awt.AwtXbrz;
19 | import io.github.stanio.xbrz.awt.ImageData;
20 |
21 | /**
22 | * Provides command-line entry point for using xBRZ.
23 | *
24 | * REVISIT:
25 | *
32 | */
33 | public class ScalerTool {
34 |
35 | public static Iterator scaleImage(File source, int factor) throws IOException {
36 | return new ScaledImageIterator(source, factor);
37 | }
38 |
39 | public static void main(String[] args) throws Exception {
40 | if (args.length == 0) {
41 | printUsage();
42 | System.exit(1);
43 | }
44 | int factor = 2;
45 | if (args.length > 1) {
46 | try {
47 | factor = Integer.parseInt(args[1]);
48 | } catch (NumberFormatException e) {
49 | System.err.println(e.toString());
50 | printUsage();
51 | System.exit(2);
52 | }
53 | }
54 |
55 | String source = args[0];
56 | String targetBase = source.replaceFirst("((? frames = scaleImage(new File(source), factor);
60 | while (frames.hasNext()) {
61 | BufferedImage current = frames.next();
62 | String target;
63 | if (index > 1 || frames.hasNext()) {
64 | target = targetBase + "-" + index + "@" + factor + "x.png";
65 | } else {
66 | target = targetBase + "@" + factor + "x.png";
67 | }
68 | ImageIO.write(current, "png", new File(target));
69 | System.out.println(target);
70 | index += 1;
71 | }
72 | }
73 |
74 | private static void printUsage() {
75 | System.err.println("Usage: xbrz [scaling_factor]");
76 | }
77 |
78 |
79 | private static class ScaledImageIterator implements Iterator {
80 |
81 | private int factor;
82 | private InputStream sourceStream;
83 | private ImageInputStream imageStream;
84 | private ImageReader reader;
85 | private int index = 0;
86 | private BufferedImage nextImage;
87 |
88 | ScaledImageIterator(File source, int factor) throws IOException {
89 | this.factor = factor;
90 | this.sourceStream = new FileInputStream(source);
91 | this.imageStream = ImageIO.createImageInputStream(sourceStream);
92 | if (imageStream == null) {
93 | throw new IIOException("Can't create an ImageInputStream!");
94 | }
95 |
96 | Iterator imageReaders = ImageIO.getImageReaders(imageStream);
97 | if (!imageReaders.hasNext()) {
98 | throw new IIOException("Unsupported image format: " + source);
99 | }
100 | this.reader = imageReaders.next();
101 | reader.setInput(imageStream, true, true);
102 | }
103 |
104 | @Override
105 | public boolean hasNext() {
106 | if (nextImage == null && reader != null) {
107 | readNext();
108 | }
109 | return (nextImage != null);
110 | }
111 |
112 | private void readNext() {
113 | try {
114 | nextImage = reader.read(index);
115 | index += 1;
116 | } catch (@SuppressWarnings("unused") IndexOutOfBoundsException e) {
117 | close();
118 | } catch (IOException e) {
119 | throw new UncheckedIOException(e);
120 | }
121 | }
122 |
123 | @Override
124 | public BufferedImage next() {
125 | if (hasNext()) {
126 | ImageData sourceData = ImageData.get(nextImage);
127 | //ImageData sourceData = new ImageData(nextImage, true);
128 | nextImage = null;
129 | return AwtXbrz.scaleImage(sourceData, factor);
130 | }
131 | throw new NoSuchElementException();
132 | }
133 |
134 | public void close() {
135 | reader.dispose();
136 | reader = null;
137 | try (Closeable is1 = sourceStream; Closeable is2 = imageStream) {
138 | // auto-close
139 | } catch (IOException ioe) {
140 | ioe.printStackTrace(System.out);
141 | }
142 | imageStream = null;
143 | sourceStream = null;
144 | }
145 | }
146 |
147 | }
148 |
--------------------------------------------------------------------------------
/xbrz-tool/src/main/java9/module-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This module, both source code and documentation,
3 | * is in the Public Domain, and comes with NO WARRANTY.
4 | */
5 |
6 | /**
7 | * Provides the command-line entry point of the (Java) xBRZ scaler tool.
8 | */
9 | module io.github.stanio.xbrz.tool {
10 |
11 | exports io.github.stanio.xbrz.tool;
12 |
13 | requires java.desktop;
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/xbrz-tool/src/main/scripts/xbrz-boot.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | java -jar "%~f0" %*
3 | exit /b
4 |
--------------------------------------------------------------------------------
/xbrz-tool/src/main/scripts/xbrz-boot.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | exec java -jar $0 "$@"
3 |
--------------------------------------------------------------------------------