2

I have a new CF18 server and I'm getting some errors reading and converting some old images that were readable on my previous CF11 server. FYI GetReadableImageFormats results in "BMP,GIF,JPEG,JPEG 2000,JPEG2000,JPG,PNG,PNM,RAW,TIF,TIFF,WBMP"

Normally I read the files as a Binary and put it into memory for manipulation

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

This now results in an error: "An exception occurred while trying to read the image. No SOF segment in stream"

Reading the file with action="read" and dumping the left(binImage, 999) results: "...2015:10:07 17:46:58 Kofax standard Multi-Page TIFF Storage Filter v3.03.000,..."

Then I tried reading it into java using:

<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>

Which yields an error: "Decoding of old style JPEG-in-TIFF data is not supported."

I found this... Decoding of old style JPEG-in-TIFF data is not supported

Do you think using TwelveMonkeys ImageIO the best path to follow for my issue?

UPDATE: Based on the suggestion that there is an invalid marker 0xFF9E I tried the following:

<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) returns "NO" and the "No SOF segment in stream" error persists. I looped over the hexEncoding and found the FF9E string 23x. I've never edited raw image code so I'm not sure my replace is correct.

Edit: At this point I'm fairly certain my Search and Replace hexEncoding, 'FF9E', 'FFE9' logic is flawed. there is no occurance of 0xff9e in the binaryEncoded binImage.

Stephen Sharpe
  • 167
  • 1
  • 8
  • Just found this issue: https://github.com/haraldk/TwelveMonkeys/issues/481 *It contains an unknown JPEG marker FF9E (not FFE9)* – Bernhard Döbler Jan 03 '20 at 02:27
  • Good lead thanks! I'm looking into the suggestion at the end of the linked thread... "If you need to read this file, you can strip out the 0xFF9E segment, and it will work fine." – Stephen Sharpe Jan 03 '20 at 16:32

1 Answers1

0

This was driving me nuts. I tried everything I could find short of installing extra JAVA libraries or routing it through other executables to make the conversion. In my case there is only one JPEG in a TIFF, so I wrote something that literally grabs the binary data for the JPEG out of the TIFF (doesn't account for pages) and serves it up. Once you have the binary of the JPEG you can write it to a file, do conversions on it, even stream it direct to the browser. Here ya go future people who need this. I didn't write it to do pages or detect what kind of tiff it is since for my uses I already know all that. These things are .bin files, but they are all the same single page jpeg in a tiff and I needed a way to serve them up quickly in a format that browsers don't hate. This runs fast enough to be served up on the fly. Is there a better way? Probably, but this works, self contained, copy and paste, and makes complete sense to anyone that needs to edit it.

<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>