Java 2D 图像调整大小忽略双三次/双线性插值渲染提示(OS X + linux)

2024-03-04

我正在尝试使用 Image Voodoo 插件在 JRuby/Rails 应用程序中为上传的图像创建缩略图 - 问题是调整大小的缩略图看起来像......屁股。

似乎生成缩略图的代码绝对正确地执行了所有操作,将插值渲染提示设置为“双三次”,但在我们的开发环境 (OS X) 或生产 Web 服务器 (Linux) 上并没有遵循它们。

我提取了生成缩略图的代码,将其重写为直接 Java 应用程序(即从 main() 方法启动),并将插值渲染提示显式设置为“双三次”,并重现了(缺少)双三次和双线性调整大小。

正如预期的那样,在 OS X 和 Linux 上,缩略图都丑陋且像素化,但在 Windows 上,它通过使用双三次插值很好地调整了图像大小。

是否有任何 JVM 环境设置和/或其他库我缺少以使其正常工作?为了这个,我做了很多头撞墙的事情。


我意识到这个问题不久前就被问过,但以防万一其他人仍然遇到这个问题。

缩略图看起来像屁股的原因有两个原因(主要是第一个):

  • Java 中的非增量图像缩放非常粗糙,会丢弃大量像素数据,并且无论渲染提示如何,都会对结果进行一次平均。
  • 在 Java2D 中处理支持不佳的 BufferedImage 类型(通常是 GIF)可能会导致外观非常差/抖动的结果。

事实证明老面积平均比例过滤器 http://download.oracle.com/javase/6/docs/api/java/awt/image/AreaAveragingScaleFilter.html在制作漂亮的缩略图方面做得不错,但它速度很慢并且被 Java2D 团队弃用了——不幸的是他们没有用任何漂亮的开箱即用的替代方案来取代它,让我们有点靠自己了。

Chris Campbell(来自 Java2D 团队)几年前用增量缩放的概念解决了这个问题——不是在一次操作中从起始分辨率到目标分辨率,而是分步骤进行,结果看起来要好得多。

鉴于此代码相当大,我将所有最佳实践写入一个名为的库imgscalr http://www.thebuzzmedia.com/software/imgscalr-java-image-scaling-library/并在 Apache 2 许可证下发布。

最基本的用法如下所示:

BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, 640);

在此用例中,库使用所谓的“自动”缩放模式,并将生成的图像(尊重其比例)调整到 640x640 的边界框内。因此,如果图像不是正方形而是标准 4:3 图像,它会将其大小调整为 640x480 —— 参数只是它的最大尺寸。

网上还有很多其他方法标量类 http://www.thebuzzmedia.com/downloads/software/imgscalr/javadoc/org/imgscalr/Scalr.html(全静态且易于使用)让您可以控制一切。

为了获得尽可能最好看的缩略图,命令如下所示:

BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, Method.QUALITY, 
                                       150, 100, Scalr.OP_ANTIALIAS);

Scalr.OP_ANTIALIAS 是可选的,但很多用户觉得当你在 Java 中缩小到足够小的缩略图时,像素值之间的一些过渡有点过于离散,使图像看起来“锐利”,所以很多的用户请求一种稍微软化缩略图的方法。

这是通过一个卷积运算 http://download.oracle.com/javase/6/docs/api/java/awt/image/ConvolveOp.html如果您以前从未使用过它们,那么尝试找出要使用的正确“内核”......是一件痛苦的事情。在类上定义的 OP_ANTIALIAS 常量是我在与另一位将 imgscalr 部署到巴西社交网络(用于缩放个人资料照片)的用户进行一周测试后发现的最好看的抗锯齿操作。我把它包括在内是为了让每个人的生活更轻松一些。

此外,除了所有这些示例之外,您可能已经注意到,当您缩放 GIF 和某些其他类型的图像 (BMP) 时,有时缩放后的结果与原始图像相比看起来很糟糕……这是因为图像的支持很差。 BufferedImage 类型和 Java2D 回退到使用其软件渲染管道而不是硬件加速管道以获得更好的支持图像类型。

imgscalr 将为您处理所有这些问题,并将图像保留为最受支持的图像类型,以避免这种情况。

