home *** CD-ROM | disk | FTP | other *** search
Wrap
from JascApp import * import string import JascUtils def ScriptProperties(): return { 'Author': 'Joe Fromm', 'Copyright': 'Copyright (C) 2002-2003, Jasc Software Inc., All Rights Reserved. Permission to create derivate works of this script is granted provided this copyright notice is included', 'Description': 'Put EXIF camera and exposure information at the bottom of the image.', 'Host': 'Paint Shop Pro 8', 'Host Version': '8.00' } def Do(Environment): ''' This script extracts data from the active document to place a caption at the lower right corner of the image. The caption contains the camera make/model number, aperture and exposure time. This does require that the image contain this information to being with - if no EXIF data is found it puts up a message box and returns. The text is placed at the bottom right corner of the image. To make it easier to read, the area around the text is filled with a dark gray. To isolate the caption and backdrop from the rest of the image, a layer group is created. Following execution of the script, three additional layers will be created, placed above the layer that was active when the script was run: EXIF Caption - the group layer EXIF Text - this is a vector layer containing the text we created Caption Background - this is a raster layer that is filled with grey around the text ''' if JascUtils.RequireADoc( Environment ) == App.Constants.Boolean.false: return # first extract the EXIF data - if we can't find any just return without changing the image ImageInfo = App.Do( Environment, 'ReturnImageInfo' ) if ImageInfo['ExifMake'] == '' or ImageInfo['ExifModel'] == '' or \ ImageInfo['ExifFNumber' ] == '' or ImageInfo['ExifExposureTime'] == '': App.Do(Environment, 'MsgBox', { 'Buttons': App.Constants.MsgButtons.OK, 'Icon': App.Constants.MsgIcons.Stop, 'Text': 'No EXIF data found on the current image.', }) return # save any existing selection SelSaver = JascUtils.SaveSelection( Environment, App.TargetDocument ) # assemble the camera string by concatenating the camera make and model. Some camera # manufacturers have the barbaric practice of CAPITALIZING everything in their make and model # strings, so convert it to initial caps only for a more civilized appearance CaptionTextCamera = unicode(string.capwords( ImageInfo['ExifMake'] + ' ' + ImageInfo[ 'ExifModel' ] )) # now assemble exposure information by using the aperture and exposure Aperture = float(ImageInfo['ExifFNumber']) CaptionTextExposure = u'f/%g aperture, %s exposure' % (Aperture, ImageInfo['ExifExposureTime'].strip()) # first we create a raster layer at 50% opacity as a backdrop for the caption # for now the raster layer is empty - we'll fill it in later # the new layer becomes the active layer App.Do( Environment, 'NewRasterLayer', { 'General': { 'Opacity': 50, 'Name': 'Caption Background', 'IsVisible': App.Constants.Boolean.true, }, 'GeneralSettings': { 'ExecutionMode': App.Constants.ExecutionMode.Silent, } }) # create a layer group. This will place the raster layer in the group # the group is the active layer on completion App.Do( Environment, 'NewLayerGroup', { 'General': { 'Opacity': 100, 'Name': 'EXIF Caption', }, 'GeneralSettings': { 'ExecutionMode': App.Constants.ExecutionMode.Silent, } }) # select the raster layer so that the vector layer gets created above it App.Do( Environment, 'SelectLayer', { 'Path': (0,0,[1],App.Constants.Boolean.false), }) # now create a vector layer to put text on - creating the layer will make it active App.Do( Environment, 'NewVectorLayer', { 'General': { 'Opacity': 100, 'Name': 'EXIF Text', }, 'GeneralSettings': { 'ExecutionMode': App.Constants.ExecutionMode.Silent, } }) # Figure out how big the text should be by examining the overall image size. We'll do a rough # scale based on 1000 pixels. We won't paint text less than 16 point in any event. ImageMaxDimension = max(App.TargetDocument.Width, App.TargetDocument.Height) TextScaleFactor = max(0.25, float(ImageMaxDimension) / 1000.0) TextSize = int(16.0 * TextScaleFactor) # now place the text - use right justification at the lower right corner of the image. # we are placing 16 pixel text, so to leave some room for leading we place the first # line of text 24 pixels up from the bottom, and the second will be only 4 pixels up # from the bottom. # since we use a black backdrop for the text, make the text color white. TextPlacementLine1 = (App.TargetDocument.Width - 4 * TextScaleFactor, App.TargetDocument.Height - (24 * TextScaleFactor)) App.Do( Environment, 'Text', { 'CreateAs': App.Constants.CreateAs.Vector, 'Segments': [{ 'Fill': { 'Color': (255,255,255), 'Pattern': None, 'Gradient': None, 'Texture': None }, 'Font': 'Arial', 'PointSize': TextSize, 'Start': TextPlacementLine1, 'Stroke': None, 'LineStyle': None, 'LineWidth':0, 'SetText': App.Constants.Justify.Right, },{ 'Characters': CaptionTextCamera }], 'FinalApply': App.Constants.Boolean.false, 'GeneralSettings': { 'ExecutionMode': App.Constants.ExecutionMode.Silent, 'AutoActionMode': App.Constants.AutoActionMode.Match } }) # place the second line of text TextPlacementLine2 = (App.TargetDocument.Width - 4 * TextScaleFactor, App.TargetDocument.Height - (4 * TextScaleFactor) ) App.Do( Environment, 'Text', { 'CreateAs': App.Constants.CreateAs.Vector, 'Segments': [{ 'Fill': { 'Color': (255,255,255), 'Pattern': None, 'Gradient': None, 'Texture': None, }, 'Font': 'Arial', 'PointSize': TextSize, 'Start': TextPlacementLine2, 'Stroke': None, 'LineStyle': None, 'LineWidth':0, 'SetText': App.Constants.Justify.Right, },{ 'Characters': CaptionTextExposure }], 'FinalApply': App.Constants.Boolean.false, 'GeneralSettings': { 'ExecutionMode': App.Constants.ExecutionMode.Silent, 'AutoActionMode': App.Constants.AutoActionMode.Match } }) # we have the text down, but we want to put a backdrop behind it so that the text remains # visible. How big do we make the backdrop? Who knows, so we just ask the vector layer how # big it is Result = App.Do( Environment, 'ReturnLayerProperties' ) TextRectangle = Result[ 'LayerRect' ] FillStartPoint = ( TextRectangle[0][0] - (4 * TextScaleFactor), TextRectangle[0][1] - (4 * TextScaleFactor) ) FillEndPoint = ( App.TargetDocument.Width, App.TargetDocument.Height ) # select the raster layer - it is immediately below the vector layer App.Do( Environment, 'SelectLayer', { 'Path': (0,-1,[],App.Constants.Boolean.false), }) # make a selection around the bounding box of the text. Once we have a selection we'll fill it App.Do( Environment, 'Selection', { 'General': { 'Mode': App.Constants.SelectionOperation.Replace, 'Antialias': App.Constants.Boolean.true, 'Feather': 0 }, 'SelectionShape': App.Constants.SelectionShape.Rectangle, 'Start': FillStartPoint, 'End': FillEndPoint, 'GeneralSettings': { 'ExecutionMode': App.Constants.ExecutionMode.Silent } }) # now do a flood fill, making sure the point we click on is inside of our selection # use a dark grey for the fill so that we can see the text on top of it App.Do( Environment, 'Fill', { 'BlendMode': 0, 'MatchMode': 1, 'Material': { 'Color': (32,32,32), 'Pattern': None, 'Gradient': None, 'Texture': None }, 'Opacity': 100, 'Point': (FillStartPoint[0] + 1, FillStartPoint[1] + 1), 'Tolerance': 20, 'GeneralSettings': { 'ExecutionMode': App.Constants.ExecutionMode.Silent } }) # restore the original selectoin SelSaver.RestoreSelection() # All done!