- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试从一些图像数据创建一个 BufferedImage,它是一个字节数组。图像是 RGB 格式,每个像素有 3 个样本 - R、G 和 B,每个样本 32 位(对于每个样本,不是所有 3 个样本)。
现在我想从这个字节数组创建一个 BufferedImage。这就是我所做的:
ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] {32, 32, 32}, false, false, Transparency.OPAQUE, DataBuffer.TYPE_INT);
Object tempArray = ArrayUtils.toNBits(bitsPerSample, pixels, samplesPerPixel*imageWidth, endian == IOUtils.BIG_ENDIAN);
WritableRaster raster = cm.createCompatibleWritableRaster(imageWidth, imageHeight);
raster.setDataElements(0, 0, imageWidth, imageHeight, tempArray);
BufferedImage bi = new BufferedImage(cm, raster, false, null);
上述代码适用于每个样本 24 位 RGB 图像,但不适用于每个样本 32 位。生成的图像是垃圾,显示在图像的右侧。它应该像图像的左侧。
注意:我的机器上唯一可以读取此图像的图像阅读器是 ImageMagick。所有其他显示的结果与下图右侧的垃圾类似。
ArrayUtils.toNBits() 只是将字节数组转换为具有正确字节顺序的 int 数组。我确定这个是正确的,因为我已经与其他方法交叉检查以生成相同的 int 数组。
我想问题可能是因为我使用所有 32 位 int 来表示包含负值的颜色。看起来我需要 long 数据类型,但是没有 long 类型的 DataBuffer。
Instances of ComponentColorModel created with transfer types DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, and DataBuffer.TYPE_INT have pixel sample values which are treated as unsigned integral values.
以上引用来自 ComponentColorModel 的 Java 文档。这意味着 32 位样本确实被视为无符号整数值。那么问题可能出在其他地方。
有没有人遇到过类似的问题并找到了解决方法,或者我可能在这里做错了什么?
更新 2:“真正的”问题在于当使用 32 位样本时,ComponentColorModel 的算法将 1 向左移动 0 次 (1<<0),因为移动开启int 始终在 0~31 之间(含)。这不是预期值。要解决这个问题(实际上左移 32 次),唯一需要做的就是将 1 从 int 更改为 long 类型,如 1L,如下面的修复所示。
更新:根据 HaraldK 的回答和评论,我们最终同意问题来自 Java 的 ComponentColorModel,它没有正确处理 32 位样本。 HaraldK 提出的修复方案也适用于我的案例。以下是我的版本:
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
public class Int32ComponentColorModel extends ComponentColorModel {
//
public Int32ComponentColorModel(ColorSpace cs, boolean alpha) {
super(cs, alpha, false, alpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE, DataBuffer.TYPE_INT);
}
@Override
public float[] getNormalizedComponents(Object pixel, float[] normComponents, int normOffset) {
int numComponents = getNumComponents();
if (normComponents == null || normComponents.length < numComponents + normOffset) {
normComponents = new float[numComponents + normOffset];
}
switch (transferType) {
case DataBuffer.TYPE_INT:
int[] ipixel = (int[]) pixel;
for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
normComponents[nc] = ipixel[c] / ((float) ((1L << getComponentSize(c)) - 1));
}
break;
default: // I don't think we can ever come this far. Just in case!!!
throw new UnsupportedOperationException("This method has not been implemented for transferType " + transferType);
}
return normComponents;
}
}
最佳答案
更新:
这似乎是一个已知错误:ComponentColorModel.getNormalizedComponents() does not handle 32-bit TYPE_INT ,10(十!)年前针对 Java 5 的报道。
有利的一面是,Java 现在已部分开源。我们现在可以提出一个补丁,如果幸运的话,它将针对 Java 9 左右进行评估......:-P
该错误提出了以下解决方法:
Subclass ComponentColorModel and override getNormalizedComponents() to properly handle 32 bit per sample TYPE_INT data by dividing the incoming pixel value by 'Math.pow(2, 32) - 1' when dealing with this data, rather than using the erroneous bit shift. (Using a floating point value is ok, since getNormalizedComponents() converts everything to floating point anyway).
我的修复有点不同,但基本思想是相同的(随意优化您认为合适的:-)):
private static class TypeIntComponentColorModel extends ComponentColorModel {
public TypeIntComponentColorModel(final ColorSpace cs, final boolean alpha) {
super(cs, alpha, false, alpha ? TRANSLUCENT : OPAQUE, DataBuffer.TYPE_INT);
}
@Override
public float[] getNormalizedComponents(Object pixel, float[] normComponents, int normOffset) {
int numComponents = getNumComponents();
if (normComponents == null) {
normComponents = new float[numComponents + normOffset];
}
switch (transferType) {
case DataBuffer.TYPE_INT:
int[] ipixel = (int[]) pixel;
for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) {
normComponents[nc] = ((float) (ipixel[c] & 0xffffffffl)) / ((float) ((1l << getComponentSize(c)) - 1));
}
break;
default:
throw new UnsupportedOperationException("This method has not been implemented for transferType " + transferType);
}
return normComponents;
}
}
考虑以下代码。如果按原样运行,对我来说,它显示的图像大部分是黑色的,右上四分之一的白色覆盖着一个黑色圆圈。如果我将数据类型更改为 TYPE_USHORT
(取消注释 transferType
行),它会显示一半/一半白色和从黑色到白色的线性渐变,中间有一个橙色圆圈(应该如此)。
使用ColorConvertOp
转换为标准类型似乎没有什么区别。
public class Int32Image {
public static void main(String[] args) {
// Define dimensions and layout of the image
int w = 300;
int h = 200;
int transferType = DataBuffer.TYPE_INT;
// int transferType = DataBuffer.TYPE_USHORT;
ColorModel colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), false, false, Transparency.OPAQUE, transferType);
WritableRaster raster = colorModel.createCompatibleWritableRaster(w, h);
BufferedImage image = new BufferedImage(colorModel, raster, false, null);
// Start with linear gradient
if (raster.getTransferType() == DataBuffer.TYPE_INT) {
DataBufferInt buffer = (DataBufferInt) raster.getDataBuffer();
int[] data = buffer.getData();
for (int y = 0; y < h; y++) {
int value = (int) (y * 0xffffffffL / h);
for (int x = 0; x < w; x++) {
int offset = y * w * 3 + x * 3;
data[offset] = value;
data[offset + 1] = value;
data[offset + 2] = value;
}
}
}
else if (raster.getTransferType() == DataBuffer.TYPE_USHORT) {
DataBufferUShort buffer = (DataBufferUShort) raster.getDataBuffer();
short[] data = buffer.getData();
for (int y = 0; y < h; y++) {
short value = (short) (y * 0xffffL / h);
for (int x = 0; x < w; x++) {
int offset = y * w * 3 + x * 3;
data[offset] = value;
data[offset + 1] = value;
data[offset + 2] = value;
}
}
}
// Paint something (in color)
Graphics2D g = image.createGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, w / 2, h);
g.setColor(Color.ORANGE);
g.fillOval(100, 50, w - 200, h - 100);
g.dispose();
System.out.println("image = " + image);
// image = new ColorConvertOp(null).filter(image, new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB));
JFrame frame = new JFrame();
frame.add(new JLabel(new ImageIcon(image)));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
对我来说,这似乎表明使用 transferType TYPE_INT
的 ColorModel
有问题。但我很乐意犯错。 ;-)
您可以尝试的另一件事是将值缩小到 16 位,使用 TYPE_USHORT
光栅和颜色模型,看看这是否有所不同。我打赌它会,但我懒得尝试。 ;-)
关于java - 如何为每个样本 32 位、3 个样本图像数据创建 BufferedImage,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26875429/
我正在处理不平衡的面板数据,我想从中抽取一个随机样本,该样本不受每个单位不同观察次数的影响。例如,在下面的代码中,IBM 被选中的可能性是 GOOG 的两倍,被选中的可能性是 MSFT 的五倍。有没有
有人可以指出实现 CollectionChanged 的示例。我正在使用 wpf mvvm 灯。我试图谷歌,没有找到任何足够好的东西。 最佳答案 public ObservableCollecti
我有 df我想对某些变量的分布进行一些抽样。比方说 df['type'].value_counts(normalize=True)返回: 0.3 A 0.5 B 0.2 C 我想做类似 sampled
我仍然无法理解样本/像素/片段之间有什么区别。 由于片段着色器按像素执行,我认为片段只是指一个像素,这是正确的吗?谁能给我一个例子和每个人的定义? 最佳答案 片段着色器按片段执行并发出像素。它们非常相
我正在尝试理解这个名为“The Amazing Audio Engine”的 GitHub 项目,它简化了在 iOS 上处理音频的过程。 我从麦克风捕捉并使用这种方法: id receiver = [
如何在诺基亚 Qt SDK(用于手机)中使用 QTableView。我引用了一些文档,但我仍然不清楚 QTableView。请任何人建议如何使用 QTableView。 我想显示具有三列的 QTabl
我已经能够获取 JmDNS 附带的示例来编译和运行,但是我无法获取任何类来发现我的服务。 我正在运行一个 Windows 环境,多台 PC 运行 VNC、SSH 和 Apache,我一直在尝试让 Jm
问题的具体实例 我的整数范围是 1-100。我想生成此范围内的 n 个总数,这些数字尽可能均匀分布并包括第一个和最后一个值。 示例 start = 1, end = 100, n = 5 Outp
我在线程组中有几个带有脚本的 JSR 223 采样器,它们在执行在调用 HTTP 请求之前进行一些工作。 问题在于 JSR 233 采样器包含在最终摘要报告中 我的问题是如何从最终计算中排除那些 JS
我需要有关存储后端歌曲预览的好方法的建议(现在正在查看iTunes,也许还有spotify和soundcloud)。我的想法是,我需要预下载并可能缓存30秒及更少的音频文件,以方便召回。 然后,我需要
我刚刚从 Github 下载了 Atmosphere 样本。当我在聊天样本上运行 jetty:run goal 时,我遇到了一些问题。 我可以使用浏览器访问该页面(http://localhost:9
我有一个包含五个项目的向量。 my_vec 有更换,当我需要时没有更换。最有效的方法是什么? 请注意,在我的向量中,我有两次值“a” - 因此,在返回的打乱向量集中,它们都应该有两次“a”。 最佳答案
我正在尝试学习如何阅读规范。让我们看看尝试压缩后会得到什么:1) 一个空缓冲区和 2) 一个感叹号: >>> zlib.compress(b'', 0) b'x\x01\x01\x00\x00\xff
我是 cuda 的新手,几周前才开始阅读有关并行编程和 cuda 的内容。在我安装了 cuda 工具包之后,我正在浏览 sdk 示例(安装工具包时附带的)并想尝试其中的一些。我从 0_Simple 文
我正在使用 FsCheck 生成自定义数据的 Gen . 假设你有一个函数返回 Gen : let chooseRectangle widthMax heightMax offset = gen
我有一个包含大约 800 万个观察值的数据框。我需要从中提取样本,但想从多个列中采样。 我尝试了以下方法,但不起作用: import pandas as pd state = ['mi', 'mi',
我学习安卓图形,我遇到了一个奇怪的问题: 我发现很多提到“FingerPaint”样本的地方,但我在样本文件夹中找不到它。 只有 47 个示例项目,没有一个是关于图形的。 如何下载此示例?我按照这
假设我有一个 pandas 数据框 rid category 0 0 c2 1 1 c3 2 2 c2 3 3 c3 4 4
我想用 Pandas sample功能,但具有不分组或过滤数据的标准。 import pandas as pd import numpy as np df = pd.DataFrame(np.rand
我正在尝试从 MNIST 数据集中绘制 10 个样本。每个数字之一。这是代码: import sklearn import pandas as pd import matplotlib.pyplot
我是一名优秀的程序员,十分优秀!