不管怎样,这确实是一个很长的说法,“你可以使用 imgscalr 为你做这一切,而不必担心任何事情”。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 2D 图像调整大小忽略双三次/双线性插值渲染提示(OS X + linux) 的相关文章

  • 使用 scikit-image 和 Transform.PolynomialTransform 进行图像变形

    我附上一个压缩档案 https drive google com file d 0B6EnJ Vh6zs1MkVCRlNhZkJsOEk view usp sharing包含说明和重现问题所需的所有文件 我还没有上传图片的权限 我有一个带有
  • 重构——套接字中的良好实践——简单的服务器-客户端 Swing 应用程序

    我使用单例和观察者模式编写了一个带有 Swing 接口的简单服务器 客户端程序 每个客户端都连接到服务器并可以发送消息 服务器将其收到的消息转发给其余的客户端 客户端使用 GUI 允许它们随时连接和断开与服务器的连接 该程序运行得很好 因为
  • 如何防止在 CXF Web 服务客户端中生成 JAXBElement

    我正在尝试使用 CXF 创建一个 Web 服务客户端来使用 WCF Web 服务 当我使用 wsdl2java 时 它生成具有 JAXBElement 类型而不是 String 的对象 我读到有关使用 jaxb bindings xml 文
  • H264 字节流到图像文件

    第一次来这里所以要温柔 我已经在给定的 H 264 字节流上工作了几个星期 一般注意事项 字节流不是来自文件 它是从外部源实时提供给我的 字节流使用 Android 的媒体编解码器进行编码 当将流写入扩展名为 H264的文件时 VLC能够正
  • 使用 JAXB 编组 LocalDate

    我正在构建一系列链接类 我希望能够将其实例编组到 XML 以便我可以将它们保存到文件中并稍后再次读取它们 目前我使用以下代码作为测试用例 import javax xml bind annotation import javax xml b
  • 从剪贴板获取图像 Awt 与 FX

    最近 我们的 Java FX 应用程序无法再从剪贴板读取图像 例如 用户在 Microsofts Paint 中选择图像的一部分并按复制 我不是在谈论复制的图像文件 它们工作得很好 我很确定它过去已经有效 但我仍然需要验证这一点 尽管如此
  • Maven 目标的默认阶段?

    据我了解 在 Maven 中 插件目标可以附加到生命周期阶段 如果没有定义 默认阶段是什么 根据我的经验 这取决于插件的目标 例如 组装 单个 http maven apache org plugins maven assembly plu
  • Android:自动从项目包中删除未使用的图像

    我正在开发一个相当大的android项目 并且在drawable文件夹中有很多图像 其中许多图像未在项目中使用 因为它们已被替换 并且占用了宝贵的空间 有什么方法可以自动找到这些图像并删除它们 而不是搜索项目中的每个图像 我使用过的一些工具
  • org.postgresql.util.PSQLException:协议错误。会话设置失败

    我知道这些类型的问题已经存在 但提供的解决方案对我不起作用 在我的应用程序中 没有版本不匹配的黑白驱动程序和 PostgreSQL 服务器 我还没有找到任何其他解决方案 我正在使用 PostgreSQL 服务器 9 4 和 postgres
  • 空 EntityManager/EJB 注入 MDB

    我有一个消息驱动 bean MDB 部署到 WebLogic 12 1 3 我尝试使用 PersistenceContext 注释将实体管理器注入 MDB 但实体管理器为空 我还尝试注入一个简单的无状态会话 bean 它也是空的 但是 Me
  • 如何屏蔽 Protobuf 中的某些字段

    我找不到一种方法来屏蔽 protobuf 结构中的某些字段 我确实阅读了有关 FieldMaskUtil 的内容并尝试了几个示例 但它似乎做了相反的操作 即复制 FieldMask 中提到的字段 这与我想要的不同 这是示例结构和相应的测试代
  • 此版本不符合 Google Play 64 位要求,添加库后仍然出现错误

    我正在 Play 商店上传一个视频编辑器应用程序 其中包含带有一些本机代码的库 所以我通过将其添加到 gradle 来使其兼容 64 位 ndk abiFilters armeabi v7a arm64 v8a x86 x86 64 添加了
  • 带有面板的 Java Swing JToolbar:外观和感觉

    我有一个JToolbar其中包含多个JPanels 需要 因为我希望每个都有特定的边界 不幸的是 外观管理器无法识别JPanels属于工具栏和JButtons因此 渲染器与普通按钮一样 即没有工具栏上的特殊鼠标悬停效果 更换JPanels
  • 如何使用 BufferedReader 对象从 Java 中的一行读取多个整数值?

    我正在使用 BufferedReader 类读取 Java 程序中的输入 我想读取用户的输入 该用户可以在带空格的单行中输入多个整数数据 我想读取整数数组中的所有这些数据 输入格式 用户首先输入他 她想要输入的数字数量 然后在下一行中使用多
  • 如何获取 Android 中临时文件的文件大小?

    如果我使用 openFileOutput 创建并写入临时文件 写入完成后如何获取文件大小 我希望这可以帮助你 File file new File selectedPath int file size Integer parseInt St
  • 更改 RowLayout SWT Java 中元素的顺序

    有没有办法更改在行布局中创建的元素的顺序 我想将其显示在元素中 首先显示 例如 如果我创建 element1 则 element2 element3 element4 我想看到的布局为 元素4 元素3 元素2 元素1 这意味着最后创建的元素
  • 如何列出所有可用的 LookAndFeel 主题?

    如何列出所有可用的 LookAndFeel 主题 我想在 JComboBox 中显示以供用户选择 这真的很简单 public static UIManager LookAndFeelInfo getInstalledLookAndFeels
  • 如何在 Java 中创建要打印到 JFrame 的 JLabels 数组

    我正在尝试制作一系列标签 每个标签都有一个来自函数的不同值 我不知道要使用的标签的确切数量 我的意思是可以打印任意数量的值 请帮我做这件事 很简单 只需一个方法返回一个数组或一些 JLabels 集合 并将它们全部添加到您的 JCompon
  • java中wav文件转换为字节数组

    我的项目是 阿塞拜疆语音的语音识别 我必须编写一个程序来转换wav文件到字节数组 如何将音频文件转换为byte 基本上如第一个答案中的片段所描述 但不是BufferedInputStream use AudioSystem getAudio
  • 如何使用 SAX Java 解析器读取注释文本

    我只想使用 Java 中的 SAX 解析器读取 XML 文件中对象标记的注释 这是我的文件的摘要

