Skip navigation
Currently Being Moderated

cfimage inside cfdocument problem

Apr 4, 2012 9:25 AM

Tags: #cfdocument #cfimage

Very strange, but repeatable issue I've run into.  I'm using the barbecue Java barcode generator library to generate code128 compliant barcodes which are then handed to cfimage writeToBrowser to finally end up with printable packing/mailing labels.  When rendered to screen, everything works perfectly, but as soon as I wrap it in a cfdocument tag, so that we can generate as a pdf for printing on a label printer, I'm ending up with the wrong image on the wrong label in a few cases.  It's always the same records that end up reusing an image from an earlier record (and always the same earlier record).  I can check in the ColdFusion8\tmpCache\CFFileServlet\_cf_image folder and see that all the correct images were created by the cfimage tag, but for whatever reason, some of the images don't make it into the pdf, but are replaced by a different barcode from an earlier record.  I can't see any commonality between the two records and if I intentionally remove the earlier record from the query, the proper barcode shows up.

 

So, any ideas about where to go from here?  Anybody know anything about how cfdocument pulls in images and if there is any kind of caching or prechecking of the images before rendering.  I actually checked to make sure the two files didn't have the same MD5 sum to see if there was something happening there where CF thinks it's the same image.  They were not the same.

 

I've tried this on two CF 8.01 boxes with the same result.  Always the same records, same images, same problem, even if I limit the query to only the two problem records.  I'm totally stumped.  Anybody?

 
Replies
  • Currently Being Moderated
    Apr 4, 2012 9:46 AM   in reply to jeff.c

    Can you post your code?

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 4, 2012 11:06 AM   in reply to jeff.c

    I notice there is lot of looping and grouping going on. Any chance it is related? If you output the "bcText" at each step (inside the pdf) is the value correct? Also, for grins you might output the image URL and confirm whether it is repeating, or the "bcText" is repeating.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 4, 2012 12:57 PM   in reply to jeff.c

    jeff.c wrote:

     

    Not sure it's helpful, but here's the code, at least the relevant parts.  As I said, I've confirmed that this is all doing what it's supposed to and if I take off the cfdocument, it renders to the screen perfectly every time.

     

    <cfdocument format="PDF" pagewidth="4" pageheight="6.0" pagetype="CUSTOM" margintop="0.17" marginbottom="0.05" marginleft="0.17" marginright="0.17">

     

    <cfset labelCounter = 1 />

    <cfoutput query="qryGetShippingLabelData" group="Lab_Code">

      <!--- Do some stuff --->

      <cfoutput group="shipGroup">

        <cfloop from=1 to=#numLabels# index="i">

          <cfset bcText = "" />

          <cfif labelCounter NEQ 1><cfdocumentitem type="pagebreak" /></cfif>

          #labelHead#

          <cfoutput>

            <cfset bcText = bcText & numberFormat(study_id,"00000") & iif(singleSampleBox,1,numSamples) />

          </cfoutput>

                                  <cfset bcText = numberFormat(Lab_ID,"00000") & bcText />

                                  <p><cfimage action="writeToBrowser" source="#getCode128(bcText)#" /></p>

          #labelFoot#

          <cfset labelCounter = labelCounter + 1 />

        </cfloop>

      </cfoutput>

    </cfoutput>

     

    </cfdocument>

    The code needs improving. The PDF may render correctly after that, who knows.

     

    1) You have, at the centre of it all, code that is within 3 loops. It will help to scope the variables, such as qryGetShippingLabelData.x and shipGroup.y.

     

    2) The cfouput tag in the following stretch is unnecessarily in the way:

     

          <cfoutput>

            <cfset bcText = bcText & numberFormat(study_id,"00000") & iif(singleSampleBox,1,numSamples) />

          </cfoutput>

     

    Then again, if you drop this cfoutput tag you will get:

     

    <cfset bcText = bcText & numberFormat(study_id,"00000") & iif(singleSampleBox,1,numSamples) />

    <cfset bcText = numberFormat(Lab_ID,"00000") & bcText />

     

    That looks like repetition to me. At least, it doesn't appear to me that that was the intention.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 4, 2012 1:20 PM   in reply to jeff.c

              function getCode128 (data)           {

                   barcode = bbq.createCode128(data);

                   barcode.setBarWidth( 1 );


    After seeing the function code, first thing I would recommend is VAR scoping all of the function local variables. Then try it again.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 4, 2012 1:20 PM   in reply to jeff.c

    It is clear you are dealing with just 2 images in this simpler example. Please just bear with me and explain what problem you reproduce with the 2 images.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 4, 2012 1:26 PM   in reply to -==cfSearching==-

    -==cfSearching==- wrote:

     

              function getCode128 (data)           {

                   barcode = bbq.createCode128(data);

                   barcode.setBarWidth( 1 );


    After seeing the function code, first thing I would recommend is VAR scoping all of the function local variables. Then try it again.

    In fact, I would VAR newImg and barcodeImage as well.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 4, 2012 2:03 PM   in reply to BKBK

    In fact, I would VAR newImg and barcodeImage as well.

     

    Yep, that is why I said all function local variables. I was only trying to highlight the fact that were no VAR scope declarations at the top of the function. (I did not look over the  variable names in detail :-)

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 5, 2012 1:14 AM   in reply to -==cfSearching==-

    -==cfSearching==- wrote:

     

    In fact, I would VAR newImg and barcodeImage as well.

     

    Yep, that is why I said all function local variables. I was only trying to highlight the fact that were no VAR scope declarations at the top of the function. (I did not look over the  variable names in detail :-)

    Nice of you, but you needn't explain. It was an oversight. I was already thinking VAR myself, and so just skimmed 'barcode' and 'VAR'. Sorry.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 5, 2012 1:52 AM   in reply to jeff.c

    jeff.c wrote:

     

    Nope.  All grouping and loops are necessary based on the shape of the data and the required output based on the number of labels required for each row in the source query.  I'm doing something at each stage of the grouping (although I removed some of that because it wasn't really relevant to the question) to build these labels.  I'm quite confident that the grouping and looping is correct and not part of the problem.  In fact, I've built a simple test page that removes all the complexity of my grouping and query and will still produce this problem (although you have to have the barbecue library to test).

     

    <cfset bbq = createObject("java", "net.sourceforge.barbecue.BarcodeFactory") />

    <cfset ih = createObject("java", "net.sourceforge.barbecue.BarcodeImageHandler") />

     

    <cfscript>

              function getCode128 (data)           {

        barcode = bbq.createCode128(data);

        barcode.setBarWidth( 1 );

        barcode.setBarHeight( 50 );

        barcode.setDrawingText( false );

        barcode.setDrawingQuietSection( false );

        barcode.setResolution( 200 );

     

        newImg = ih.getImage( barcode );

        barcodeImage = ImageNew(newImg);

     

        return barcodeImage;

              }

    </cfscript>


    <cfset list = "00413001811,00403001811" />

     

    <cfdocument format="pdf" pagewidth="4" pageheight="6.0" pagetype="CUSTOM" margintop="0.17" marginbottom="0.05" marginleft="0.17" marginright="0.17">

    <html>

              <head>

              </head>

              <body>

                        <cfloop list="#list#" index="i">

                                  <p><cfimage action="writetobrowser" source="#getCode128("#i#")#" /></p>

                                  <p><cfoutput>#i#</cfoutput></p>

                        </cfloop>

              </body>

    </html>

    </cfdocument>

    The question remains why it fails with, but works without, cfdocument. Does cfdocument introduce a new page context? I wonder. If so, then what -==cfSearching==- said about varring the variables would immediately make sense. Unvarred variables belong to the context of the current page.

     

    Another issue may arise from  <cfloop list="#list#" index="i">. You implicitly assume that ColdFusion will process the list elements in the exact order in which they appear in the list. I suspect ColdFusion wont always. It may internally apply some kind of sorting, and begin with the last element in the list.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 5, 2012 5:07 AM   in reply to BKBK

    @BKBK: I don't want to sidetrack the thread here, but that last statement about assuming the order of processing on a list in the CFLOOP tag is pretty concerning. I've never witnessed any behavior other than processing the list exactly in the order provided, and I have a hard time believing that we've just been lucky for 15 years. That /is/ in fact a key assumption in lots of CFML code. Do you have a basis for that statement, either in the docs or repeatable behavior in code you can share? To have them processed in anything other than the order provided seems so counterintuitive as to render the whole concept of using a list to drive any sort of iteration as basically useless...

     

    --

    /ron

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 5, 2012 8:55 AM   in reply to Ron.Stewart

    cf_ron wrote:

     

    @BKBK: I don't want to sidetrack the thread here, but that last statement about assuming the order of processing on a list in the CFLOOP tag is pretty concerning. I've never witnessed any behavior other than processing the list exactly in the order provided, and I have a hard time believing that we've just been lucky for 15 years. That /is/ in fact a key assumption in lots of CFML code. Do you have a basis for that statement, either in the docs or repeatable behavior in code you can share? To have them processed in anything other than the order provided seems so counterintuitive as to render the whole concept of using a list to drive any sort of iteration as basically useless...

    No need worrying or running for the hills, Ron. I wrote that piece without due attention. What I omitted says more about what I was thinking.

     

    I was trying to puzzle out why ColdFusion would start looping a list at position 2, or at any position other than 1 for that matter. What I wished I had said follows.

     

    Another issue may arise from  <cfloop list="#list#" index="i">. If the list is indeed as it appears in the code, then there is no issue. However, suppose the list was comprised of the keys of a struct. That is, the list of keys is structKeyList(theStruct), and you've stated the list in the code as a simplified test page. You implicitly assume that ColdFusion will process the list elements in the exact order in which they appear in the list. I suspect ColdFusion wont always. It may internally apply some kind of sorting, and begin with the last element in the list.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 5, 2012 9:17 AM   in reply to BKBK

    @BKBK: No worries here. If I get the gist of your comment, it was centered around the question of whether the list itself was ordered as expected rather than whether the list was iterated over in order from first to last?

     

    --

    /ron

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 5, 2012 10:28 AM   in reply to Ron.Stewart

    jeff.c sent me a copy of his code and image files referenced above, and I have duplicated this behavior on a fully-updated 9.01 box. Same exact behavior, so it is clearly not something unique to 8.01 or something that has been patched in 9.x. I have a CF10 box I will try this on in a bit, as well...

     

    Update: also does not work on CF10 beta -- same behavior.

     

    --

    /ron

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 5, 2012 12:10 PM   in reply to Ron.Stewart

    I, too, have tested on CF 10 Beta. I painted a stripe across one of the barcodes for easier recognition.

    _cfimg6949878617879408634.PNG                              _cfimg300382366701370250.PNG

    (respectively: _cfimg6949878617879408634.png, _cfimg300382366701370250.png)

     

    Then I ran the following code, first, without cfdocument, then with cfdocument.

     

    <!---<cfdocument format="pdf" pagewidth="4" pageheight="6.0" pagetype="CUSTOM" margintop="0.17" marginbottom="0.05" marginleft="0.17" marginright="0.17">--->

    <html>

    <head></head>

    <body>

      <div><img id="_cfimg6949878617879408634" src="_cfimg6949878617879408634.png" /></div>

      <p>00413001811</p>

    <div><img id="_cfimg300382366701370250" src="_cfimg300382366701370250.png" /></div>

      <p>00403001811</p>

    </body>

    </html>

    <!---</cfdocument>--->

     

    In both cases, the result was:

     

    result.png

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 6, 2012 12:12 PM   in reply to Ron.Stewart

    (Update:  Grr... I just love this forum software.)

     

    I think I was finally able to reproduce the behavior on 9.01. But it only happens when setDrawingText(..) is false.

     

     

     

    <cfscript>

        /* deliberately refactored to eliminate  var scoping issues as a possible cause */

        function getCode128 ( data, hideText )           {

            var bbq = createObject("java", "net.sourceforge.barbecue.BarcodeFactory");

            var ih = createObject("java", "net.sourceforge.barbecue.BarcodeImageHandler");

            var barcode = bbq.createCode128( arguments.data );

     

            barcode.setBarWidth( 1 );

            barcode.setBarHeight( 50 );

            barcode.setDrawingQuietSection( false );

            barcode.setResolution( 200 );

            if ( structKeyExists(arguments, "hideText") and arguments.hideText ) {

                barcode.setDrawingText( false );

            }

     

            return ImageNew(ih.getImage( barcode ));

        }

    </cfscript>

     

    <cfset numbers = ["00413001811","00403001811","00413001811","00403001811"] />

    <cfdocument format="pdf">

        <cfloop from="1" to="#arrayLen(numbers)#" index="i">

            <cfset imgText  = numbers[i] />

            <cfset hideText = i lte 2 />

            <cfoutput>

               [#i#] #imgText# <cfimage action="writetobrowser" source="#getCode128(imgText, hideText)#" /><br />

            </cfoutput>

        </cfloop>

    </cfdocument>

     

     

     

    jeff.c wrote:

    maybe at least an acknowledgement from an Adobe rep that there may be an issue here?

     

    Well these are user-to-user forums. If you want to speak with an adobe representative, you need to use official channels. (While I have seen an occaisional comment here and there, it is rare. So it is extremely unlikely you would get a response from an Adobe employee here).

     

    Message was edited by: -==cfSearching==-

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 5, 2012 3:38 PM   in reply to jeff.c

    I'm not comfortable just including the barcode text though and hoping

    that it

     

    solves the problem.  In my mind, it's still possible and likely

    that the underlying

     

    engine could still be confused in comparing images

     

    We are on the same page there. I would not rely on it either. It just helps illustrate the issue a bit more clearly.

     

     

    -Leigh

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 6, 2012 3:34 AM   in reply to -==cfSearching==-

    Leigh, you might want to change the text rendered red in your code to quoted strings.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 6, 2012 4:09 AM   in reply to jeff.c

    jeff.c wrote:

     

    @BKBK - Your test would validate my hypothesis that cfdocument is doing something to look at the images and determine if they have already been loaded and, if so, reuse the already loaded image.  Whatever that comparison is based on is treating these two images as the same image.  Since you've altered the original image, I'm not surprised that it now works correctly, but if you go back to the original images, unaltered, I'm quite confident you'll see the same behavior.  For what it's worth, I compared the MD5 sum of the two images and they do not match.

    Your confidence is justified! I reran my above test with the original image. I did reproduce the issue.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 6, 2012 6:31 AM   in reply to -==cfSearching==-

    I think I was finally able to reproduce the behavior on 9.01. But it only happens when setDrawingText(..) is false.

    I further tested the same code on CF 10 Beta. Irrespective of whether I used barcode.setDrawingText(false) or barcode.setDrawingText(true), I did reproduce the issue. Also, when I changed the order of the numbers from ["00413001811","00403001811"] to ["00403001811","00413001811"], the barcode image changed, but the issue persisted.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 6, 2012 12:11 PM   in reply to BKBK

    Leigh, you might want to change the text rendered red in your code to quoted strings.

     

    Yes, you are right but that is courtesy of this lovely forum software ;-). After it mangled the original (with quotes) three times, I finally gave up. I am not sure it lets you edit posts after other responses are added. I will check the web interface later.

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 7, 2012 12:56 AM   in reply to jeff.c

    With Jeff.c's earlier images:

     

    _cfimg6949878617879408634.PNG_cfimg6949878617879408634.png

     

    _cfimg300382366701370250.PNG_cfimg300382366701370250.png

     

    I used the following simplified code, and tried every which way to not reproduce the cfdocument problem. For example, I displayed the images on a separate CFM page, downloaded the page by cfhttp, and used cfdocument to display the page content. All my attempts failed. The problem persists.

     

    <cfdocument format="pdf">

    <p><img src="_cfimg6949878617879408634.png"></p>

    <p><img src="_cfimg300382366701370250.png"></p>

    </cfdocument>

     
    |
    Mark as:
  • Currently Being Moderated
    Apr 9, 2012 8:18 AM   in reply to jeff.c

    jeff.c wrote:

     

    I did get a reply from Rupesh Kumar (Adobe CF Engineer) from a question I submitted on his ColdFused blog where he stated that the thought this had been fixed in 9.01.  I assured him it had not and pointed him to the bug I filed.

     

    Well at least now you have a firm confirmation of your suspicion it is a it is a bug. Since it sounds like a known issue, did he mention anything about cause or possible work-arounds?

     
    |
    Mark as:
  • Currently Being Moderated
    Aug 31, 2012 12:47 PM   in reply to -==cfSearching==-

    I am still running into this issue in cf 9.01 as well..... so frustrating to have to use lossy jpegs to render my bar codes into a pdf.

     

    Thanks for incredible troubleshooting and follow up Jeff, you are my hero.

     
    |
    Mark as:
  • Currently Being Moderated
    Nov 5, 2012 6:36 AM   in reply to k1n6

    I'm having the same problem. Before read this topic, I already knew that when you setDrawingText(false) the problem happens and I still need to solve this problem too. I wonder stop use barbecue and try use ".ttf" fonts. Somebody used ".ttf" fonts and got a good result?

     
    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (0)

Answers + Points = Status

  • 10 points awarded for Correct Answers
  • 5 points awarded for Helpful Answers
  • 10,000+ points
  • 1,001-10,000 points
  • 501-1,000 points
  • 5-500 points