source: extensions/FCKEditor/editor/filemanager/connectors/cfm/image.cfc @ 3295

Last change on this file since 3295 was 3295, checked in by patdenice, 15 years ago

New extension added:
FCK Editor (2.0.a)

File size: 46.0 KB
Line 
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>
Note: See TracBrowser for help on using the repository browser.