1<!--- 2 image.cfc v2.19, written by Rick Root (rick@webworksllc.com) 3 Derivative of work originally done originally by James Dew. 4 5 Related Web Sites: 6 - http://www.opensourcecf.com/imagecfc (home page) 7 - http://www.cfopen.org/projects/imagecfc (project page) 8 9 LICENSE 10 ------- 11 Copyright (c) 2007, Rick Root <rick@webworksllc.com> 12 All rights reserved. 13 14 Redistribution and use in source and binary forms, with or 15 without modification, are permitted provided that the 16 following conditions are met: 17 18 - Redistributions of source code must retain the above 19 copyright notice, this list of conditions and the 20 following disclaimer. 21 - Redistributions in binary form must reproduce the above 22 copyright notice, this list of conditions and the 23 following disclaimer in the documentation and/or other 24 materials provided with the distribution. 25 - Neither the name of the Webworks, LLC. nor the names of 26 its contributors may be used to endorse or promote products 27 derived from this software without specific prior written 28 permission. 29 30 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 31 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 32 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 33 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 34 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 35 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 36 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 37 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 38 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 40 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 41 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 42 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 43 44 ============================================================ 45 This is a derivative work. Following is the original 46 Copyright notice. 47 ============================================================ 48 49 Copyright (c) 2004 James F. Dew <jdew@yggdrasil.ca> 50 51 Permission to use, copy, modify, and distribute this software for any 52 purpose with or without fee is hereby granted, provided that the above 53 copyright notice and this permission notice appear in all copies. 54 55 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 56 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 57 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 58 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 59 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 60 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 61 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 62---> 63<!--- 64 SPECIAL NOTE FOR HEADLESS SYSTEMS 65 --------------------------------- 66 If you get a "cannot connect to X11 server" when running certain 67 parts of this component under Bluedragon (Linux), you must 68 add "-Djava.awt.headless=true" to the java startup line in 69 <bluedragon>/bin/StartBluedragon.sh. This isssue is discussed 70 in the Bluedragon Installation Guide section 3.8.1 for 71 Bluedragon 6.2.1. 72 73 Bluedragon may also report a ClassNotFound exception when trying 74 to instantiate the java.awt.image.BufferedImage class. This is 75 most likely the same issue. 76 77 If you get "This graphics environment can be used only in the 78 software emulation mode" when calling certain parts of this 79 component under Coldfusion MX, you should refer to Technote 80 ID #18747: http://www.macromedia.com/go/tn_18747 81---> 82 83<cfcomponent displayname="Image"> 84 85<cfset variables.throwOnError = "Yes"> 86<cfset variables.defaultJpegCompression = "90"> 87<cfset variables.interpolation = "bicubic"> 88<cfset variables.textAntiAliasing = "Yes"> 89<cfset variables.tempDirectory = "#expandPath(".")#"> 90 91<cfset variables.javanulls = "no"> 92<cftry> 93 <cfset nullvalue = javacast("null","")> 94 <cfset variables.javanulls = "yes"> 95 <cfcatch type="any"> 96 <cfset variables.javanulls = "no"> 97 <!--- javacast null not supported, so filters won't work ---> 98 </cfcatch> 99</cftry> 100<!--- 101<cfif javanulls> 102 <cfset variables.blurFilter = createObject("component","blurFilter")> 103 <cfset variables.sharpenFilter = createObject("component","sharpenFilter")> 104 <cfset variables.posterizeFilter = createObject("component","posterizeFilter")> 105</cfif> 106---> 107 108<cfset variables.Math = createobject("java", "java.lang.Math")> 109<cfset variables.arrObj = createobject("java", "java.lang.reflect.Array")> 110<cfset variables.floatClass = createobject("java", "java.lang.Float").TYPE> 111<cfset variables.intClass = createobject("java", "java.lang.Integer").TYPE> 112<cfset variables.shortClass = createobject("java", "java.lang.Short").TYPE> 113 114<cffunction name="getImageInfo" access="public" output="true" returntype="struct" hint="Rotate an image (+/-)90, (+/-)180, or (+/-)270 degrees."> 115 <cfargument name="objImage" required="yes" type="Any"> 116 <cfargument name="inputFile" required="yes" type="string"> 117 118 <cfset var retVal = StructNew()> 119 <cfset var loadImage = StructNew()> 120 <cfset var img = ""> 121 122 <cfset retVal.errorCode = 0> 123 <cfset retVal.errorMessage = ""> 124 125 <cfif inputFile neq ""> 126 <cfset loadImage = readImage(inputFile, "NO")> 127 <cfif loadImage.errorCode is 0> 128 <cfset img = loadImage.img> 129 <cfelse> 130 <cfset retVal = throw(loadImage.errorMessage)> 131 <cfreturn retVal> 132 </cfif> 133 <cfset retVal.metaData = getImageMetadata(loadImage.inFile)> 134 <cfelse> 135 <cfset img = objImage> 136 <cfset retVal.metadata = getImageMetadata("")> 137 </cfif> 138 <cftry> 139 <cfset retVal.width = img.getWidth()> 140 <cfset retVal.height = img.getHeight()> 141 <cfset retVal.colorModel = img.getColorModel().toString()> 142 <cfset retVal.colorspace = img.getColorModel().getColorSpace().toString()> 143 <cfset retVal.objColorModel = img.getColorModel()> 144 <cfset retVal.objColorspace = img.getColorModel().getColorSpace()> 145 <cfset retVal.sampleModel = img.getSampleModel().toString()> 146 <cfset retVal.imageType = img.getType()> 147 <cfset retVal.misc = img.toString()> 148 <cfset retVal.canModify = true> 149 <cfreturn retVal> 150 <cfcatch type="any"> 151 <cfset retVal = throw( "#cfcatch.message#: #cfcatch.detail#")> 152 <cfreturn retVal> 153 </cfcatch> 154 </cftry> 155</cffunction> 156 157<cffunction name="getImageMetadata" access="private" output="false" returntype="query"> 158 <cfargument name="inFile" required="yes" type="Any"><!--- java.io.File ---> 159 160 <cfset var retQry = queryNew("dirName,tagName,tagValue")> 161 <cfset var paths = arrayNew(1)> 162 <cfset var loader = ""> 163 <cfset var JpegMetadatareader = ""> 164 <cfset var myMetadata = ""> 165 <cfset var directories = ""> 166 <cfset var currentDirectory = ""> 167 <cfset var tags = ""> 168 <cfset var currentTag = ""> 169 <cfset var tagName = ""> 170 171 <cftry> 172 <cfscript> 173 paths = arrayNew(1); 174 paths[1] = expandPath("metadata-extractor-2.3.1.jar"); 175 loader = createObject("component", "javaloader.JavaLoader").init(paths); 176 177 //at this stage we only have access to the class, but we don't have an instance 178 JpegMetadataReader = loader.create("com.drew.imaging.jpeg.JpegMetadataReader"); 179 180 myMetaData = JpegMetadataReader.readMetadata(inFile); 181 directories = myMetaData.getDirectoryIterator(); 182 while (directories.hasNext()) { 183 currentDirectory = directories.next(); 184 tags = currentDirectory.getTagIterator(); 185 while (tags.hasNext()) { 186 currentTag = tags.next(); 187 if (currentTag.getTagName() DOES NOT CONTAIN "Unknown") { //leave out the junk data 188 queryAddRow(retQry); 189 querySetCell(retQry,"dirName",replace(currentTag.getDirectoryName(),' ','_','ALL')); 190 tagName = replace(currentTag.getTagName(),' ','','ALL'); 191 tagName = replace(tagName,'/','','ALL'); 192 querySetCell(retQry,"tagName",tagName); 193 querySetCell(retQry,"tagValue",currentTag.getDescription()); 194 } 195 } 196 } 197 return retQry; 198 </cfscript> 199 <cfcatch type="any"> 200 <cfreturn retQry /> 201 </cfcatch> 202 </cftry> 203</cffunction> 204 205<cffunction name="flipHorizontal" access="public" output="true" returntype="struct" hint="Flip an image horizontally."> 206 <cfargument name="objImage" required="yes" type="Any"> 207 <cfargument name="inputFile" required="yes" type="string"> 208 <cfargument name="outputFile" required="yes" type="string"> 209 <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> 210 211 <cfreturn flipflop(objImage, inputFile, outputFile, "horizontal", jpegCompression)> 212</cffunction> 213 214<cffunction name="flipVertical" access="public" output="true" returntype="struct" hint="Flop an image vertically."> 215 <cfargument name="objImage" required="yes" type="Any"> 216 <cfargument name="inputFile" required="yes" type="string"> 217 <cfargument name="outputFile" required="yes" type="string"> 218 <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> 219 220 <cfreturn flipflop(objImage, inputFile, outputFile, "vertical", jpegCompression)> 221</cffunction> 222 223<cffunction name="scaleWidth" access="public" output="true" returntype="struct" hint="Scale an image to a specific width."> 224 <cfargument name="objImage" required="yes" type="Any"> 225 <cfargument name="inputFile" required="yes" type="string"> 226 <cfargument name="outputFile" required="yes" type="string"> 227 <cfargument name="newWidth" required="yes" type="numeric"> 228 <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> 229 230 <cfreturn resize(objImage, inputFile, outputFile, newWidth, 0, "false", "false", jpegCompression)> 231</cffunction> 232 233<cffunction name="scaleHeight" access="public" output="true" returntype="struct" hint="Scale an image to a specific height."> 234 <cfargument name="objImage" required="yes" type="Any"> 235 <cfargument name="inputFile" required="yes" type="string"> 236 <cfargument name="outputFile" required="yes" type="string"> 237 <cfargument name="newHeight" required="yes" type="numeric"> 238 <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> 239 240 <cfreturn resize(objImage, inputFile, outputFile, 0, newHeight, "false", "false", jpegCompression)> 241</cffunction> 242 243<cffunction name="resize" access="public" output="true" returntype="struct" hint="Resize an image to a specific width and height."> 244 <cfargument name="objImage" required="yes" type="Any"> 245 <cfargument name="inputFile" required="yes" type="string"> 246 <cfargument name="outputFile" required="yes" type="string"> 247 <cfargument name="newWidth" required="yes" type="numeric"> 248 <cfargument name="newHeight" required="yes" type="numeric"> 249 <cfargument name="preserveAspect" required="no" type="boolean" default="FALSE"> 250 <cfargument name="cropToExact" required="no" type="boolean" default="FALSE"> 251 <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> 252 253 <cfset var retVal = StructNew()> 254 <cfset var loadImage = StructNew()> 255 <cfset var saveImage = StructNew()> 256 <cfset var at = ""> 257 <cfset var op = ""> 258 <cfset var w = ""> 259 <cfset var h = ""> 260 <cfset var scale = 1> 261 <cfset var scaleX = 1> 262 <cfset var scaleY = 1> 263 <cfset var resizedImage = ""> 264 <cfset var rh = getRenderingHints()> 265 <cfset var specifiedWidth = arguments.newWidth> 266 <cfset var specifiedHeight = arguments.newHeight> 267 <cfset var imgInfo = ""> 268 <cfset var img = ""> 269 <cfset var cropImageResult = ""> 270 <cfset var cropOffsetX = ""> 271 <cfset var cropOffsetY = ""> 272 273 <cfset retVal.errorCode = 0> 274 <cfset retVal.errorMessage = ""> 275 276 <cfif inputFile neq ""> 277 <cfset loadImage = readImage(inputFile, "NO")> 278 <cfif loadImage.errorCode is 0> 279 <cfset img = loadImage.img> 280 <cfelse> 281 <cfset retVal = throw(loadImage.errorMessage)> 282 <cfreturn retVal> 283 </cfif> 284 <cfelse> 285 <cfset img = objImage> 286 </cfif> 287 <cfif img.getType() eq 0> 288 <cfset img = convertImageObject(img,img.TYPE_3BYTE_BGR)> 289 </cfif> 290 <cfscript> 291 resizedImage = CreateObject("java", "java.awt.image.BufferedImage"); 292 at = CreateObject("java", "java.awt.geom.AffineTransform"); 293 op = CreateObject("java", "java.awt.image.AffineTransformOp"); 294 295 w = img.getWidth(); 296 h = img.getHeight(); 297 298 if (preserveAspect and cropToExact and newHeight gt 0 and newWidth gt 0) 299 { 300 if (w / h gt newWidth / newHeight){ 301 newWidth = 0; 302 } else if (w / h lt newWidth / newHeight){ 303 newHeight = 0; 304 } 305 } else if (preserveAspect and newHeight gt 0 and newWidth gt 0) { 306 if (w / h gt newWidth / newHeight){ 307 newHeight = 0; 308 } else if (w / h lt newWidth / newHeight){ 309 newWidth = 0; 310 } 311 } 312 if (newWidth gt 0 and newHeight eq 0) { 313 scale = newWidth / w; 314 w = newWidth; 315 h = round(h*scale); 316 } else if (newHeight gt 0 and newWidth eq 0) { 317 scale = newHeight / h; 318 h = newHeight; 319 w = round(w*scale); 320 } else if (newHeight gt 0 and newWidth gt 0) { 321 w = newWidth; 322 h = newHeight; 323 } else { 324 retVal = throw( retVal.errorMessage); 325 return retVal; 326 } 327 resizedImage.init(javacast("int",w),javacast("int",h),img.getType()); 328 329 w = w / img.getWidth(); 330 h = h / img.getHeight(); 331 332 333 334 op.init(at.getScaleInstance(javacast("double",w),javacast("double",h)), rh); 335 // resizedImage = op.createCompatibleDestImage(img, img.getColorModel()); 336 op.filter(img, resizedImage); 337 338 imgInfo = getimageinfo(resizedImage, ""); 339 if (imgInfo.errorCode gt 0) 340 { 341 return imgInfo; 342 } 343 344 cropOffsetX = max( Int( (imgInfo.width/2) - (newWidth/2) ), 0 ); 345 cropOffsetY = max( Int( (imgInfo.height/2) - (newHeight/2) ), 0 ); 346 // There is a chance that the image is exactly the correct 347 // width and height and don't need to be cropped 348 if 349 ( 350 preserveAspect and cropToExact 351 and 352 (imgInfo.width IS NOT specifiedWidth OR imgInfo.height IS NOT specifiedHeight) 353 ) 354 { 355 // Get the correct offset to get the center of the image 356 cropOffsetX = max( Int( (imgInfo.width/2) - (specifiedWidth/2) ), 0 ); 357 cropOffsetY = max( Int( (imgInfo.height/2) - (specifiedHeight/2) ), 0 ); 358 359 cropImageResult = crop( resizedImage, "", "", cropOffsetX, cropOffsetY, specifiedWidth, specifiedHeight ); 360 if ( cropImageResult.errorCode GT 0) 361 { 362 return cropImageResult; 363 } else { 364 resizedImage = cropImageResult.img; 365 } 366 } 367 if (outputFile eq "") 368 { 369 retVal.img = resizedImage; 370 return retVal; 371 } else { 372 saveImage = writeImage(outputFile, resizedImage, jpegCompression); 373 if (saveImage.errorCode gt 0) 374 { 375 return saveImage; 376 } else { 377 return retVal; 378 } 379 } 380 </cfscript> 381</cffunction> 382 383<cffunction name="crop" access="public" output="true" returntype="struct" hint="Crop an image."> 384 <cfargument name="objImage" required="yes" type="Any"> 385 <cfargument name="inputFile" required="yes" type="string"> 386 <cfargument name="outputFile" required="yes" type="string"> 387 <cfargument name="fromX" required="yes" type="numeric"> 388 <cfargument name="fromY" required="yes" type="numeric"> 389 <cfargument name="newWidth" required="yes" type="numeric"> 390 <cfargument name="newHeight" required="yes" type="numeric"> 391 <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> 392 393 <cfset var retVal = StructNew()> 394 <cfset var loadImage = StructNew()> 395 <cfset var saveImage = StructNew()> 396 <cfset var croppedImage = ""> 397 <cfset var rh = getRenderingHints()> 398 <cfset var img = ""> 399 400 <cfset retVal.errorCode = 0> 401 <cfset retVal.errorMessage = ""> 402 403 <cfif inputFile neq ""> 404 <cfset loadImage = readImage(inputFile, "NO")> 405 <cfif loadImage.errorCode is 0> 406 <cfset img = loadImage.img> 407 <cfelse> 408 <cfset retVal = throw(loadImage.errorMessage)> 409 <cfreturn retVal> 410 </cfif> 411 <cfelse> 412 <cfset img = objImage> 413 </cfif> 414 <cfif img.getType() eq 0> 415 <cfset img = convertImageObject(img,img.TYPE_3BYTE_BGR)> 416 </cfif> 417 <cfscript> 418 if (fromX + newWidth gt img.getWidth() 419 OR 420 fromY + newHeight gt img.getHeight() 421 ) 422 { 423 retval = throw( "The cropped image dimensions go beyond the original image dimensions."); 424 return retVal; 425 } 426 croppedImage = img.getSubimage(javaCast("int", fromX), javaCast("int", fromY), javaCast("int", newWidth), javaCast("int", newHeight) ); 427 if (outputFile eq "") 428 { 429 retVal.img = croppedImage; 430 return retVal; 431 } else { 432 saveImage = writeImage(outputFile, croppedImage, jpegCompression); 433 if (saveImage.errorCode gt 0) 434 { 435 return saveImage; 436 } else { 437 return retVal; 438 } 439 } 440 </cfscript> 441</cffunction> 442 443<cffunction name="rotate" access="public" output="true" returntype="struct" hint="Rotate an image (+/-)90, (+/-)180, or (+/-)270 degrees."> 444 <cfargument name="objImage" required="yes" type="Any"> 445 <cfargument name="inputFile" required="yes" type="string"> 446 <cfargument name="outputFile" required="yes" type="string"> 447 <cfargument name="degrees" required="yes" type="numeric"> 448 <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> 449 450 <cfset var retVal = StructNew()> 451 <cfset var img = ""> 452 <cfset var loadImage = StructNew()> 453 <cfset var saveImage = StructNew()> 454 <cfset var at = ""> 455 <cfset var op = ""> 456 <cfset var w = 0> 457 <cfset var h = 0> 458 <cfset var iw = 0> 459 <cfset var ih = 0> 460 <cfset var x = 0> 461 <cfset var y = 0> 462 <cfset var rotatedImage = ""> 463 <cfset var rh = getRenderingHints()> 464 465 <cfset retVal.errorCode = 0> 466 <cfset retVal.errorMessage = ""> 467 468 <cfif inputFile neq ""> 469 <cfset loadImage = readImage(inputFile, "NO")> 470 <cfif loadImage.errorCode is 0> 471 <cfset img = loadImage.img> 472 <cfelse> 473 <cfset retVal = throw(loadImage.errorMessage)> 474 <cfreturn retVal> 475 </cfif> 476 <cfelse> 477 <cfset img = objImage> 478 </cfif> 479 <cfif img.getType() eq 0> 480 <cfset img = convertImageObject(img,img.TYPE_3BYTE_BGR)> 481 </cfif> 482 <cfif ListFind("-270,-180,-90,90,180,270",degrees) is 0> 483 <cfset retVal = throw( "At this time, image.cfc only supports rotating images in 90 degree increments.")> 484 <cfreturn retVal> 485 </cfif> 486 487 <cfscript> 488 rotatedImage = CreateObject("java", "java.awt.image.BufferedImage"); 489 at = CreateObject("java", "java.awt.geom.AffineTransform"); 490 op = CreateObject("java", "java.awt.image.AffineTransformOp"); 491 492 iw = img.getWidth(); h = iw; 493 ih = img.getHeight(); w = ih; 494 495 if(arguments.degrees eq 180) { w = iw; h = ih; } 496 497 x = (w/2)-(iw/2); 498 y = (h/2)-(ih/2); 499 500 rotatedImage.init(javacast("int",w),javacast("int",h),img.getType()); 501 502 at.rotate(arguments.degrees * 0.0174532925,w/2,h/2); 503 at.translate(x,y); 504 op.init(at, rh); 505 506 op.filter(img, rotatedImage); 507 508 if (outputFile eq "") 509 { 510 retVal.img = rotatedImage; 511 return retVal; 512 } else { 513 saveImage = writeImage(outputFile, rotatedImage, jpegCompression); 514 if (saveImage.errorCode gt 0) 515 { 516 return saveImage; 517 } else { 518 return retVal; 519 } 520 } 521 </cfscript> 522</cffunction> 523 524<cffunction name="convert" access="public" output="true" returntype="struct" hint="Convert an image from one format to another."> 525 <cfargument name="objImage" required="yes" type="Any"> 526 <cfargument name="inputFile" required="yes" type="string"> 527 <cfargument name="outputFile" required="yes" type="string"> 528 <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> 529 530 <cfset var retVal = StructNew()> 531 <cfset var loadImage = StructNew()> 532 <cfset var saveImage = StructNew()> 533 <cfset var img = ""> 534 535 <cfset retVal.errorCode = 0> 536 <cfset retVal.errorMessage = ""> 537 538 <cfif inputFile neq ""> 539 <cfset loadImage = readImage(inputFile, "NO")> 540 <cfif loadImage.errorCode is 0> 541 <cfset img = loadImage.img> 542 <cfelse> 543 <cfset retVal = throw(loadImage.errorMessage)> 544 <cfreturn retVal> 545 </cfif> 546 <cfelse> 547 <cfset img = objImage> 548 </cfif> 549 550 <cfscript> 551 if (outputFile eq "") 552 { 553 retVal = throw( "The convert method requires a valid output filename."); 554 return retVal; 555 } else { 556 saveImage = writeImage(outputFile, img, jpegCompression); 557 if (saveImage.errorCode gt 0) 558 { 559 return saveImage; 560 } else { 561 return retVal; 562 } 563 } 564 </cfscript> 565</cffunction> 566 567<cffunction name="setOption" access="public" output="true" returnType="void" hint="Sets values for allowed CFC options."> 568 <cfargument name="key" type="string" required="yes"> 569 <cfargument name="val" type="string" required="yes"> 570 571 <cfset var validKeys = "interpolation,textantialiasing,throwonerror,defaultJpegCompression"> 572 <cfset arguments.key = lcase(trim(arguments.key))> 573 <cfset arguments.val = lcase(trim(arguments.val))> 574 <cfif listFind(validKeys, arguments.key) gt 0> 575 <cfset variables[arguments.key] = arguments.val> 576 </cfif> 577</cffunction> 578 579<cffunction name="getOption" access="public" output="true" returnType="any" hint="Returns the current value for the specified CFC option."> 580 <cfargument name="key" type="string" required="yes"> 581 582 <cfset var validKeys = "interpolation,textantialiasing,throwonerror,defaultJpegCompression"> 583 <cfset arguments.key = lcase(trim(arguments.key))> 584 <cfif listFindNoCase(validKeys, arguments.key) gt 0> 585 <cfreturn variables[arguments.key]> 586 <cfelse> 587 <cfreturn ""> 588 </cfif> 589</cffunction> 590 591<cffunction name="getRenderingHints" access="private" output="true" returnType="any" hint="Internal method controls various aspects of rendering quality."> 592 <cfset var rh = CreateObject("java","java.awt.RenderingHints")> 593 <cfset var initMap = CreateObject("java","java.util.HashMap")> 594 <cfset initMap.init()> 595 <cfset rh.init(initMap)> 596 <cfset rh.put(rh.KEY_ALPHA_INTERPOLATION, rh.VALUE_ALPHA_INTERPOLATION_QUALITY)> <!--- QUALITY, SPEED, DEFAULT ---> 597 <cfset rh.put(rh.KEY_ANTIALIASING, rh.VALUE_ANTIALIAS_ON)> <!--- ON, OFF, DEFAULT ---> 598 <cfset rh.put(rh.KEY_COLOR_RENDERING, rh.VALUE_COLOR_RENDER_QUALITY)> <!--- QUALITY, SPEED, DEFAULT ---> 599 <cfset rh.put(rh.KEY_DITHERING, rh.VALUE_DITHER_DEFAULT)> <!--- DISABLE, ENABLE, DEFAULT ---> 600 <cfset rh.put(rh.KEY_RENDERING, rh.VALUE_RENDER_QUALITY)> <!--- QUALITY, SPEED, DEFAULT ---> 601 <cfset rh.put(rh.KEY_FRACTIONALMETRICS, rh.VALUE_FRACTIONALMETRICS_DEFAULT)> <!--- DISABLE, ENABLE, DEFAULT ---> 602 <cfset rh.put(rh.KEY_STROKE_CONTROL, rh.VALUE_STROKE_DEFAULT)> 603 604 <cfif variables.textAntiAliasing> 605 <cfset rh.put(rh.KEY_TEXT_ANTIALIASING, rh.VALUE_TEXT_ANTIALIAS_ON)> 606 <cfelse> 607 <cfset rh.put(rh.KEY_TEXT_ANTIALIASING, rh.VALUE_TEXT_ANTIALIAS_OFF)> 608 </cfif> 609 610 <cfif variables.interpolation eq "nearest_neighbor"> 611 <cfset rh.put(rh.KEY_INTERPOLATION, rh.VALUE_INTERPOLATION_NEAREST_NEIGHBOR)> 612 <cfelseif variables.interpolation eq "bilinear"> 613 <cfset rh.put(rh.KEY_INTERPOLATION, rh.VALUE_INTERPOLATION_BILINEAR)> 614 <cfelse> 615 <cfset rh.put(rh.KEY_INTERPOLATION, rh.VALUE_INTERPOLATION_BICUBIC)> 616 </cfif> 617 618 <cfreturn rh> 619</cffunction> 620 621<cffunction name="readImage" access="public" output="true" returntype="struct" hint="Reads an image from a local file. Requires an absolute path."> 622 <cfargument name="source" required="yes" type="string"> 623 <cfargument name="forModification" required="no" type="boolean" default="yes"> 624 625 <cfif isURL(source)> 626 <cfreturn readImageFromURL(source, forModification)> 627 <cfelse> 628 <cfreturn readImageFromFile(source, forModification)> 629 </cfif> 630</cffunction> 631 632<cffunction name="readImageFromFile" access="private" output="true" returntype="struct" hint="Reads an image from a local file. Requires an absolute path."> 633 <cfargument name="inputFile" required="yes" type="string"> 634 <cfargument name="forModification" required="no" type="boolean" default="yes"> 635 636 <cfset var retVal = StructNew()> 637 <cfset var img = ""> 638 <cfset var inFile = ""> 639 <cfset var filename = getFileFromPath(inputFile)> 640 <cfset var extension = lcase(listLast(inputFile,"."))> 641 <cfset var imageIO = CreateObject("java", "javax.imageio.ImageIO")> 642 <cfset var validExtensionsToRead = ArrayToList(imageIO.getReaderFormatNames())> 643 644 <cfset retVal.errorCode = 0> 645 <cfset retVal.errorMessage = ""> 646 647 <cfif not fileExists(arguments.inputFile)> 648 <cfset retVal = throw("The specified file #Chr(34)##arguments.inputFile##Chr(34)# could not be found.")> 649 <cfreturn retVal> 650 <cfelseif listLen(filename,".") lt 2> 651 <cfset retVal = throw("Sorry, image files without extensions cannot be manipulated.")> 652 <cfreturn retVal> 653 <cfelseif listFindNoCase(validExtensionsToRead, extension) is 0> 654 <cfset retVal = throw("Java is unable to read #extension# files.")> 655 <cfreturn retVal> 656 <cfelseif NOT fileExists(arguments.inputFile)> 657 <cfset retVal = throw("The specified input file does not exist.")> 658 <cfreturn retVal> 659 <cfelse> 660 <cfset img = CreateObject("java", "java.awt.image.BufferedImage")> 661 <cfset inFile = CreateObject("java", "java.io.File")> 662 <cfset inFile.init(arguments.inputFile)> 663 <cfif NOT inFile.canRead()> 664 <cfset retVal = throw("Unable to open source file #Chr(34)##arguments.inputFile##Chr(34)#.")> 665 <cfreturn retVal> 666 <cfelse> 667 <cftry> 668 <cfset img = imageIO.read(inFile)> 669 <cfcatch type="any"> 670 <cfset retval = throw("An error occurred attempting to read the specified image. #cfcatch.message# - #cfcatch.detail#")> 671 <cfreturn retVal> 672 </cfcatch> 673 </cftry> 674 <cfset retVal.img = img> 675 <cfset retVal.inFile = inFile> 676 <cfreturn retVal> 677 </cfif> 678 </cfif> 679</cffunction> 680 681<cffunction name="readImageFromURL" access="private" output="true" returntype="struct" hint="Read an image from a URL. Requires an absolute URL."> 682 <cfargument name="inputURL" required="yes" type="string"> 683 <cfargument name="forModification" required="no" type="boolean" default="yes"> 684 685 <cfset var retVal = StructNew()> 686 <cfset var img = CreateObject("java", "java.awt.image.BufferedImage")> 687 <cfset var inURL = CreateObject("java", "java.net.URL")> 688 <cfset var imageIO = CreateObject("java", "javax.imageio.ImageIO")> 689 690 <cfset retVal.errorCode = 0> 691 <cfset retVal.errorMessage = ""> 692 693 694 <cfset inURL.init(arguments.inputURL)> 695 <cftry> 696 <cfset img = imageIO.read(inURL)> 697 <cfcatch type="any"> 698 <cfset retval = throw("An error occurred attempting to read the specified image. #cfcatch.message# - #cfcatch.detail#")> 699 <cfreturn retVal> 700 </cfcatch> 701 </cftry> 702 <cfset retVal.img = img> 703 <cfreturn retVal> 704</cffunction> 705 706<cffunction name="writeImage" access="public" output="true" returntype="struct" hint="Write an image to disk."> 707 <cfargument name="outputFile" required="yes" type="string"> 708 <cfargument name="img" required="yes" type="any"> 709 <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> 710 711 <cfset var retVal = StructNew()> 712 <cfset var outFile = ""> 713 <cfset var filename = getFileFromPath(outputFile)> 714 <cfset var extension = lcase(listLast(filename,"."))> 715 <cfset var imageIO = CreateObject("java", "javax.imageio.ImageIO")> 716 <cfset var validExtensionsToWrite = ArrayToList(imageIO.getWriterFormatNames())> 717 <!--- used for jpeg output method ---> 718 <cfset var out = ""> 719 <cfset var fos = ""> 720 <cfset var JPEGCodec = ""> 721 <cfset var encoder = ""> 722 <cfset var param = ""> 723 <cfset var quality = javacast("float", jpegCompression/100)> 724 <cfset var tempOutputFile = "#variables.tempDirectory#\#createUUID()#.#extension#"> 725 726 <cfset retVal.errorCode = 0> 727 <cfset retVal.errorMessage = ""> 728 729 <cfif listFindNoCase(validExtensionsToWrite, extension) eq 0> 730 <cfset throw("Java is unable to write #extension# files. Valid formats include: #validExtensionsToWrite#")> 731 </cfif> 732 733 <cfif extension neq "jpg" and extension neq "jpeg"> 734 <!--- 735 Simple output method for non jpeg images 736 ---> 737 <cfset outFile = CreateObject("java", "java.io.File")> 738 <cfset outFile.init(tempOutputFile)> 739 <cfset imageIO.write(img, extension, outFile)> 740 <cfelse> 741 <cfscript> 742 /* 743 JPEG output method handles compression 744 */ 745 out = createObject("java", "java.io.BufferedOutputStream"); 746 fos = createObject("java", "java.io.FileOutputStream"); 747 fos.init(tempOutputFile); 748 out.init(fos); 749 JPEGCodec = createObject("java", "com.sun.image.codec.jpeg.JPEGCodec"); 750 encoder = JPEGCodec.createJPEGEncoder(out); 751 param = encoder.getDefaultJPEGEncodeParam(img); 752 param.setQuality(quality, false); 753 encoder.setJPEGEncodeParam(param); 754 encoder.encode(img); 755 out.close(); 756 </cfscript> 757 </cfif> 758 <!--- move file to its final destination ---> 759 <cffile action="MOVE" source="#tempOutputFile#" destination="#arguments.outputFile#"> 760 <cfreturn retVal> 761</cffunction> 762 763<cffunction name="flipflop" access="private" output="true" returntype="struct" hint="Internal method used for flipping and flopping images."> 764 <cfargument name="objImage" required="yes" type="Any"> 765 <cfargument name="inputFile" required="yes" type="string"> 766 <cfargument name="outputFile" required="yes" type="string"> 767 <cfargument name="direction" required="yes" type="string"><!--- horizontal or vertical ---> 768 <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> 769 770 <cfset var retVal = StructNew()> 771 <cfset var loadImage = StructNew()> 772 <cfset var saveImage = StructNew()> 773 <cfset var flippedImage = ""> 774 <cfset var rh = getRenderingHints()> 775 <cfset var img = ""> 776 777 <cfset retVal.errorCode = 0> 778 <cfset retVal.errorMessage = ""> 779 780 <cfif inputFile neq ""> 781 <cfset loadImage = readImage(inputFile, "NO")> 782 <cfif loadImage.errorCode is 0> 783 <cfset img = loadImage.img> 784 <cfelse> 785 <cfset retVal = throw(loadImage.errorMessage)> 786 <cfreturn retVal> 787 </cfif> 788 <cfelse> 789 <cfset img = objImage> 790 </cfif> 791 <cfif img.getType() eq 0> 792 <cfset img = convertImageObject(img,img.TYPE_3BYTE_BGR)> 793 </cfif> 794 <cfscript> 795 flippedImage = CreateObject("java", "java.awt.image.BufferedImage"); 796 at = CreateObject("java", "java.awt.geom.AffineTransform"); 797 op = CreateObject("java", "java.awt.image.AffineTransformOp"); 798 799 flippedImage.init(img.getWidth(), img.getHeight(), img.getType()); 800 801 if (direction eq "horizontal") { 802 at = at.getScaleInstance(-1, 1); 803 at.translate(-img.getWidth(), 0); 804 } else { 805 at = at.getScaleInstance(1,-1); 806 at.translate(0, -img.getHeight()); 807 } 808 op.init(at, rh); 809 op.filter(img, flippedImage); 810 811 if (outputFile eq "") 812 { 813 retVal.img = flippedImage; 814 return retVal; 815 } else { 816 saveImage = writeImage(outputFile, flippedImage, jpegCompression); 817 if (saveImage.errorCode gt 0) 818 { 819 return saveImage; 820 } else { 821 return retVal; 822 } 823 } 824 </cfscript> 825</cffunction> 826 827 828 829<cffunction name="filterFastBlur" access="public" output="true" returntype="struct" hint="Internal method used for flipping and flopping images."> 830 <cfargument name="objImage" required="yes" type="Any"> 831 <cfargument name="inputFile" required="yes" type="string"> 832 <cfargument name="outputFile" required="yes" type="string"> 833 <cfargument name="blurAmount" required="yes" type="numeric"> 834 <cfargument name="iterations" required="yes" type="numeric"> 835 <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> 836 837 <cfset var retVal = StructNew()> 838 <cfset var loadImage = StructNew()> 839 <cfset var saveImage = StructNew()> 840 <cfset var srcImage = ""> 841 <cfset var destImage = ""> 842 <cfset var rh = getRenderingHints()> 843 844 <cfset retVal.errorCode = 0> 845 <cfset retVal.errorMessage = ""> 846 847 <cfif NOT variables.javanulls> 848 <cfset throw("Sorry, but the blur filter is not supported on this platform.")> 849 </cfif> 850 <cfif inputFile neq ""> 851 <cfset loadImage = readImage(inputFile, "NO")> 852 <cfif loadImage.errorCode is 0> 853 <cfset srcImage = loadImage.img> 854 <cfelse> 855 <cfset retVal = throw(loadImage.errorMessage)> 856 <cfreturn retVal> 857 </cfif> 858 <cfelse> 859 <cfset srcImage = objImage> 860 </cfif> 861 <cfif srcImage.getType() eq 0> 862 <cfset srcImage = convertImageObject(srcImage,srcImage.TYPE_3BYTE_BGR)> 863 </cfif> 864 865 <cfscript> 866 867 // initialize the blur filter 868 variables.blurFilter.init(arguments.blurAmount); 869 // move the source image into the destination image 870 // so we can repeatedly blur it. 871 destImage = srcImage; 872 873 for (i=1; i lte iterations; i=i+1) 874 { 875 // do the blur i times 876 destImage = variables.blurFilter.filter(destImage); 877 } 878 879 880 if (outputFile eq "") 881 { 882 // return the image object 883 retVal.img = destImage; 884 return retVal; 885 } else { 886 // write the image object to the specified file. 887 saveImage = writeImage(outputFile, destImage, jpegCompression); 888 if (saveImage.errorCode gt 0) 889 { 890 return saveImage; 891 } else { 892 return retVal; 893 } 894 } 895 </cfscript> 896</cffunction> 897 898<cffunction name="filterSharpen" access="public" output="true" returntype="struct" hint="Internal method used for flipping and flopping images."> 899 <cfargument name="objImage" required="yes" type="Any"> 900 <cfargument name="inputFile" required="yes" type="string"> 901 <cfargument name="outputFile" required="yes" type="string"> 902 <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> 903 904 <cfset var retVal = StructNew()> 905 <cfset var loadImage = StructNew()> 906 <cfset var saveImage = StructNew()> 907 <cfset var srcImage = ""> 908 <cfset var destImage = ""> 909 <cfset var rh = getRenderingHints()> 910 911 <cfset retVal.errorCode = 0> 912 <cfset retVal.errorMessage = ""> 913 914 <cfif NOT variables.javanulls> 915 <cfset throw("Sorry, but the blur filter is not supported on this platform.")> 916 </cfif> 917 918 <cfif inputFile neq ""> 919 <cfset loadImage = readImage(inputFile, "NO")> 920 <cfif loadImage.errorCode is 0> 921 <cfset srcImage = loadImage.img> 922 <cfelse> 923 <cfset retVal = throw(loadImage.errorMessage)> 924 <cfreturn retVal> 925 </cfif> 926 <cfelse> 927 <cfset srcImage = objImage> 928 </cfif> 929 <cfif srcImage.getType() eq 0> 930 <cfset srcImage = convertImageObject(srcImage,srcImage.TYPE_3BYTE_BGR)> 931 </cfif> 932 933 <cfscript> 934 // initialize the sharpen filter 935 variables.sharpenFilter.init(); 936 937 destImage = variables.sharpenFilter.filter(srcImage); 938 939 940 if (outputFile eq "") 941 { 942 // return the image object 943 retVal.img = destImage; 944 return retVal; 945 } else { 946 // write the image object to the specified file. 947 saveImage = writeImage(outputFile, destImage, jpegCompression); 948 if (saveImage.errorCode gt 0) 949 { 950 return saveImage; 951 } else { 952 return retVal; 953 } 954 } 955 </cfscript> 956</cffunction> 957 958 959<cffunction name="filterPosterize" access="public" output="true" returntype="struct" hint="Internal method used for flipping and flopping images."> 960 <cfargument name="objImage" required="yes" type="Any"> 961 <cfargument name="inputFile" required="yes" type="string"> 962 <cfargument name="outputFile" required="yes" type="string"> 963 <cfargument name="amount" required="yes" type="string"> 964 <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> 965 966 <cfset var retVal = StructNew()> 967 <cfset var loadImage = StructNew()> 968 <cfset var saveImage = StructNew()> 969 <cfset var srcImage = ""> 970 <cfset var destImage = ""> 971 <cfset var rh = getRenderingHints()> 972 973 <cfset retVal.errorCode = 0> 974 <cfset retVal.errorMessage = ""> 975 976 <cfif NOT variables.javanulls> 977 <cfset throw("Sorry, but the blur filter is not supported on this platform.")> 978 </cfif> 979 980 <cfif inputFile neq ""> 981 <cfset loadImage = readImage(inputFile, "NO")> 982 <cfif loadImage.errorCode is 0> 983 <cfset srcImage = loadImage.img> 984 <cfelse> 985 <cfset retVal = throw(loadImage.errorMessage)> 986 <cfreturn retVal> 987 </cfif> 988 <cfelse> 989 <cfset srcImage = objImage> 990 </cfif> 991 <cfif srcImage.getType() eq 0> 992 <cfset srcImage = convertImageObject(srcImage,srcImage.TYPE_3BYTE_BGR)> 993 </cfif> 994 <cfif srcImage.getType() neq 5> 995 <cfset throw("ImageCFC cannot posterize this image type (#srcImage.getType()#)")> 996 </cfif> 997 <cfscript> 998 // initialize the posterize filter 999 variables.posterizeFilter.init(arguments.amount); 1000 1001 destImage = variables.posterizeFilter.filter(srcImage); 1002 1003 1004 if (outputFile eq "") 1005 { 1006 // return the image object 1007 retVal.img = destImage; 1008 return retVal; 1009 } else { 1010 // write the image object to the specified file. 1011 saveImage = writeImage(outputFile, destImage, jpegCompression); 1012 if (saveImage.errorCode gt 0) 1013 { 1014 return saveImage; 1015 } else { 1016 return retVal; 1017 } 1018 } 1019 </cfscript> 1020</cffunction> 1021 1022 1023<cffunction name="addText" access="public" output="true" returntype="struct" hint="Add text to an image."> 1024 <cfargument name="objImage" required="yes" type="Any"> 1025 <cfargument name="inputFile" required="yes" type="string"> 1026 <cfargument name="outputFile" required="yes" type="string"> 1027 <cfargument name="x" required="yes" type="numeric"> 1028 <cfargument name="y" required="yes" type="numeric"> 1029 <cfargument name="fontDetails" required="yes" type="struct"> 1030 <cfargument name="content" required="yes" type="String"> 1031 <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> 1032 1033 <cfset var retVal = StructNew()> 1034 <cfset var loadImage = StructNew()> 1035 <cfset var img = ""> 1036 <cfset var saveImage = StructNew()> 1037 <cfset var g2d = ""> 1038 <cfset var bgImage = ""> 1039 <cfset var fontImage = ""> 1040 <cfset var overlayImage = ""> 1041 <cfset var Color = ""> 1042 <cfset var font = ""> 1043 <cfset var font_stream = ""> 1044 <cfset var ac = ""> 1045 <cfset var rgb = ""> 1046 1047 <cfset retVal.errorCode = 0> 1048 <cfset retVal.errorMessage = ""> 1049 1050 <cfparam name="arguments.fontDetails.size" default="12"> 1051 <cfparam name="arguments.fontDetails.color" default="black"> 1052 <cfparam name="arguments.fontDetails.fontFile" default=""> 1053 <cfparam name="arguments.fontDetails.fontName" default="serif"> 1054 1055 <cfif arguments.fontDetails.fontFile neq "" and not fileExists(arguments.fontDetails.fontFile)> 1056 <cfset retVal = throw("The specified font file #Chr(34)##arguments.inputFile##Chr(34)# could not be found on the server.")> 1057 <cfreturn retVal> 1058 </cfif> 1059 <cftry> 1060 <cfset rgb = getRGB(arguments.fontDetails.color)> 1061 <cfcatch type="any"> 1062 <cfset retVal = throw("Invalid color #Chr(34)##arguments.fontDetails.color##Chr(34)#")> 1063 <cfreturn retVal> 1064 </cfcatch> 1065 </cftry> 1066 <cfif inputFile neq ""> 1067 <cfset loadImage = readImage(inputFile, "NO")> 1068 <cfif loadImage.errorCode is 0> 1069 <cfset img = loadImage.img> 1070 <cfelse> 1071 <cfset retVal = throw(loadImage.errorMessage)> 1072 <cfreturn retVal> 1073 </cfif> 1074 <cfelse> 1075 <cfset img = objImage> 1076 </cfif> 1077 <cfif img.getType() eq 0> 1078 <cfset img = convertImageObject(img,img.TYPE_3BYTE_BGR)> 1079 </cfif> 1080 <cfscript> 1081 // load objects 1082 bgImage = CreateObject("java", "java.awt.image.BufferedImage"); 1083 fontImage = CreateObject("java", "java.awt.image.BufferedImage"); 1084 overlayImage = CreateObject("java", "java.awt.image.BufferedImage"); 1085 Color = CreateObject("java","java.awt.Color"); 1086 font = createObject("java","java.awt.Font"); 1087 font_stream = createObject("java","java.io.FileInputStream"); 1088 ac = CreateObject("Java", "java.awt.AlphaComposite"); 1089 1090 // set up basic needs 1091 fontColor = Color.init(javacast("int", rgb.red), javacast("int", rgb.green), javacast("int", rgb.blue)); 1092 1093 if (fontDetails.fontFile neq "") 1094 { 1095 font_stream.init(arguments.fontDetails.fontFile); 1096 font = font.createFont(font.TRUETYPE_FONT, font_stream); 1097 font = font.deriveFont(javacast("float",arguments.fontDetails.size)); 1098 } else { 1099 font.init(fontDetails.fontName, evaluate(fontDetails.style), fontDetails.size); 1100 } 1101 // get font metrics using a 1x1 bufferedImage 1102 fontImage.init(1,1,img.getType()); 1103 g2 = fontImage.createGraphics(); 1104 g2.setRenderingHints(getRenderingHints()); 1105 fc = g2.getFontRenderContext(); 1106 bounds = font.getStringBounds(content,fc); 1107 1108 g2 = img.createGraphics(); 1109 g2.setRenderingHints(getRenderingHints()); 1110 g2.setFont(font); 1111 g2.setColor(fontColor); 1112 // in case you want to change the alpha 1113 // g2.setComposite(ac.getInstance(ac.SRC_OVER, 0.50)); 1114 1115 // the location (arguments.fontDetails.size+y) doesn't really work 1116 // the way I want it to. 1117 g2.drawString(content,javacast("int",x),javacast("int",arguments.fontDetails.size+y)); 1118 1119 if (outputFile eq "") 1120 { 1121 retVal.img = img; 1122 return retVal; 1123 } else { 1124 saveImage = writeImage(outputFile, img, jpegCompression); 1125 if (saveImage.errorCode gt 0) 1126 { 1127 return saveImage; 1128 } else { 1129 return retVal; 1130 } 1131 } 1132 </cfscript> 1133</cffunction> 1134 1135<cffunction name="watermark" access="public" output="false"> 1136 <cfargument name="objImage1" required="yes" type="Any"> 1137 <cfargument name="objImage2" required="yes" type="Any"> 1138 <cfargument name="inputFile1" required="yes" type="string"> 1139 <cfargument name="inputFile2" required="yes" type="string"> 1140 <cfargument name="alpha" required="yes" type="numeric"> 1141 <cfargument name="placeAtX" required="yes" type="numeric"> 1142 <cfargument name="placeAtY" required="yes" type="numeric"> 1143 <cfargument name="outputFile" required="yes" type="string"> 1144 <cfargument name="jpegCompression" required="no" type="numeric" default="#variables.defaultJpegCompression#"> 1145 1146 <cfset var retVal = StructNew()> 1147 <cfset var loadImage = StructNew()> 1148 <cfset var originalImage = ""> 1149 <cfset var wmImage = ""> 1150 <cfset var saveImage = StructNew()> 1151 <cfset var ac = ""> 1152 <cfset var rh = getRenderingHints()> 1153 1154 <cfset retVal.errorCode = 0> 1155 <cfset retVal.errorMessage = ""> 1156 1157 <cfif inputFile1 neq ""> 1158 <cfset loadImage = readImage(inputFile1, "NO")> 1159 <cfif loadImage.errorCode is 0> 1160 <cfset originalImage = loadImage.img> 1161 <cfelse> 1162 <cfset retVal = throw(loadImage.errorMessage)> 1163 <cfreturn retVal> 1164 </cfif> 1165 <cfelse> 1166 <cfset originalImage = objImage1> 1167 </cfif> 1168 <cfif originalImage.getType() eq 0> 1169 <cfset originalImage = convertImageObject(originalImage,originalImage.TYPE_3BYTE_BGR)> 1170 </cfif> 1171 1172 <cfif inputFile2 neq ""> 1173 <cfset loadImage = readImage(inputFile2, "NO")> 1174 <cfif loadImage.errorCode is 0> 1175 <cfset wmImage = loadImage.img> 1176 <cfelse> 1177 <cfset retVal = throw(loadImage.errorMessage)> 1178 <cfreturn retVal> 1179 </cfif> 1180 <cfelse> 1181 <cfset wmImage = objImage2> 1182 </cfif> 1183 <cfif wmImage.getType() eq 0> 1184 <cfset wmImage = convertImageObject(wmImage,wmImage.TYPE_3BYTE_BGR)> 1185 </cfif> 1186 1187 1188 <cfscript> 1189 at = CreateObject("java", "java.awt.geom.AffineTransform"); 1190 op = CreateObject("java", "java.awt.image.AffineTransformOp"); 1191 ac = CreateObject("Java", "java.awt.AlphaComposite"); 1192 gfx = originalImage.getGraphics(); 1193 gfx.setComposite(ac.getInstance(ac.SRC_OVER, alpha)); 1194 1195 at.init(); 1196 // op.init(at,op.TYPE_BILINEAR); 1197 op.init(at, rh); 1198 1199 gfx.drawImage(wmImage, op, javaCast("int",arguments.placeAtX), javacast("int", arguments.placeAtY)); 1200 1201 gfx.dispose(); 1202 1203 if (outputFile eq "") 1204 { 1205 retVal.img = originalImage; 1206 return retVal; 1207 } else { 1208 saveImage = writeImage(outputFile, originalImage, jpegCompression); 1209 if (saveImage.errorCode gt 0) 1210 { 1211 return saveImage; 1212 } else { 1213 return retVal; 1214 } 1215 } 1216 </cfscript> 1217</cffunction> 1218 1219<cffunction name="isURL" access="private" output="false" returnType="boolean"> 1220 <cfargument name="stringToCheck" required="yes" type="string"> 1221 <cfif REFindNoCase("^(((https?:)\/\/))[-[:alnum:]\?%,\.\/&##!@:=\+~_]+[A-Za-z0-9\/]$",stringToCheck) NEQ 0> 1222 <cfreturn true> 1223 <cfelse> 1224 <cfreturn false> 1225 </cfif> 1226</cffunction> 1227 1228<!--- function returns RGB values in a structure for hex or the 16 1229 HTML named colors ---> 1230<cffunction name="getRGB" access="private" output="true" returnType="struct"> 1231 <cfargument name="color" type="string" required="yes"> 1232 1233 <cfset var retVal = structNew()> 1234 <cfset var cnt = 0> 1235 <cfset var namedColors = "aqua,black,blue,fuchsia,gray,green,lime,maroon,navy,olive,purple,red,silver,teal,white,yellow"> 1236 <cfset var namedColorsHexValues = "00ffff,000000,0000ff,ff00ff,808080,008000,00ff00,800000,000080,808080,ff0000,c0c0c0,008080,ffffff,ffff00"> 1237 1238 <cfset retVal.red = 0> 1239 <cfset retVal.green = 0> 1240 <cfset retVal.blue = 0> 1241 1242 <cfset arguments.color = trim(arguments.color)> 1243 <cfif len(arguments.color) is 0> 1244 <cfreturn retVal> 1245 <cfelseif listFind(namedColors, arguments.color) gt 0> 1246 <cfset arguments.color = listGetAt(namedColorsHexValues, listFind(namedColors, arguments.color))> 1247 </cfif> 1248 <cfif left(arguments.color,1) eq "##"> 1249 <cfset arguments.color = right(arguments.color,len(arguments.color)-1)> 1250 </cfif> 1251 <cfif len(arguments.color) neq 6> 1252 <cfreturn retVal> 1253 <cfelse> 1254 <cftry> 1255 <cfset retVal.red = InputBaseN(mid(arguments.color,1,2),16)> 1256 <cfset retVal.green = InputBaseN(mid(arguments.color,3,2),16)> 1257 <cfset retVal.blue = InputBaseN(mid(arguments.color,5,2),16)> 1258 <cfcatch type="any"> 1259 <cfset retVal.red = 0> 1260 <cfset retVal.green = 0> 1261 <cfset retVal.blue = 0> 1262 <cfreturn retVal> 1263 </cfcatch> 1264 </cftry> 1265 </cfif> 1266 <cfreturn retVal> 1267</cffunction> 1268 1269<cffunction name="throw" access="private" output="false" returnType="struct"> 1270 <cfargument name="detail" type="string" required="yes"> 1271 <cfargument name="force" type="boolean" required="no" default="no"> 1272 1273 <cfset var retVal = StructNew()> 1274 1275 <cfif variables.throwOnError or arguments.force> 1276 <cfthrow detail="#arguments.detail#" message="#arguments.detail#"> 1277 <cfelse> 1278 <cfset retVal.errorCode = 1> 1279 <cfset retVal.errorMessage = arguments.detail> 1280 <cfreturn retVal> 1281 </cfif> 1282</cffunction> 1283 1284<cffunction name="debugDump" access="private"> 1285 <cfdump var="#arguments#"><cfabort> 1286</cffunction> 1287 1288<cffunction name="convertImageObject" access="private" output="false" returnType="any"> 1289 <cfargument name="bImage" type="Any" required="yes"> 1290 <cfargument name="type" type="numeric" required="yes"> 1291 1292 <cfscript> 1293 // convert the image to a specified BufferedImage type and return it 1294 1295 var width = bImage.getWidth(); 1296 var height = bImage.getHeight(); 1297 var newImage = createObject("java","java.awt.image.BufferedImage").init(javacast("int",width), javacast("int",height), javacast("int",type)); 1298 // int[] rgbArray = new int[width*height]; 1299 var rgbArray = variables.arrObj.newInstance(variables.intClass, javacast("int",width*height)); 1300 1301 bImage.getRGB( 1302 javacast("int",0), 1303 javacast("int",0), 1304 javacast("int",width), 1305 javacast("int",height), 1306 rgbArray, 1307 javacast("int",0), 1308 javacast("int",width) 1309 ); 1310 newImage.setRGB( 1311 javacast("int",0), 1312 javacast("int",0), 1313 javacast("int",width), 1314 javacast("int",height), 1315 rgbArray, 1316 javacast("int",0), 1317 javacast("int",width) 1318 ); 1319 return newImage; 1320 </cfscript> 1321 1322</cffunction> 1323 1324</cfcomponent> 1325 1326