├── .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 | icons-demo1 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 | icons-demo2 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 | 23 |
24 | 51 |
52 |
53 |
54 |

All Packages

55 |
56 |
Package Summary
57 |
58 |
Package
59 |
Description
60 | 61 |
 
62 | 63 |
 
64 | 65 |
 
66 | 67 |
 
68 |
69 |
70 | 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 | 23 |
24 | 51 |
52 |
53 |
54 |

xBRZ for Java 1.8.2 API

55 |
56 | 63 |
64 |
Modules
65 |
66 |
Module
67 |
Description
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 | 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 | 23 |
24 | 51 |
52 |
53 |
54 |

Uses of Class
io.github.stanio.xbrz.awt.AwtXbrz

55 |
56 | No usage of io.github.stanio.xbrz.awt.AwtXbrz
57 | 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 | 23 |
24 | 51 |
52 |
53 |
54 |

Uses of Class
io.github.stanio.xbrz.awt.XbrzFilter

55 |
56 |
Packages that use XbrzFilter
57 |
58 |
Package
59 |
Description
60 | 61 |
 
62 |
63 |
64 | 80 |
81 |
82 | 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 | 23 |
24 | 51 |
52 |
53 |
54 |

Uses of Class
io.github.stanio.xbrz.awt.XbrzImage

55 |
56 | No usage of io.github.stanio.xbrz.awt.XbrzImage
57 | 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 | 23 |
24 | 51 |
52 |
53 |
54 |

Uses of Class
io.github.stanio.xbrz.awt.XbrzOp

55 |
56 | No usage of io.github.stanio.xbrz.awt.XbrzOp
57 | 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 | 23 |
24 | 51 |
52 |
53 |
54 |

Hierarchy For Package io.github.stanio.xbrz.awt

55 |
56 | Package Hierarchies: 57 | 60 |
61 |

Class Hierarchy

62 | 77 |
78 |
79 | 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 | 23 |
24 | 51 |
52 |
53 |
54 |

Uses of Package
io.github.stanio.xbrz.awt

55 |
56 |
Packages that use io.github.stanio.xbrz.awt
57 |
58 |
Package
59 |
Description
60 | 61 |
 
62 |
63 |
64 | 83 |
84 |
85 | 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 | 23 |
24 | 51 |
52 |
53 |
54 |

Uses of Class
io.github.stanio.xbrz.awt.util.SmoothResizeOp

55 |
56 | No usage of io.github.stanio.xbrz.awt.util.SmoothResizeOp
57 | 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 | 23 |
24 | 51 |
52 |
53 |
54 |

Uses of Package
io.github.stanio.xbrz.awt.util

55 |
56 | 57 |
58 |
Package
59 |
Description
60 | 61 |
 
62 |
63 |
64 | 88 |
89 |
90 | 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 | 23 |
24 | 51 |
52 |
53 |
54 |

Hierarchy For Package io.github.stanio.xbrz

55 |
56 | Package Hierarchies: 57 | 60 |
61 |

Class Hierarchy

62 | 70 |
71 |
72 |

Interface Hierarchy

73 | 76 |
77 |
78 | 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 | 23 |
24 | 70 |
71 |
72 |
73 |

Module io.github.stanio.xbrz.core

74 |
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 |
    89 |
    Exports
    90 |
    91 |
    Package
    92 |
    Description
    93 | 94 |
     
    95 |
    96 |
    97 |
    98 |
  • 99 |
100 |
101 |
102 | 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 | 23 |
24 | 51 |
52 |
53 |
54 |

Uses of Class
io.github.stanio.xbrz.tool.ScalerTool

55 |
56 | No usage of io.github.stanio.xbrz.tool.ScalerTool
57 | 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 | 23 |
24 | 51 |
52 |
53 |
54 |

Hierarchy For Package io.github.stanio.xbrz.tool

55 |
56 | Package Hierarchies: 57 | 60 |
61 |

Class Hierarchy

62 |
    63 |
  • java.lang.Object 64 | 67 |
  • 68 |
69 |
70 |
71 | 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 | 23 |
24 | 51 |
52 |
53 |
54 |

Uses of Package
io.github.stanio.xbrz.tool

55 |
56 | No usage of io.github.stanio.xbrz.tool
57 | 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 | 23 |
24 | 70 |
71 |
72 |
73 |

Module io.github.stanio.xbrz.tool

74 |
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 |
    88 |
    Exports
    89 |
    90 |
    Package
    91 |
    Description
    92 | 93 |
     
    94 |
    95 |
    96 |
    97 |
  • 98 |
99 |
100 |
101 | 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 | 17 | 18 | 19 |
20 | 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 | 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 62 |

63 | 64 |

65 |
66 |

Loading search index...

67 | 71 |
72 | 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 | [![xbrz-awt](https://img.shields.io/maven-central/v/io.github.stanio/xbrz-awt?label=xbrz-awt&logo=openjdk&logoColor=silver)](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 | [![xbrz-core](https://img.shields.io/maven-central/v/io.github.stanio/xbrz-core?label=xbrz-core&logo=openjdk&logoColor=silver)](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 | --------------------------------------------------------------------------------