2

我有一个新的 CF18 服务器,我在读取和转换一些在我以前的 CF11 服务器上可读的旧图像时遇到了一些错误。仅供参考 GetReadableImageFormats 结果为“BMP,GIF,JPEG,JPEG 2000,JPEG2000,JPG,PNG,PNM,RAW,TIF,TIFF,WBMP”

通常我将文件作为二进制文件读取并将其放入内存中进行操作

<cffile action="readBinary" file="#file_location#" variable="binImage" />
<cfimage action="read" source="#binImage#" name="objImage" isbase64="no"> 

现在这会导致错误:“尝试读取图像时发生异常。流中没有 SOF 段”

使用 action="read" 读取文件并转储 left(binImage, 999) 结果:“...2015:10:07 17:46:58 Kofax standard Multi-Page TIFF Storage Filter v3.03.000,...”

然后我尝试使用以下方法将其读入java:

<cfset tifFileName="#file_location#">
<cfscript>
     ss = createObject("Java","com.sun.media.jai.codec.FileSeekableStream").init(tifFileName);
     //create JAI ImageDecoder
     decoder = createObject("Java","com.sun.media.jai.codec.ImageCodec").createImageDecoder("tiff", ss, JavaCast("null",""));
 </cfscript>

这会产生错误:“不支持旧式 JPEG-in-TIFF 数据的解码。”

我发现了这个... 不支持旧式 JPEG-in-TIFF 数据的解码

您认为使用 TwelveMonkeys ImageIO 是解决我的问题的最佳途径吗?

更新:根据存在无效标记 0xFF9E 的建议,我尝试了以下操作:

<cffile action="readBinary" file="#file_location#" variable="binImage" />
<cfset hexEncoding = binaryEncode(binImage, "hex")>
<cfset new_hexEncoding = replaceNoCase(hexEncoding, 'FF9E', 'FFE9', 'ALL')>
<cfset binImage = binaryDecode(new_hexEncoding, "hex")>

isImage(binImage) 返回“NO”并且“流中没有 SOF 段”错误仍然存​​在。我遍历了 hexEncoding 并找到了 FF9E 字符串 23x。我从未编辑过原始图像代码,所以我不确定我的替换是否正确。

编辑:此时我相当确定我的搜索和替换 hexEncoding、'FF9E'、'FFE9' 逻辑有缺陷。在 binaryEncoded binImage 中没有出现 0xff9e。

4

1 回答 1

0

这让我发疯了。除了安装额外的 JAVA 库或通过其他可执行文件路由它来进行转换之外,我尝试了所有能找到的方法。在我的例子中,TIFF 中只有一个 JPEG,所以我写了一些东西,从 TIFF 中抓取 JPEG 的二进制数据(不考虑页面)并提供它。获得 JPEG 的二进制文件后,您可以将其写入文件,对其进行转换,甚至将其直接流式传输到浏览器。来吧,未来需要这个的人。我没有写它来做页面或检测它是什么类型的 tiff,因为对于我的用途,我已经知道这一切。这些东西是 .bin 文件,但它们都是 tiff 中相同的单页 jpeg,我需要一种方法以浏览器不讨厌的格式快速提供它们。这运行速度足够快,可以即时提供服务。有没有更好的办法?可能,但这有效,自包含,复制和粘贴,并且对于需要编辑它的任何人来说都是完全有意义的。

<cfscript>
strFileName = "test.tiff";
blnOutputImageToBrowser = true;
blnSaveToFile = true;
strSaveFile = GetDirectoryFromPath(GetCurrentTemplatePath())&"test.jpg"

imgByteArray = FileReadBinary(strFileName);
//Convert to HEX String
hexString = binaryEncode(imgByteArray,"hex"); //Convert binary to HEX String, so we can pattern search it
//Set HEX Length
hexLength = arraylen(imgByteArray);

//Find Start of JPG Data in HEX String
jpegStartHEX = find("FFD8FF",hexString);
jpegStartBIN = (jpegStartHEX-1)/2; //-1 because CF arrays start on 1 and everyone else starts on 1. /2 because the HEX string positions are double the byte array positions
objByteBuffer = CreateObject("java","java.nio.ByteBuffer"); //Init JAVA byte buffer class for us to use later (this makes it go faster than trying to convert the hex string back to binary)

//Find Stop of JPG Data
jpegStopHEX = 0;
jpegStopBIN = 0;
intSearchIDX = jpegStartHEX+6; //Might as well start after the JPEG start block
blnStop = false;
while (intSearchIDX < len(hexString) && jpegStopHEX == 0 && !blnStop) {
    newIDX = find("FFD9",hexString,intSearchIDX);
    if (newIDX == 0) {
        blnStop=true;
    }
    else {
        if (newIDX%2 == 0) { //bad search try again (due to indexing in CF starting on 1 instead of 0, the even numbers are in between hex code [they are pairs like 00 and FF])
            intSearchIDX = newIDX+1;
        }
        else { //Found ya
            jpegStopHEX = newIDX;
            blnStop=true;
        }
    }
}
jpegStopBIN = (jpegStopHEX-1)/2; //-1 because CF arrays start on 1 and everyone else starts on 1. /2 because the HEX string positions are double the byte array positions

//Dump JPG Binary into ByteArray from the start and stop positions we discovered
jpegLengthBIN = jpegStopBIN+2-jpegStartBIN;
objBufferImage = objByteBuffer.Allocate(JavaCast( "int", jpegLengthBIN ));
objBufferImage.Put(imgByteArray,JavaCast( "int", jpegStartBIN ),JavaCast( "int", jpegLengthBIN ));

if (blnSaveToFile) { //Dump byte array into test file
    fileWrite(strSaveFile,objBufferImage.Array());
}
if (blnOutputImageToBrowser) {
    img = ImageNew( objBufferImage.Array() );
    ImageResize(img,"1200","","highestPerformance"); //Because we might as well show an example of resizing
    outputImage(toBinary(toBase64(img))); //You could skip loading the byte array as an image object and just plop the binary in directly if you don't need to manipulate it any
}
</cfscript>
<cffunction name="outputImage" returntype="void">
    <cfargument name="binInput" type="binary">
    <cfcontent variable="#binInput#" type="image/png" reset="true" />
    <cfreturn>
</cffunction>
于 2021-05-29T20:12:11.453 回答