如何将24位PNG保存/转换为8位PNG?

时间:2012-09-04 00:13:06

标签: java railo jai cfimage cfml

我使用ImageNew中的Railo(和相关内容)创建图片,其中使用了JAI

当我保存图像时,我得到一个24位PNG,但我只需要8位。 (只需使用图形编辑器将文件重新保存为8位,就可以得到四分之一到一半的字节数。)

ImageWrite不提供任何有关PNG位深度的功能,我也找不到任何与JAI本身相关的细节(获取http://jai-core.dev.java.net/的DNS错误)

更新

使用Quantize ImageFilter我可以将颜色数量减少到256 - 这会大大减少文件大小(但仍然没有手动处理),但仍会导致24- bit / unpaletted PNG文件。不幸的是,它也消除了我需要保留的透明度(或至少重新应用。)

如果我生成并通过OptiPNG(一个无损PNG优化器)生成它的文件,它会生成索引的8位文件并削减相当多的字节并提供可接受的文件大小。

因此,拼图的剩余步骤:如何在ImageFilter删除之后重新应用透明度(或者更好,防止它被删除)。

我想我需要某种方式来做Image.replace('white','transparent')作为基于Railo / Java的解决方案或跨平台的命令行工具。

3 个答案:

答案 0 :(得分:2)

好的,所以我有一个可以产生可接受结果的工作解决方案 - 最终文件比我原来的手动过程略小,但在视觉上无法区分。

解决方案并不像我想的那样跨平台(需要为OptiPNG寻找/构建Linux二进制文件),但它仍然是一个足够好的解决方案。

正如Leigh在问题评论中所建议的那样,我使用的是量化器来减少颜色,然后使用MapColorsFilter来修复量化器打破透明度的事实,然后最后使用OptiPNG将生成的文件压缩为a合理的大小。

以下是相关代码:

<cfscript>
    var Filename = './filename.png'
    var MyImage = NewImage(Filename)

    ImageFilter(MyImage,'quantize',{numColors:256,dither:false})

    // ImageFilter(MyImage,'MapColors',{oldColor:'white',newColor:'ffffff00'})
    var TransImage = ImageMapColors(MyImage,'white','ffffff00')

    ImageWrite( TransImage , Filename )
</cfscript>

<cfexecute
    name      = "#Variables.OptiPngExecutable#"
    arguments = "-o9 #Filename#"
    timeout   = 30
/>

目前RailoC的ImageFilter中有一个针对MapColors过滤器的错误,所以我必须直接访问过滤器,这里是我用来解决的代码:

<cffunction name="ImageMapColors" output=false >
    <cfargument name="Image" rtype="Image" required />
    <cfargument name="Old"   type="String" required />
    <cfargument name="New"   type="String" required />

    <cfset var ObjKey = 'ColorReplacer_#Arguments.Old#_#Arguments.New#' />

    <cfif NOT StructKeyExists(Variables,ObjKey)>
        <cfset var Old = createObject('java','railo.commons.color.ColorCaster').toColor(Arguments.Old) />
        <cfset var New = createObject('java','railo.commons.color.ColorCaster').toColor(Arguments.New) />
        <cfset Variables[ObjKey] = createObject("java","railo.runtime.img.filter.MapColorsFilter")
            .init(Old.getRGB(),New.getRGB()) />
    </cfif>

    <cfreturn ImageNew( Variables[ObjKey].filter(ImageGetBufferedImage(Arguments.Image),{}) ) />
</cffunction>

答案 1 :(得分:0)

cfexecute

pngquant应满足您的需求。

答案 2 :(得分:-1)

您是否尝试使用ImageWrite()的“质量”属性首先将中间步骤保存为JPEG,然后另存为PNG?只是一个想法。猜测使用.3.4作为值可能会有效吗?