随机推荐

  • 统一处理非托管 API 中的错误代码

    我正在围绕一个相当大的非托管 API 编写一个包装器 几乎每个导入的方法在失败时都会返回一个常见的错误代码 现在 我正在这样做 ErrorCode result Api Method if result ErrorCode SUCCESS
  • Playframework 与 CSRF:“会话中未找到 CSRF 令牌”?

    我正在使用 Playframework 及其内置 CSRF 过滤器和 Security Authenticator 系统制作一个简单的身份验证系统 但我遇到了一个问题 当用户填写登录名 密码并提交输入时 出现以下错误 在会话中找不到 CSR
  • 如何更新 SQL 中游标获取的列

    在进一步讨论之前 是的 我知道与基于集合的操作相比 游标的性能很差 在这种特殊情况下 我在包含 100 条左右记录的临时表上运行游标 并且该临时表始终相当小 因此性能不如灵活性那么重要 我的困难是我无法找到如何更新游标获取的列的示例 以前
  • 在 Git 中运行预提交挂钩。有没有办法验证脚本是否正在运行?

    我想运行 Git 按照博客的建议 我使用了 git init初始化存储库 然后 git在 hooks 目录中存在钩子的位置创建文件夹 然后按照我重命名的脚本的建议pre commit sample as pre commit它不起作用 所以
  • 如何在Qt中保存对话框的状态?

    假设对话框中有复选框 选项等控件 如何在 Qt 中保存对话框的状态 我应该使用 QSettings 还是其他东西 Thanks 我遇到了同样的问题 谷歌搜索并没有太大帮助 所以最后我写了自己的解决方案 我创建了一组函数 用于在创建和销毁时读
  • Keras:为什么损失函数必须为每个批次项返回一个标量,而不仅仅是一个标量?

    我正在 Keras 中编写一个自定义损失函数 但遇到了以下问题 为什么 Keras 损失函数必须为每个批次项返回一个标量 而不是仅返回一个标量 我关心的是整批的累计损失 而不是每件商品的损失 不是吗 我想我已经明白了 fit 有争论samp
  • 更好地理解 C# 泛型

    我查看了一些使用 C 泛型的示例代码 为什么以及何时应该使用它们 所有的例子都很复杂 我需要一个简单 清晰的示例来帮助我开始使用 C 泛型 一个非常简单的例子是通用的List
  • 使用 PHP 5.5 安装 xdebug

    我读了很多答案 但不明白为什么 xdebug 不起作用 php ini xdebug zend extension usr lib php5 20090626 xdebug so php v PHP 5 5 6 1 debphp org p
  • Docker 容器未开始给出“OCI 运行时创建失败”

    我已经安装了Docker版本 https docs docker com release notes 17 12 0 ce 构建 c97c6d6当我尝试启动任何容器时 出现以下错误 docker 来自守护进程的错误响应 OCI运行时创建失败
  • 在像素着色器中计算世界空间坐标

    我有一个像素着色器 我想根据我的世界空间坐标计算每个像素的位置 我该怎么做 我需要什么 我有一个ps input具有 float4 位置的结构 SV POSITION 我认为这很重要 但存储在里面的值似乎有点有趣 我似乎无法弄清楚它们有什么
  • Liferay 连接和压缩 javascript

    我试图弄清楚如何实现所有 js 文件的压缩和缩小 目前我将它们放在一个钩子插件中 html js mycustomjs folder 我知道liferay有自己的机制来压缩javascripts 在barebone jsp或 everyth
  • 在 MacOSX 上,当指定无效的身份验证凭据时,QNetworkAccessManager 会进入无限循环

    在我的跨平台应用程序中 我使用 QNetworkAccessManager 将 HTTP 请求发送到需要身份验证的 HTTP 服务 我最近升级到 QT5 令我完全惊讶的是 在 MacOSX 上 我的应用程序会在某些情况下尽快向我的服务发送大
  • 合理化我的简单 OpenCL 内核中有关全局内存的情况

    const char programSource kernel void vecAdd global int a global int b global int c int gid get global id 0 for int i 0 i
  • CodeIgniter Active Record 一次删除多条记录

    这是我的控制器功能之一 它从名为 users 的数据库表中获取所有行并将其放入数组中 然后它加载一个名为 deleteuser 的视图以及传递的数组数据 function deleteuser this gt load gt model u
  • 如何使用鼠标手动放置 networkx 节点?

    我有一个相当大且混乱的节点网络 我希望尽可能整齐地显示它 This is how it s currently being displayed 首先 我尝试调整布局 看看它是否可以自动生成良好的输出 我尝试了许多不同的 nx 布局 但它们都
  • 谷歌应用程序引擎Python第一次上传应用程序

    我第一次尝试上传我的应用程序引擎项目 但我不知道为什么它不起作用 我的终端的错误是 me Desktop appcfg py update ProjectDir Application tacticalagentz version 1 Ho
  • 运行脚本来重命名 txt 文件中的几个单词

    我需要你的帮助 我的目录 文件夹 中有一个 txt 文件 需要运行脚本来重命名几个单词 例如 其中 LX4XAB 到 LX4xab XS3X44 到 Xs3x44 在哪里 另一个词 直到最后用另一个名称保存文件 你能帮助我吗 谢谢 干得好
  • Node 中express.js 和 axios.js 的区别

    我们使用axios来进行get post等http请求 我们也出于同样的目的使用快递 然而 根据我读到的内容 它们有不同的目的 请解释一下如何 PS 如果能举例说明就太好了 你可以将express js视为一个仓库 app get item
  • 从 LinkedHashMap 中检索值

    我有一个看起来像这样的对象 test1 get tags restcalls test2 put tags restcalls 我正在检索上面的对象 如下所示 HashMap json new ObjectMapper readValue
  • Java 2D 图像调整大小忽略双三次/双线性插值渲染提示(OS X + linux)

    我正在尝试使用 Image Voodoo 插件在 JRuby Rails 应用程序中为上传的图像创建缩略图 问题是调整大小的缩略图看起来像 屁股 似乎生成缩略图的代码绝对正确地执行了所有操作 将插值渲染提示设置为 双三次 但在我们的开发环境