在 JMP 数据表中压缩(相同)图像JMP 能够将图像存储在数据列中。
即使存储同一张图片 1000 次,速度也超级快——而且不会占用电脑内存。
但是将文件存储到硬盘上需要一些时间,而且会占用大量空间!
启用 GZ 压缩也无济于事:

试试看——为什么 GZ 压缩不起作用?
dt = new table("test", add rows(1000),Compress File When Saved( 1 ), new column ("img", Expression));
myIMg= New Image(open("https://apod.nasa.gov/apod/image/2603/NGC1300-LRGB_1024.jpg"));
:img[1] = myImg;
// add the image to row 1
dt << save("$temp\test1.jmp");
wait(0);
Show(File Size( "$temp\test1.jmp" ));
// add the image to every row
for each row(
:img=myImg
);
wait(0);
lastImg= new image(:img[1000]);
last image << scale(0.2);
ex = New Window( "Modal Dialog example",
Modal,
V List Box(
Text Box( "Wow, very fast! this is the image in row 1000:" ),
Picture Box (last image),
Text Box( "do you have enough time/space to save the data table?" ),
H list Box (Button Box ("OK",bb<< close window()),bb = Button Box("cancel", bb<< close window();stop();)),
)
);
dt << save("$temp\test2.jmp");
wait(0);
Show(File Size( "$temp\test2.jmp" ));
自动化和脚本编写内容组织回复:在 JMP 数据表中压缩(相同)图像文件保存之前,为什么 JMP 运行速度这么快?
对用户而言,似乎每一行都会保存一张图片:

但 JMP 只存储了对原始图像的引用。改变图像大小即可显示链接:
names default to here(1);
dt = new table("test", add rows(10),Compress File When Saved( 1 ), new column ("img", Expression));
myIMg= New Image(open("https://apod.nasa.gov/apod/image/2603/NGC1300-LRGB_1024.jpg"));
:img[1] = myImg;
// add the image to every row - as a "reference"
for each row(
:img=myImg
);
wait(0);
// add the image to row 4 - as a new image
:img[4] = new image(myImg);
// change on e of the images
image2 = :img[2];
image2 << scale(0.5);
// ... changes all the images - because all of them are links to the same image
Show(image2 << get size);
Show(myImg << get size);
Show(:img[3] << get size);
// all of them? not row 4
Show(:img[4] << get size);

回复:在 JMP 数据表中压缩(相同)图像当堆叠带有图像的表格时,也适用同样的技巧。
大胆去做吧——你可以堆叠成千上万列,得到成千上万张重复的图片——它们是克隆的,不会占用内存。
但千万别去救那张叠起来的桌子!
Names Default to Here(1);
dt = Open( "$SAMPLE_DATA/Big Class Families.jmp" );
dtstack = dt << Stack(
columns( :height, :weight )
);
:picture[1] << scale(5);
Show(:picture[1] << get size);
Show(:picture[2] << get size);
回复:在 JMP 数据表中压缩(相同)图像……并考虑附带损害。
它们并不像你想象的那样显而易见。
Names Default to Here(1);
dt = Open( "$SAMPLE_DATA/Big Class Families.jmp" );
Show(dt:picture[1] << get size);
dt sub = dt<< Subset( All rows, Selected columns only( 0 ) ); // non-linked subset
dt stack = dt << Stack(
columns( :height, :weight )
);
dt stack:picture[1] << scale(0.1);
Show(dt stack:picture[1] << get size);
Show(dt stack:picture[2] << get size);
Show(dt:picture[1] << get size);
Show(dt sub:picture[1] << get size);

回复:在 JMP 数据表中压缩(相同)图像JPG 格式本身就是一种优化过的压缩格式。通常情况下,压缩随机数据、已压缩数据或加密数据会导致数据量增大而不是减小,因为压缩算法几乎找不到可压缩的数据,而且还会在压缩数据周围添加头部信息和一些管理数据。没错,数据表确实将二进制图像以 base64 编码的形式“保存”到列的字符串字段中,但对于 gzip 压缩来说,它仍然看起来像是随机数据。
我认为真正的问题(或许应该转交给 JMP 技术支持,进而转交给数据表开发者)是:为什么这里保存的不是单个副本和引用,而是完全相同的镜像副本?我还假设,如果加载已保存的表,由于它们现在可能已经是不同的,因此会占用大量内存。如果数据表知道它在内存中是相同的,为什么在保存时不保持这一点呢?
回复:在 JMP 数据表中压缩(相同)图像[ 00296024 ]
->“
JMP 没有以最大化图像存储效率的方式压缩数据表,这并不奇怪。看起来一切运行正常。
回复:在 JMP 数据表中压缩(相同)图像实际上,最简单的办法是:JMP 识别出图像是相同的,并在存储文件时使用此信息。
似乎在内存中,JMP 使用类似“指针”的东西,多个指针指向同一张图片。-> 生成表格时会进行收集。
JMP 存储文件时,会使用指针,并且对于相同的图像也毫不在意,会将它们逐个存储。
然而,令我惊讶的是,该列的压缩算法没有识别出重复项,也没有有效地存储它们。
我的AI推测(可能是出于向后兼容性的考虑?),JMP使用了一种较旧的压缩机制,其压缩窗口较小(JMP的首选项中提到了gz格式)。在这种情况下,解析第二张图像时,第一张图像将位于压缩窗口之外。
人工智能建议:
改用更现代的压缩方案(zstd / lzma?)不仅可以显著提高多个相同图像的压缩率,还可以更好地压缩其他类型的列。
回复:在 JMP 数据表中压缩(相同)图像开发人员已经意识到这个问题,并表示他正在调查。JMP 数据表最初并不支持图像,图像功能是最近(大约十年前)才添加的。我认为添加图像支持时,采用这种方式是为了避免更改 .jmp 文件格式,并保持向后兼容性。对于旧版本的 JMP,图像会显示为字符串数据。此外,它还允许通过脚本创建包含图像的表格。修复此问题可能需要更新 .jmp 文件格式。或许可以将图像像分类数据或列表检查类型的数据一样存储在内部,并且最好使用二进制 blob 格式而不是 base64 编码。
非常感谢你们帮我们找出这些问题并进行修复。最终,我们希望 JMP 能够兼顾高性能和良好的内存使用率。
数据量只会越来越大。
回复:在 JMP 数据表中压缩(相同)图像听起来不错。
感谢大家的坦诚讨论和真知灼见

我们的共同目标是使 JMP 尽可能地完善——强大、全面、精良。
它应该会继续保持世界最佳分析工具的地位。……随着人工智能的飞速发展,竞争将会更加激烈!
回复:在 JMP 数据表中压缩(相同)图像Excel:关系容器(通过指针对图像进行去重)。
JMP:扁平数据流(每行重复图像二进制数据)。
— 由 Gemini 3.1 Pro 声明