在Scala中编写功能强大且功能强大的图像处理库
我们正在为Scala(学生项目)开发一个小型图像处理库。该库完全功能(即无变异性)。图像的栅格存储为Stream [Stream [Int]],以最小的努力利用懒惰评估的好处。然而,在对映像执行一些操作时,堆将被满载并抛出OutOfMemoryError。 (例如,在JVM堆空间不足之前,可以对大小为500 x 400,35 kb的jpeg图像执行多达4个操作。)
我们想到的方法是: >使用JVM选项进行Twiddling并增加堆大小。 (我们不知道如何做到这一点在IDEA – 我们正在使用的IDE。) 我们最后一个选择是放弃不变性,并使其成为一个可变的库(如流行的图像处理库),这是我们不想做的。请建议我们有一些方法来保持这个库的功能并且仍然有效,如果你知道我的意思。 谢谢, 附录: val image = Image from "E:/metallica.jpg" val redded = image.map(_ & 0xff0000) redded.display(title = "Redded") 并输出: "C:Program Files (x86)Javajdk1.6.0_02binjava" -Didea.launcher.port=7533 "-Didea.launcher.bin.path=C:Program Files (x86)JetBrainsIntelliJ IDEA Community Edition 10.0.2bin" -Dfile.encoding=windows-1252 -classpath "C:Program Files (x86)Javajdk1.6.0_02jrelibcharsets.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibdeploy.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibjavaws.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibjce.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibjsse.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibmanagement-agent.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibplugin.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibresources.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibrt.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibextdnsns.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibextlocaledata.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibextsunjce_provider.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibextsunmscapi.jar;C:Program Files (x86)Javajdk1.6.0_02jrelibextsunpkcs11.jar;C:new PhPhoebeoutproductionPhoebe;E:InventoryMarvin.jar;C:scala-2.8.1.finallibscala-library.jar;C:scala-2.8.1.finallibscala-swing.jar;C:scala-2.8.1.finallibscala-dbc.jar;C:new Ph;C:scala-2.8.1.finallibscala-compiler.jar;E:Inventorycommons-math-2.2.jar;E:Inventorycommons-math-2.2-sources.jar;E:Inventorycommons-math-2.2-javadoc.jar;E:Inventoryjmathplot.jar;E:Inventoryjmathio.jar;E:Inventoryjmatharray.jar;E:InventoryJavax Media.zip;E:Inventoryjai-core-1.1.3-alpha.jar;C:Program Files (x86)JetBrainsIntelliJ IDEA Community Edition 10.0.2libidea_rt.jar" com.intellij.rt.execution.application.AppMain phoebe.test.ImageTest Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at scala.collection.Iterator$class.toStream(Iterator.scala:1011) at scala.collection.IndexedSeqLike$Elements.toStream(IndexedSeqLike.scala:52) at scala.collection.Iterator$$anonfun$toStream$1.apply(Iterator.scala:1011) at scala.collection.Iterator$$anonfun$toStream$1.apply(Iterator.scala:1011) at scala.collection.immutable.Stream$Cons.tail(Stream.scala:565) at scala.collection.immutable.Stream$Cons.tail(Stream.scala:557) at scala.collection.immutable.Stream$$anonfun$map$1.apply(Stream.scala:168) at scala.collection.immutable.Stream$$anonfun$map$1.apply(Stream.scala:168) at scala.collection.immutable.Stream$Cons.tail(Stream.scala:565) at scala.collection.immutable.Stream$Cons.tail(Stream.scala:557) at scala.collection.immutable.Stream$$anonfun$flatten1$1$1.apply(Stream.scala:453) at scala.collection.immutable.Stream$$anonfun$flatten1$1$1.apply(Stream.scala:453) at scala.collection.immutable.Stream$Cons.tail(Stream.scala:565) at scala.collection.immutable.Stream$Cons.tail(Stream.scala:557) at scala.collection.immutable.Stream.length(Stream.scala:113) at scala.collection.SeqLike$class.size(SeqLike.scala:221) at scala.collection.immutable.Stream.size(Stream.scala:48) at scala.collection.TraversableOnce$class.toArray(TraversableOnce.scala:388) at scala.collection.immutable.Stream.toArray(Stream.scala:48) at phoebe.picasso.Image.force(Image.scala:85) at phoebe.picasso.SimpleImageViewer.<init>(SimpleImageViewer.scala:10) at phoebe.picasso.Image.display(Image.scala:91) at phoebe.test.ImageTest$.main(ImageTest.scala:14) at phoebe.test.ImageTest.main(ImageTest.scala) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:115) Process finished with exit code 1 解决方法
如果我理解正确,您将每个像素存储在一个Stream元素中,这可能是低效的。您可以做的是创建自定义的LazyRaster类,其中包含对某些大小(例如,20×20)的图像块的延迟引用。第一次写一个块时,它的相应的数组被初始化,从那里改变像素意味着写入该数组。
这是更多的工作,但可能会导致更好的性能。此外,如果您希望支持图像操作的堆叠(例如,进行地图绘制),然后在“一次性”中评估图像,则实施可能会变得棘手 – 流实现是最佳证据。 另一件可以做的事情是确保旧的Streams是properly garbage collected.我怀疑你的例子中的图像对象是你的流的包装器。如果您希望将多个映像操作(如映射)堆叠在一起,并且能够gc不再需要的引用,则必须确保不保存对流的任何引用 – 请注意,如果: >你有一个参考你的图像堆栈(在图中的例子) 不用多了解具体的用例,很难说更多。 就个人而言,我会完全避免Streams,只需使用一些不可改变的基于阵列的数据结构,既节省空间,又避免了拳击。我唯一可以看到Streams使用的地方是迭代图像转换,如卷积或应用一叠过滤器。相反,您不会有像素流,而是流图像。这可能是表达一系列变革的好方法 – 在这种情况下,上面给出的链接中关于gc的评论适用。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |