Overview

Namespaces

  • None
  • Xmf
    • Database
    • Module
      • Helper
    • Template
  • Xoops
    • Auth
    • Core
      • Cache
      • Database
        • Logging
        • Schema
      • Exception
      • Handler
        • Scheme
      • Kernel
        • Dtype
        • Handlers
        • Model
      • Lists
      • Locale
        • Punic
      • Service
        • Contract
      • Session
      • Text
        • Sanitizer
          • Extensions
      • Theme
        • Plugins
    • Form
    • Html
    • Locale
    • Module
      • Helper
      • Plugin

Classes

  • ArtObject
  • ArtObjectHandler
  • Avatars
  • AvatarsAvatar
  • AvatarsAvatar_userForm
  • AvatarsAvatarForm
  • AvatarsAvatarHandler
  • AvatarsLocale
  • AvatarsLocaleEn_US
  • AvatarsPreload
  • AvatarsProvider
  • AvatarsUserlink
  • AvatarsUserlinkHandler
  • AwesomeButton
  • BannerRender
  • Banners
  • BannersBanner
  • BannersBannerclient
  • BannersBannerclientForm
  • BannersBannerclientHandler
  • BannersBannerForm
  • BannersBannerHandler
  • BannersPreload
  • BloggerApi
  • CodexMenusPlugin
  • CodexSearchPlugin
  • CodexSystemPlugin
  • CodexUserconfigsPlugin
  • Comments
  • CommentsComment
  • CommentsCommentForm
  • CommentsCommentHandler
  • CommentsCommentRenderer
  • CommentsPreload
  • CommentsSystemPlugin
  • CommentsUserconfigsPlugin
  • Cookie
  • CountryFlagProvider
  • Criteria
  • CriteriaCompo
  • CriteriaElement
  • DebugbarLogger
  • DebugbarPreload
  • DebugbarUserconfigsPlugin
  • DefaultThemeLocale
  • DefaultThemeLocaleEn_US
  • FormDhtmlTextArea
  • FormTextArea
  • GravatarsPreload
  • GravatarsProvider
  • htmLawed
  • HtmlToPdfProvider
  • imageLib
  • Images
  • ImagesCategory
  • ImagesCategory_imagemanagerForm
  • ImagesCategoryForm
  • ImagesCategoryHandler
  • ImagesCategoryselectForm
  • ImagesImage
  • ImagesImage_Body
  • ImagesImage_imagemanagerForm
  • ImagesImagebody
  • ImagesImagebodyHandler
  • ImagesImageForm
  • ImagesImageHandler
  • ImagesPreload
  • JUpload
  • LegacyLogger
  • LoggerPreload
  • LoggerUserconfigsPlugin
  • Maintenance
  • MaintenanceMaintenanceForm
  • Menus
  • MenusBuilder
  • MenusConstantDecorator
  • MenusDecorator
  • MenusDecoratorAbstract
  • MenusDefaultDecorator
  • MenusDynamicDecorator
  • MenusMenu
  • MenusMenuHandler
  • MenusMenus
  • MenusMenus_menuForm
  • MenusMenus_menusForm
  • MenusMenusHandler
  • MenusPreload
  • MenusSmartyDecorator
  • MetaWeblogApi
  • MonologLogger
  • MonologPreload
  • MonologUserconfigsPlugin
  • MovableTypeApi
  • MyTextSanitizer
  • MyTextSanitizerExtended
  • Notifications
  • NotificationsNotification
  • NotificationsNotificationHandler
  • NotificationsPreload
  • NotificationsSystemPlugin
  • Page
  • PageCommentsPlugin
  • PageGroupPermHandler
  • PageLocale
  • PageLocaleEn_US
  • PageNotificationsPlugin
  • PagePage_content
  • PagePage_contentForm
  • PagePage_contentHandler
  • PagePage_rating
  • PagePage_ratingHandler
  • PagePage_related
  • PagePage_related_link
  • PagePage_related_linkHandler
  • PagePage_relatedForm
  • PagePage_relatedHandler
  • PagePreload
  • PageSearchPlugin
  • PageSystemPlugin
  • PdfPreload
  • PmMessage
  • PmMessageHandler
  • PmPreload
  • ProfileCategory
  • ProfileCategoryForm
  • ProfileCategoryHandler
  • ProfileCorePreload
  • ProfileField
  • ProfileFieldForm
  • ProfileFieldHandler
  • ProfileMenusPlugin
  • ProfileProfile
  • ProfileProfileHandler
  • ProfileRegstep
  • ProfileRegstepForm
  • ProfileRegstepHandler
  • ProfileVisibility
  • ProfileVisibilityHandler
  • Protector
  • protector_bruteforce_overrun_message
  • protector_crawler_overrun_message
  • protector_f5attack_overrun_message
  • protector_postcommon_post_deny_by_httpbl
  • protector_postcommon_post_deny_by_rbl
  • protector_postcommon_post_htmlpurify4everyone
  • protector_postcommon_post_htmlpurify4guest
  • protector_postcommon_post_need_multibyte
  • protector_postcommon_post_register_moratorium
  • protector_postcommon_register_insert_js_check
  • protector_precommon_badip_errorlog
  • protector_precommon_badip_message
  • protector_precommon_badip_redirection
  • protector_precommon_bwlimit_errorlog
  • protector_precommon_bwlimit_message
  • protector_prepurge_exit_message
  • protector_spamcheck_overrun_message
  • ProtectorCenterForm
  • ProtectorCorePreload
  • ProtectorFilterAbstract
  • ProtectorFilterHandler
  • ProtectorMySQLDatabase
  • Publisher
  • PublisherBlockForm
  • PublisherCategory
  • PublisherCategoryForm
  • PublisherCategoryHandler
  • PublisherCommentsPlugin
  • PublisherFile
  • PublisherFileForm
  • PublisherFileHandler
  • PublisherFormDateTime
  • PublisherGroupPermHandler
  • PublisherItem
  • PublisherItemForm
  • PublisherItemHandler
  • PublisherMenusPlugin
  • PublisherMetagen
  • PublisherMimetype
  • PublisherMimetypeHandler
  • PublisherNotificationsPlugin
  • PublisherPermissionHandler
  • PublisherPreload
  • PublisherRating
  • PublisherRatingHandler
  • PublisherSearchPlugin
  • PublisherSystemPlugin
  • PublisherUtils
  • QrcodePreload
  • QrcodeProvider
  • ReCaptchaResponse
  • RpcArrayHandler
  • RpcBase64Handler
  • RpcBooleanHandler
  • RpcDateTimeHandler
  • RpcDoubleHandler
  • RpcIntHandler
  • RpcMemberHandler
  • RpcMethodNameHandler
  • RpcNameHandler
  • RpcStringHandler
  • RpcStructHandler
  • RpcValueHandler
  • RssAuthorHandler
  • RssCategoryHandler
  • RssChannelHandler
  • RssCommentsHandler
  • RssCopyrightHandler
  • RssDescriptionHandler
  • RssDocsHandler
  • RssGeneratorHandler
  • RssGuidHandler
  • RssHeightHandler
  • RssImageHandler
  • RssItemHandler
  • RssLanguageHandler
  • RssLastBuildDateHandler
  • RssLinkHandler
  • RssManagingEditorHandler
  • RssNameHandler
  • RssPubDateHandler
  • RssSourceHandler
  • RssTextInputHandler
  • RssTitleHandler
  • RssTtlHandler
  • RssUrlHandler
  • RssWebMasterHandler
  • RssWidthHandler
  • SaxParser
  • Search
  • SearchPreload
  • SearchSearchForm
  • Smarty_Resource_Admin
  • Smarty_Resource_Block
  • Smarty_Resource_Db
  • Smarty_Resource_Module
  • Smilies
  • SmiliesPreload
  • SmiliesProvider
  • SmiliesSmiley
  • SmiliesSmileyHandler
  • SmiliesSmiliesForm
  • Snoopy
  • SqlUtility
  • System
  • SystemBlockForm
  • SystemBreadcrumb
  • SystemExtension
  • SystemGroupForm
  • SystemLocale
  • SystemLocaleEn_US
  • SystemMenuHandler
  • SystemModule
  • SystemPreferencesForm
  • SystemPreload
  • SystemUserForm
  • tar
  • ThemeSetAuthorHandler
  • ThemeSetDateCreatedHandler
  • ThemeSetDescriptionHandler
  • ThemeSetEmailHandler
  • ThemeSetFileTypeHandler
  • ThemeSetGeneratorHandler
  • ThemeSetImageHandler
  • ThemeSetLinkHandler
  • ThemeSetModuleHandler
  • ThemeSetNameHandler
  • ThemeSetTagHandler
  • ThemeSetTemplateHandler
  • Thumbs
  • ThumbsPreload
  • ThumbsProvider
  • TinyMCE
  • Userconfigs
  • UserconfigsConfigHandler
  • UserconfigsConfigsForm
  • UserconfigsItem
  • UserconfigsItemHandler
  • UserconfigsMenusPlugin
  • UserconfigsModulesForm
  • UserconfigsOption
  • UserconfigsOptionHandler
  • UserconfigsPreload
  • UserconfigsSystemPlugin
  • UserrankPreload
  • UserRankProvider
  • UserrankRank
  • UserrankRankHandler
  • UserrankRanksForm
  • Xcaptcha
  • XcaptchaCaptchaForm
  • XcaptchaImage
  • XcaptchaImageForm
  • XcaptchaRecaptcha
  • XcaptchaRecaptchaForm
  • XcaptchaText
  • XcaptchaTextForm
  • Xlanguage
  • XlanguageLanguage
  • XlanguageLanguageForm
  • XlanguagePreload
  • XlanguageTinymceForm
  • XlanguageXlanguageHandler
  • Xmf\Database\TableLoad
  • Xmf\Database\Tables
  • Xmf\Debug
  • Xmf\FilterInput
  • Xmf\Highlighter
  • Xmf\Language
  • Xmf\Loader
  • Xmf\Metagen
  • Xmf\Module\Admin
  • Xmf\Module\Cache
  • Xmf\Module\Helper
  • Xmf\Module\Helper\AbstractHelper
  • Xmf\Module\Helper\GenericHelper
  • Xmf\Module\Permission
  • Xmf\Module\Session
  • Xmf\Request
  • Xmf\Template\AbstractTemplate
  • Xmf\Template\Breadcrumb
  • Xmf\Template\Buttonbox
  • Xmf\Template\Feed
  • Xmf\Template\PrintContent
  • Xmf\Utilities
  • Xmf\Yaml
  • XmfPreload
  • XmlTagHandler
  • Xoops
  • Xoops\Auth\Ads
  • Xoops\Auth\AuthAbstract
  • Xoops\Auth\Factory
  • Xoops\Auth\Ldap
  • Xoops\Auth\Provisioning
  • Xoops\Auth\Xoops
  • Xoops\Cache
  • Xoops\Core\Assets
  • Xoops\Core\Cache\Access
  • Xoops\Core\Cache\CacheManager
  • Xoops\Core\Cache\DriverList
  • Xoops\Core\Cache\Legacy
  • Xoops\Core\ComposerUtility
  • Xoops\Core\Database\Connection
  • Xoops\Core\Database\Factory
  • Xoops\Core\Database\Logging\XoopsDebugStack
  • Xoops\Core\Database\QueryBuilder
  • Xoops\Core\Database\Schema\ExportVisitor
  • Xoops\Core\Database\Schema\ImportSchema
  • Xoops\Core\Database\Schema\PrefixStripper
  • Xoops\Core\Database\Schema\RemovePrefixes
  • Xoops\Core\Events
  • Xoops\Core\FilterInput
  • Xoops\Core\FixedGroups
  • Xoops\Core\Handler\Factory
  • Xoops\Core\Handler\FactorySpec
  • Xoops\Core\Handler\Scheme\FQN
  • Xoops\Core\Handler\Scheme\Kernel
  • Xoops\Core\Handler\Scheme\LegacyModule
  • Xoops\Core\HttpRequest
  • Xoops\Core\Kernel\Criteria
  • Xoops\Core\Kernel\CriteriaCompo
  • Xoops\Core\Kernel\CriteriaElement
  • Xoops\Core\Kernel\Dtype
  • Xoops\Core\Kernel\Dtype\DtypeAbstract
  • Xoops\Core\Kernel\Dtype\DtypeArray
  • Xoops\Core\Kernel\Dtype\DtypeDateTime
  • Xoops\Core\Kernel\Dtype\DtypeDecimal
  • Xoops\Core\Kernel\Dtype\DtypeEmail
  • Xoops\Core\Kernel\Dtype\DtypeEnumeration
  • Xoops\Core\Kernel\Dtype\DtypeFloat
  • Xoops\Core\Kernel\Dtype\DtypeInt
  • Xoops\Core\Kernel\Dtype\DtypeJson
  • Xoops\Core\Kernel\Dtype\DtypeMoney
  • Xoops\Core\Kernel\Dtype\DtypeOther
  • Xoops\Core\Kernel\Dtype\DtypeSimpleTime
  • Xoops\Core\Kernel\Dtype\DtypeSource
  • Xoops\Core\Kernel\Dtype\DtypeTextArea
  • Xoops\Core\Kernel\Dtype\DtypeTextBox
  • Xoops\Core\Kernel\Dtype\DtypeTimeZone
  • Xoops\Core\Kernel\Dtype\DtypeUrl
  • Xoops\Core\Kernel\Handlers\XoopsBlock
  • Xoops\Core\Kernel\Handlers\XoopsBlockHandler
  • Xoops\Core\Kernel\Handlers\XoopsBlockModuleLink
  • Xoops\Core\Kernel\Handlers\XoopsBlockModuleLinkHandler
  • Xoops\Core\Kernel\Handlers\XoopsConfigHandler
  • Xoops\Core\Kernel\Handlers\XoopsConfigItem
  • Xoops\Core\Kernel\Handlers\XoopsConfigItemHandler
  • Xoops\Core\Kernel\Handlers\XoopsConfigOption
  • Xoops\Core\Kernel\Handlers\XoopsConfigOptionHandler
  • Xoops\Core\Kernel\Handlers\XoopsGroup
  • Xoops\Core\Kernel\Handlers\XoopsGroupHandler
  • Xoops\Core\Kernel\Handlers\XoopsGroupPerm
  • Xoops\Core\Kernel\Handlers\XoopsGroupPermHandler
  • Xoops\Core\Kernel\Handlers\XoopsMemberHandler
  • Xoops\Core\Kernel\Handlers\XoopsMembership
  • Xoops\Core\Kernel\Handlers\XoopsMembershipHandler
  • Xoops\Core\Kernel\Handlers\XoopsModule
  • Xoops\Core\Kernel\Handlers\XoopsModuleHandler
  • Xoops\Core\Kernel\Handlers\XoopsOnline
  • Xoops\Core\Kernel\Handlers\XoopsOnlineHandler
  • Xoops\Core\Kernel\Handlers\XoopsPrivateMessage
  • Xoops\Core\Kernel\Handlers\XoopsPrivateMessageHandler
  • Xoops\Core\Kernel\Handlers\XoopsTplFile
  • Xoops\Core\Kernel\Handlers\XoopsTplFileHandler
  • Xoops\Core\Kernel\Handlers\XoopsTplSet
  • Xoops\Core\Kernel\Handlers\XoopsTplSetHandler
  • Xoops\Core\Kernel\Handlers\XoopsUser
  • Xoops\Core\Kernel\Handlers\XoopsUserHandler
  • Xoops\Core\Kernel\Model\Joint
  • Xoops\Core\Kernel\Model\Read
  • Xoops\Core\Kernel\Model\Stats
  • Xoops\Core\Kernel\Model\Sync
  • Xoops\Core\Kernel\Model\Write
  • Xoops\Core\Kernel\XoopsModelAbstract
  • Xoops\Core\Kernel\XoopsModelFactory
  • Xoops\Core\Kernel\XoopsObject
  • Xoops\Core\Kernel\XoopsObjectHandler
  • Xoops\Core\Kernel\XoopsPersistableObjectHandler
  • Xoops\Core\Lists\Country
  • Xoops\Core\Lists\Directory
  • Xoops\Core\Lists\Editor
  • Xoops\Core\Lists\File
  • Xoops\Core\Lists\HtmlFile
  • Xoops\Core\Lists\ImageFile
  • Xoops\Core\Lists\ListAbstract
  • Xoops\Core\Lists\Locale
  • Xoops\Core\Lists\Module
  • Xoops\Core\Lists\Month
  • Xoops\Core\Lists\SubjectIcon
  • Xoops\Core\Lists\SubSet
  • Xoops\Core\Lists\Theme
  • Xoops\Core\Lists\Time
  • Xoops\Core\Lists\TimeZone
  • Xoops\Core\Locale\LegacyCodes
  • Xoops\Core\Locale\Punic\Calendar
  • Xoops\Core\Locale\Time
  • Xoops\Core\Logger
  • Xoops\Core\MediaUploader
  • Xoops\Core\MimeTypes
  • Xoops\Core\PreloadItem
  • Xoops\Core\Psr0ClassLoader
  • Xoops\Core\Psr4ClassLoader
  • Xoops\Core\Random
  • Xoops\Core\Registry
  • Xoops\Core\Request
  • Xoops\Core\Security
  • Xoops\Core\Service\AbstractContract
  • Xoops\Core\Service\Manager
  • Xoops\Core\Service\NullProvider
  • Xoops\Core\Service\Provider
  • Xoops\Core\Service\Response
  • Xoops\Core\Session\Fingerprint
  • Xoops\Core\Session\Handler
  • Xoops\Core\Session\Manager
  • Xoops\Core\Session\RememberMe
  • Xoops\Core\Session\SessionUser
  • Xoops\Core\Text\Sanitizer
  • Xoops\Core\Text\Sanitizer\Configuration
  • Xoops\Core\Text\Sanitizer\ConfigurationAbstract
  • Xoops\Core\Text\Sanitizer\DefaultConfiguration
  • Xoops\Core\Text\Sanitizer\ExtensionAbstract
  • Xoops\Core\Text\Sanitizer\Extensions\Censor
  • Xoops\Core\Text\Sanitizer\Extensions\Clickable
  • Xoops\Core\Text\Sanitizer\Extensions\Embed
  • Xoops\Core\Text\Sanitizer\Extensions\Flash
  • Xoops\Core\Text\Sanitizer\Extensions\Iframe
  • Xoops\Core\Text\Sanitizer\Extensions\Image
  • Xoops\Core\Text\Sanitizer\Extensions\Mms
  • Xoops\Core\Text\Sanitizer\Extensions\Mp3
  • Xoops\Core\Text\Sanitizer\Extensions\Quote
  • Xoops\Core\Text\Sanitizer\Extensions\Rtsp
  • Xoops\Core\Text\Sanitizer\Extensions\SoundCloud
  • Xoops\Core\Text\Sanitizer\Extensions\SyntaxHighlight
  • Xoops\Core\Text\Sanitizer\Extensions\TextFilter
  • Xoops\Core\Text\Sanitizer\Extensions\UnorderedList
  • Xoops\Core\Text\Sanitizer\Extensions\Wiki
  • Xoops\Core\Text\Sanitizer\Extensions\Wmp
  • Xoops\Core\Text\Sanitizer\Extensions\XoopsCode
  • Xoops\Core\Text\Sanitizer\Extensions\Xss
  • Xoops\Core\Text\Sanitizer\Extensions\YouTube
  • Xoops\Core\Text\Sanitizer\FilterAbstract
  • Xoops\Core\Text\Sanitizer\NullExtension
  • Xoops\Core\Text\Sanitizer\NullFilter
  • Xoops\Core\Text\Sanitizer\SanitizerComponent
  • Xoops\Core\Text\Sanitizer\SanitizerConfigurable
  • Xoops\Core\Text\ShortCodes
  • Xoops\Core\Theme\AdminFactory
  • Xoops\Core\Theme\Factory
  • Xoops\Core\Theme\NullTheme
  • Xoops\Core\Theme\PluginAbstract
  • Xoops\Core\Theme\Plugins\Blocks
  • Xoops\Core\Theme\XoopsTheme
  • Xoops\Core\XoopsTpl
  • Xoops\Core\Yaml
  • Xoops\Form\BlockForm
  • Xoops\Form\Button
  • Xoops\Form\ButtonTray
  • Xoops\Form\Captcha
  • Xoops\Form\Checkbox
  • Xoops\Form\ColorPicker
  • Xoops\Form\DateSelect
  • Xoops\Form\DateTime
  • Xoops\Form\DhtmlTextArea
  • Xoops\Form\Editor
  • Xoops\Form\Element
  • Xoops\Form\ElementFactory
  • Xoops\Form\ElementTray
  • Xoops\Form\File
  • Xoops\Form\Form
  • Xoops\Form\GroupCheckbox
  • Xoops\Form\GroupFormCheckbox
  • Xoops\Form\GroupPermissionForm
  • Xoops\Form\Hidden
  • Xoops\Form\Label
  • Xoops\Form\Mail
  • Xoops\Form\OptionElement
  • Xoops\Form\Password
  • Xoops\Form\Radio
  • Xoops\Form\RadioYesNo
  • Xoops\Form\Raw
  • Xoops\Form\Select
  • Xoops\Form\SelectCountry
  • Xoops\Form\SelectEditor
  • Xoops\Form\SelectGroup
  • Xoops\Form\SelectLanguage
  • Xoops\Form\SelectLocale
  • Xoops\Form\SelectMatchOption
  • Xoops\Form\SelectTheme
  • Xoops\Form\SelectTimeZone
  • Xoops\Form\SelectUser
  • Xoops\Form\SimpleForm
  • Xoops\Form\Tab
  • Xoops\Form\TableForm
  • Xoops\Form\TabTray
  • Xoops\Form\Text
  • Xoops\Form\TextArea
  • Xoops\Form\ThemeForm
  • Xoops\Form\Token
  • Xoops\Form\Url
  • Xoops\Html\Attributes
  • Xoops\Html\Img
  • Xoops\Locale
  • Xoops\Locale\AbstractLocale
  • Xoops\Module\Admin
  • Xoops\Module\Helper
  • Xoops\Module\Helper\Dummy
  • Xoops\Module\Helper\HelperAbstract
  • Xoops\Module\Plugin
  • Xoops\Module\Plugin\ConfigCollector
  • Xoops\Module\Plugin\PluginAbstract
  • Xoops\Utils
  • Xoops_Locale_Mailer_Abstract
  • XoopsAdminThemeFactory
  • XoopsApi
  • XoopsArt
  • XoopsBaseConfig
  • XoopsBlock
  • XoopsBlockHandler
  • XoopsBlockmodulelink
  • XoopsBlockmodulelinkHandler
  • XoopsCache
  • XoopsCaptcha
  • XoopsCaptchaImage
  • XoopsCaptchaImageHandler
  • XoopsCaptchaMethod
  • XoopsCaptchaRecaptcha
  • XoopsCaptchaText
  • XoopsConfigHandler
  • XoopsConfigItem
  • XoopsConfigItemHandler
  • XoopsConfigOption
  • XoopsConfigOptionHandler
  • XoopsDatabase
  • XoopsDatabaseFactory
  • XoopsDatabaseManager
  • XoopsDownloader
  • XoopsEditor
  • XoopsEditorHandler
  • XoopsFile
  • XoopsFileHandler
  • XoopsFilterInput
  • XoopsFolderHandler
  • XoopsForm
  • XoopsFormButton
  • XoopsFormButtonTray
  • XoopsFormCaptcha
  • XoopsFormCheckBox
  • XoopsFormColorPicker
  • XoopsFormDateTime
  • XoopsFormDhtmlTextArea
  • XoopsFormEditor
  • XoopsFormElement
  • XoopsFormElementTray
  • XoopsFormFile
  • XoopsFormHidden
  • XoopsFormHiddenToken
  • XoopsFormLabel
  • XoopsFormPassword
  • XoopsFormRadio
  • XoopsFormRadioYN
  • XoopsFormSelect
  • XoopsFormSelectCheckGroup
  • XoopsFormSelectCountry
  • XoopsFormSelectEditor
  • XoopsFormSelectGroup
  • XoopsFormSelectLang
  • XoopsFormSelectMatchOption
  • XoopsFormSelectTheme
  • XoopsFormSelectTimezone
  • XoopsFormSelectUser
  • XoopsFormText
  • XoopsFormTextArea
  • XoopsFormTextDateSelect
  • XoopsFormTinymce
  • XoopsFormTinymce4
  • XoopsGroup
  • XoopsGroupHandler
  • XoopsGroupPerm
  • XoopsGroupPermForm
  • XoopsGroupPermHandler
  • XoopsGTicket
  • XoopsGuiDefault
  • XoopsInstallWizard
  • XoopsLists
  • XoopsLoad
  • XoopsLocal
  • XoopsLocale
  • XoopsLocaleEn_US
  • XoopsLogger
  • XoopsMailer
  • XoopsMailerLocal
  • XoopsMailerLocale
  • XoopsMediaUploader
  • XoopsMemberHandler
  • XoopsMembership
  • XoopsMembershipHandler
  • XoopsModule
  • XoopsModuleHandler
  • XoopsMultiMailer
  • XoopsMySQLDatabase
  • XoopsMySQLDatabaseProxy
  • XoopsMySQLDatabaseSafe
  • XoopsObject
  • XoopsObjectHandler
  • XoopsObjectTree
  • XoopsOnline
  • XoopsOnlineHandler
  • XoopsPageNav
  • XoopsPathController
  • XoopsPersistableObjectHandler
  • XoopsPreload
  • XoopsPreloadItem
  • XoopsPrivmessage
  • XoopsPrivmessageHandler
  • XoopsRequest
  • XoopsSecurity
  • XoopsSimpleForm
  • XoopsTableForm
  • XoopsTarDownloader
  • XoopsTheme
  • XoopsThemeBlocksPlugin
  • XoopsThemeFactory
  • XoopsThemeForm
  • XoopsThemePlugin
  • XoopsThemeSetParser
  • XoopsTpl
  • XoopsTplfile
  • XoopsTplfileHandler
  • XoopsTplset
  • XoopsTplsetHandler
  • XoopsUser
  • XoopsUserHandler
  • XoopsUserUtility
  • XoopsUtility
  • XoopsXmlRpcApi
  • XoopsXmlRpcArray
  • XoopsXmlRpcBase64
  • XoopsXmlRpcBoolean
  • XoopsXmlRpcDatetime
  • XoopsXmlRpcDocument
  • XoopsXmlRpcDouble
  • XoopsXmlRpcFault
  • XoopsXmlRpcInt
  • XoopsXmlRpcParser
  • XoopsXmlRpcRequest
  • XoopsXmlRpcResponse
  • XoopsXmlRpcString
  • XoopsXmlRpcStruct
  • XoopsXmlRpcTag
  • XoopsXmlRss2Parser
  • XoopsZipDownloader
  • zipfile

Interfaces

  • CommentsPluginInterface
  • MenusDecoratorInterface
  • MenusPluginInterface
  • NotificationsPluginInterface
  • SearchPluginInterface
  • SystemPluginInterface
  • UserconfigsPluginInterface
  • Xoops\Core\AttributeInterface
  • Xoops\Core\Handler\Scheme\SchemeInterface
  • Xoops\Core\Service\Contract\AvatarInterface
  • Xoops\Core\Service\Contract\CountryflagInterface
  • Xoops\Core\Service\Contract\EmojiInterface
  • Xoops\Core\Service\Contract\HtmlToPdfInterface
  • Xoops\Core\Service\Contract\QrcodeInterface
  • Xoops\Core\Service\Contract\ThumbnailInterface
  • Xoops\Core\Service\Contract\UserRankInterface
  • Xoops\Core\Session\FingerprintInterface
  • Xoops\Form\ContainerInterface

Exceptions

  • Xoops\Core\Exception\InvalidHandlerSpecException
  • Xoops\Core\Exception\NoHandlerException

Functions

  • _changeMimeValue
  • _clearAddSessionVars
  • _clearEditSessionVars
  • _ee
  • _recaptcha_aes_encrypt
  • _recaptcha_aes_pad
  • _recaptcha_http_post
  • _recaptcha_mailhide_email_parts
  • _recaptcha_mailhide_urlbase64
  • _recaptcha_qsencode
  • _tt
  • add
  • addCriteria
  • admin_refcheck
  • b_comments_edit
  • b_comments_show
  • b_notification_show
  • b_search_show
  • b_system_info_edit
  • b_system_info_show
  • b_system_login_show
  • b_system_main_edit
  • b_system_main_show
  • b_system_newmembers_edit
  • b_system_newmembers_show
  • b_system_online_show
  • b_system_themes_edit
  • b_system_themes_show
  • b_system_topposters_edit
  • b_system_topposters_show
  • b_system_user_show
  • b_system_waiting_show
  • b_xlanguage_select_edit
  • b_xlanguage_select_show
  • banners_blocks_edit
  • banners_blocks_show
  • base_url
  • buildRssFeedCache
  • buildTable
  • check_files_extensions_on_path
  • check_files_extensions_on_phar
  • checkEmail
  • clearAddSession
  • clearEditSession
  • config_loading
  • create_folder
  • create_img
  • create_img_gd
  • createConfigform
  • createDir
  • createThemeform
  • dateSort
  • debugger
  • delete
  • deleteDir
  • duplicate_file
  • edit
  • endsWith
  • exception_handler
  • extensionSort
  • file_put_contents
  • filenameSort
  • filescount
  • fix_dirname
  • fix_filename
  • fix_get_params
  • fix_path
  • fix_strtolower
  • fix_strtoupper
  • foldersize
  • formatTimestamp
  • formatURL
  • genPathCheckHtml
  • get_file_by_url
  • get_writeoks_from_protector
  • getBrightness
  • getDbConnection
  • getDbConnectionParams
  • getDirList
  • handle_uploaded_files
  • http_response_code
  • image_check_memory_usage
  • install_acceptUser
  • install_finalize
  • installHtmlSpecialCharacters
  • is_function_callable
  • is_really_writable
  • load_functions
  • load_object
  • load_objectHandler
  • loadModuleAdminMenu
  • makeSize
  • manage
  • menus_block_edit
  • menus_block_show
  • menus_mainmenu_show
  • mod_clearCacheFile
  • mod_clearConfg
  • mod_clearConfig
  • mod_clearFile
  • mod_clearSmartyCache
  • mod_constant
  • mod_createCacheFile
  • mod_createCacheFile_byGroup
  • mod_createFile
  • mod_DB_prefix
  • mod_fetchConfg
  • mod_fetchConfig
  • mod_generateCacheId
  • mod_generateCacheId_byGroup
  • mod_getDirname
  • mod_getMysqlVersion
  • mod_isModuleAction
  • mod_loadCacheFile
  • mod_loadCacheFile_byGroup
  • mod_loadConfg
  • mod_loadConfig
  • mod_loadFile
  • mod_loadFunctions
  • mod_loadRenderer
  • mod_message
  • modify_chmod
  • new_thumbnails_creation
  • normalizeColor
  • page_blocks_edit
  • page_blocks_show
  • profile_getRegisterForm
  • profile_getUserForm
  • profile_install_addCategory
  • profile_install_addField
  • profile_install_addStep
  • profile_install_initializeProfiles
  • profile_install_setPermissions
  • protector_ip_cmp
  • protector_postcheck
  • protector_precheck
  • publisher_category_items_sel_edit
  • publisher_category_items_sel_show
  • publisher_cloneFileFolder
  • publisher_createLogo
  • publisher_date_to_date_edit
  • publisher_date_to_date_show
  • publisher_displayCategory
  • publisher_editCat
  • publisher_editFile
  • publisher_editItem
  • publisher_items_columns_edit
  • publisher_items_columns_show
  • publisher_items_menu_edit
  • publisher_items_menu_show
  • publisher_items_new_edit
  • publisher_items_new_show
  • publisher_items_random_item_show
  • publisher_items_recent_edit
  • publisher_items_recent_show
  • publisher_items_spot_edit
  • publisher_items_spot_show
  • publisher_latest_files_edit
  • publisher_latest_files_show
  • publisher_latest_news_edit
  • publisher_latest_news_show
  • publisher_mk_chkbox
  • publisher_mk_select
  • publisher_pagewrap_upload
  • publisher_search
  • publisher_search_show
  • publisher_tag_iteminfo
  • publisher_tag_synchronization
  • rcopy
  • recaptcha_check_answer
  • recaptcha_get_html
  • recaptcha_get_signup_url
  • recaptcha_mailhide_html
  • recaptcha_mailhide_url
  • redirect_header
  • rename_file
  • rename_folder
  • rrename
  • rrename_after_cleaner
  • search
  • sizeSort
  • smarty_block_assets
  • smarty_block_noshortcodes
  • smarty_compiler_xoAdminIcons
  • smarty_compiler_xoAdminNav
  • smarty_compiler_xoAppUrl
  • smarty_compiler_xoImgUrl
  • smarty_compiler_xoModuleIcons16
  • smarty_compiler_xoModuleIcons32
  • smarty_compiler_xoModuleIconsBookmarks
  • smarty_function_addBaseScript
  • smarty_function_addBaseStylesheet
  • smarty_function_securityToken
  • smarty_function_thumbnail
  • smarty_function_translate
  • smarty_function_translateTheme
  • smarty_function_xoblock
  • smarty_function_xoInboxCount
  • smarty_function_xoMemberInfo
  • smarty_function_xoops_link
  • smarty_function_xoPageNav
  • smarty_modifier_datetime
  • smarty_modifier_debug_print_var
  • smarty_outputfilter_shortcodes
  • synchronize
  • system_AdminIcons
  • system_adminVersion
  • system_cleanVars
  • system_loadLanguage
  • system_loadTemplate
  • updateMimeValue
  • userTimeToServerTime
  • xhtmlspecialchars
  • xlanguage_convert_encoding
  • xlanguage_convert_item
  • xlanguage_copyfile
  • xlanguage_detectLang
  • xlanguage_encoding
  • xlanguage_lang_detect
  • xlanguage_mkdirs
  • xlanguage_ml
  • xlanguage_ml_escape_bracket
  • xlanguage_select_show
  • xoBoolField
  • xoDiag
  • xoDiagBoolSetting
  • xoDiagIfWritable
  • xoFormField
  • xoops_comment_count
  • xoops_comment_delete
  • xoops_confirm
  • xoops_convert_encoding
  • xoops_cp_footer
  • xoops_cp_header
  • xoops_error
  • xoops_footer
  • xoops_getActiveModules
  • xoops_getbanner
  • xoops_getBaseDomain
  • xoops_getConfigOption
  • xoops_getcss
  • xoops_getenv
  • xoops_getHandler
  • xoops_getMailer
  • xoops_getModuleHandler
  • xoops_getModuleOption
  • xoops_getOption
  • xoops_getrank
  • xoops_getUrlDomain
  • xoops_getUserTimestamp
  • xoops_groupperm_deletebymoditem
  • xoops_header
  • xoops_isActiveModule
  • xoops_load
  • xoops_loadLanguage
  • xoops_makepass
  • xoops_message
  • xoops_module_install_avatars
  • xoops_module_install_banners
  • xoops_module_install_comments
  • xoops_module_install_debugbar
  • xoops_module_install_notifications
  • xoops_module_install_page
  • xoops_module_install_pm
  • xoops_module_install_profile
  • xoops_module_install_publisher
  • xoops_module_install_smilies
  • xoops_module_install_system
  • xoops_module_install_userrank
  • xoops_module_install_xlanguage
  • xoops_module_pre_uninstall_comments
  • xoops_module_pre_uninstall_notifications
  • xoops_module_update_comments
  • xoops_module_update_debugbar
  • xoops_module_update_notifications
  • xoops_module_update_pm
  • xoops_module_update_profile
  • xoops_module_update_publisher
  • xoops_module_update_search
  • xoops_module_update_system
  • xoops_module_update_xlanguage
  • xoops_notification_deletebyitem
  • xoops_notification_deletebymodule
  • xoops_notification_deletebyuser
  • xoops_result
  • xoops_setActiveModules
  • xoops_setConfigOption
  • xoops_substr
  • xoops_template_clear_module_cache
  • xoops_template_touch
  • xoops_trim
  • xoops_utf8_encode
  • xoopseditor_get_rootpath
  • xoPassField
  • xoPhpVersion
  • Overview
  • Namespace
  • Class
  • Tree
   1: <?php
   2:    # ========================================================================#
   3:    #
   4:    #  This work is licensed under the Creative Commons Attribution 3.0 Unported
   5:    #  License. To view a copy of this license,
   6:    #  visit http://creativecommons.org/licenses/by/3.0/ or send a letter to
   7:    #  Creative Commons, 444 Castro Street, Suite 900, Mountain View, California,
   8:    #  94041, USA.
   9:    #
  10:    #  All rights reserved.
  11:    #
  12:    #  Author:    Jarrod Oberto
  13:    #  Version:   1.5.1
  14:    #  Date:      10-05-11
  15:    #  Purpose:   Provide tools for image manipulation using GD
  16:    #  Param In:  See functions.
  17:    #  Param Out: Produces a resized image
  18:    #  Requires : Requires PHP GD library.
  19:    #  Usage Example:
  20:    #                     include("lib/php_image_magician.php");
  21:    #                     $magicianObj = new resize('images/car.jpg');
  22:    #                     $magicianObj -> resizeImage(150, 100, 0);
  23:    #                     $magicianObj -> saveImage('images/car_small.jpg', 100);
  24:    #
  25:    #        - See end of doc for more examples -
  26:    #
  27:    #  Supported file types include: jpg, png, gif, bmp, psd (read)
  28:    #
  29:    #
  30:    #
  31:    #  The following functions are taken from phpThumb() [available from
  32:    #    http://phpthumb.sourceforge.net], and are used with written permission
  33:    #  from James Heinrich.
  34:    #    - GD2BMPstring
  35:    #      - GetPixelColor
  36:    #      - LittleEndian2String
  37:    #
  38:    #  The following functions are from Marc Hibbins and are used with written
  39:    #  permission (are also under the Attribution-ShareAlike
  40:    #  [http://creativecommons.org/licenses/by-sa/3.0/] license.
  41:    #    -
  42:    #
  43:    #  PhpPsdReader is used with written permission from Tim de Koning.
  44:    #  [http://www.kingsquare.nl/phppsdreader]
  45:    #
  46:    #
  47:    #
  48:    #  Modificatoin history
  49:    #  Date      Initials  Ver Description
  50:    #  10-05-11  J.C.O   0.0 Initial build
  51:    #  01-06-11  J.C.O   0.1.1   * Added reflections
  52:    #              * Added Rounded corners
  53:    #              * You can now use PNG interlacing
  54:    #              * Added shadow
  55:    #              * Added caption box
  56:    #              * Added vintage filter
  57:    #              * Added dynamic image resizing (resize on the fly)
  58:    #              * minor bug fixes
  59:    #  05-06-11  J.C.O   0.1.1.1 * Fixed undefined variables
  60:    #  17-06-11  J.C.O   0.1.2   * Added image_batch_class.php class
  61:    #              * Minor bug fixes
  62:    #  26-07-11  J.C.O   0.1.4 * Added support for external images
  63:    #              * Can now set the crop poisition
  64:    #  03-08-11  J.C.O   0.1.5 * Added reset() method to reset resource to
  65:    #                original input file.
  66:    #              * Added method addTextToCaptionBox() to
  67:    #                simplify adding text to a caption box.
  68:    #              * Added experimental writeIPTC. (not finished)
  69:    #              * Added experimental readIPTC. (not finished)
  70:    #  11-08-11  J.C.O     * Added initial border presets.
  71:    #  30-08-11  J.C.O     * Added 'auto' crop option to crop portrait
  72:    #                images near the top.
  73:    #  08-09-11  J.C.O     * Added cropImage() method to allow standalone
  74:    #                cropping.
  75:    #  17-09-11  J.C.O     * Added setCropFromTop() set method - set the
  76:    #                percentage to crop from the top when using
  77:    #                crop 'auto' option.
  78:    #              * Added setTransparency() set method - allows you
  79:    #                to turn transparency off (like when saving
  80:    #                as a jpg).
  81:    #              * Added setFillColor() set method - set the
  82:    #                background color to use instead of transparency.
  83:    #  05-11-11  J.C.O   0.1.5.1 * Fixed interlacing option
  84:    #  0-07-12  J.C.O   1.0
  85:    #
  86:    #  Known issues & Limitations:
  87:    # -------------------------------
  88:    #  Not so much an issue, the image is destroyed on the deconstruct rather than
  89:    #  when we have finished with it. The reason for this is that we don't know
  90:    #  when we're finished with it as you can both save the image and display
  91:    #  it directly to the screen (imagedestroy($this->imageResized))
  92:    #
  93:    #  Opening BMP files is slow. A test with 884 bmp files processed in a loop
  94:    #  takes forever - over 5 min. This test inlcuded opening the file, then
  95:    #  getting and displaying its width and height.
  96:    #
  97:    #  $forceStretch:
  98:    # -------------------------------
  99:    #  On by default.
 100:    #  $forceStretch can be disabled by calling method setForceStretch with false
 101:    #  parameter. If disabled, if an images original size is smaller than the size
 102:    #  specified by the user, the original size will be used. This is useful when
 103:    #  dealing with small images.
 104:    #
 105:    #  If enabled, images smaller than the size specified will be stretched to
 106:    #  that size.
 107:    #
 108:    #  Tips:
 109:    # -------------------------------
 110:    #  * If you're resizing a transparent png and saving it as a jpg, set
 111:    #  $keepTransparency to false with: $magicianObj->setTransparency(false);
 112:    #
 113:    #  FEATURES:
 114:    #    * EASY TO USE
 115:    #    * BMP SUPPORT (read & write)
 116:    #    * PSD (photoshop) support (read)
 117:    #    * RESIZE IMAGES
 118:    #      - Preserve transparency (png, gif)
 119:    #      - Apply sharpening (jpg) (requires PHP >= 5.1.0)
 120:    #      - Set image quality (jpg, png)
 121:    #      - Resize modes:
 122:    #        - exact size
 123:    #        - resize by width (auto height)
 124:    #        - resize by height (auto width)
 125:    #        - auto (automatically determine the best of the above modes to use)
 126:    #        - crop - resize as best as it can then crop the rest
 127:    #      - Force stretching of smaller images (upscale)
 128:    #    * APPLY FILTERS
 129:    #      - Convert to grey scale
 130:    #      - Convert to black and white
 131:    #      - Convert to sepia
 132:    #      - Convert to negative
 133:    #    * ROTATE IMAGES
 134:    #      - Rotate using predefined "left", "right", or "180"; or any custom degree amount
 135:    #    * EXTRACT EXIF DATA (requires exif module)
 136:    #      - make
 137:    #      - model
 138:    #      - date
 139:    #      - exposure
 140:    #      - aperture
 141:    #      - f-stop
 142:    #      - iso
 143:    #      - focal length
 144:    #      - exposure program
 145:    #      - metering mode
 146:    #      - flash status
 147:    #      - creator
 148:    #      - copyright
 149:    #    * ADD WATERMARK
 150:    #      - Specify exact x, y placement
 151:    #      - Or, specify using one of the 9 pre-defined placements such as "tl"
 152:    #        (for top left), "m" (for middle), "br" (for bottom right)
 153:    #        - also specify padding from edge amount (optional).
 154:    #      - Set opacity of watermark (png).
 155:    #    * ADD BORDER
 156:    #    * USE HEX WHEN SPECIFYING COLORS (eg: #ffffff)
 157:    #    * SAVE IMAGE OR OUTPUT TO SCREEN
 158:    #
 159:    #
 160:    # ========================================================================#
 161: 
 162: 
 163: class imageLib
 164: {
 165: 
 166:     private $fileName;
 167:     private $image;
 168:     protected $imageResized;
 169:     private $widthOriginal;     # Always be the original width
 170:     private $heightOriginal;
 171:     private $width;         # Current width (width after resize)
 172:     private $height;
 173:     private $imageSize;
 174:   private $fileExtension;
 175: 
 176:   private $debug = true;
 177:   private $errorArray = array();
 178: 
 179:   private $forceStretch = true;
 180:   private $aggresiveSharpening = false;
 181: 
 182:   private $transparentArray = array('.png', '.gif');
 183:   private $keepTransparency = true;
 184:   private $fillColorArray = array('r'=>255, 'g'=>255, 'b'=>255);
 185: 
 186:   private $sharpenArray = array('jpg');
 187: 
 188:   private $psdReaderPath;
 189:   private $filterOverlayPath;
 190: 
 191:   private $isInterlace;
 192: 
 193:   private $captionBoxPositionArray = array();
 194: 
 195:   private $fontDir = 'fonts';
 196: 
 197:   private $cropFromTopPercent = 10;
 198: 
 199: 
 200: ## --------------------------------------------------------
 201: 
 202:     function __construct($fileName)
 203:     # Author:     Jarrod Oberto
 204:   # Date:     27-02-08
 205:     # Purpose:    Constructor
 206:     # Param in:   $fileName: File name and path.
 207:     # Param out:  n/a
 208:     # Reference:
 209:     # Notes:
 210:     #
 211:     {
 212:     if (!$this->testGDInstalled()) { if ($this->debug) { throw new Exception('The GD Library is not installed.'); }else{ throw new Exception(); }};
 213: 
 214:     $this->initialise();
 215: 
 216:         // *** Save the image file name. Only store this incase you want to display it
 217:         $this->fileName = $fileName;
 218:     $this->fileExtension = fix_strtolower(strrchr($fileName, '.'));
 219: 
 220:         // *** Open up the file
 221:         $this->image = $this->openImage($fileName);
 222: 
 223: 
 224:     // *** Assign here so we don't modify the original
 225:     $this->imageResized = $this->image;
 226: 
 227:         // *** If file is an image
 228:         if ($this->testIsImage($this->image))
 229:         {
 230:             // *** Get width and height
 231:             $this->width  = imagesx($this->image);
 232:             $this->widthOriginal = imagesx($this->image);
 233:             $this->height = imagesy($this->image);
 234:             $this->heightOriginal = imagesy($this->image);
 235: 
 236: 
 237:         /*  Added 15-09-08
 238:          *  Get the filesize using this build in method.
 239:          *  Stores an array of size
 240:          *
 241:          *  $this->imageSize[1] = width
 242:          *  $this->imageSize[2] = height
 243:          *  $this->imageSize[3] = width x height
 244:          *
 245:          */
 246:             $this->imageSize = getimagesize($this->fileName);
 247: 
 248:         } else {
 249:       $this->errorArray[] = 'File is not an image';
 250:     }
 251:     }
 252: 
 253: ## --------------------------------------------------------
 254: 
 255:   private function initialise () {
 256: 
 257:     $this->psdReaderPath = __DIR__ . '/classPhpPsdReader.php';
 258:     $this->filterOverlayPath = __DIR__ . '/filters';
 259: 
 260:     // *** Set if image should be interlaced or not.
 261:     $this->isInterlace = false;
 262:   }
 263: 
 264: 
 265: 
 266: /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
 267:   Resize
 268: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
 269: 
 270: 
 271:     public function resizeImage($newWidth, $newHeight, $option = 0, $sharpen = false, $autoRotate = false)
 272:     # Author:     Jarrod Oberto
 273:     # Date:       27-02-08
 274:     # Purpose:    Resizes the image
 275:     # Param in:   $newWidth:
 276:     #             $newHeight:
 277:     #             $option:     0 / exact = defined size;
 278:     #                          1 / portrait = keep aspect set height;
 279:     #                          2 / landscape = keep aspect set width;
 280:     #                          3 / auto = auto;
 281:   #                          4 / crop= resize and crop;
 282:   #
 283:   #         $option can also be an array containing options for
 284:   #         cropping. E.G., array('crop', 'r')
 285:   #
 286:   #         This array only applies to 'crop' and the 'r' refers to
 287:   #         "crop right". Other value include; tl, t, tr, l, m (default),
 288:   #         r, bl, b, br, or you can specify your own co-ords (which
 289:   #         isn't recommended.
 290:   #
 291:   #       $sharpen:    true: sharpen (jpg only);
 292:   #                false: don't sharpen
 293:     # Param out:  n/a
 294:     # Reference:
 295:     # Notes:      To clarify the $option input:
 296:     #               0 = The exact height and width dimensions you set.
 297:     #               1 = Whatever height is passed in will be the height that
 298:     #                   is set. The width will be calculated and set automatically
 299:     #                   to a the value that keeps the original aspect ratio.
 300:     #               2 = The same but based on the width. We try make the image the
 301:   #                  biggest size we can while stil fitting inside the box size
 302:     #               3 = Depending whether the image is landscape or portrait, this
 303:     #                   will automatically determine whether to resize via
 304:     #                   dimension 1,2 or 0
 305:   #               4 = Will resize and then crop the image for best fit
 306:   #
 307:   #       forceStretch can be applied to options 1,2,3 and 4
 308:     #
 309:     {
 310: 
 311:     // *** We can pass in an array of options to change the crop position
 312:     $cropPos = 'm';
 313:     if (is_array($option) && fix_strtolower($option[0]) === 'crop') {
 314:       $cropPos = $option[1];         # get the crop option
 315:     } else if (strpos($option, '-') !== false) {
 316:       // *** Or pass in a hyphen seperated option
 317:       $optionPiecesArray = explode('-', $option);
 318:       $cropPos = end($optionPiecesArray);
 319:     }
 320: 
 321:     // *** Check the option is valid
 322:     $option = $this->prepOption($option);
 323: 
 324:     // *** Make sure the file passed in is valid
 325:     if (!$this->image) { if ($this->debug) { throw new Exception('file ' . $this->getFileName() .' is missing or invalid'); }else{ throw new Exception(); }};
 326: 
 327:     // *** Get optimal width and height - based on $option
 328:     $dimensionsArray = $this->getDimensions($newWidth, $newHeight, $option);
 329: 
 330:     $optimalWidth  = $dimensionsArray['optimalWidth'];
 331:     $optimalHeight = $dimensionsArray['optimalHeight'];
 332: 
 333:     // *** Resample - create image canvas of x, y size
 334:     $this->imageResized = imagecreatetruecolor($optimalWidth, $optimalHeight);
 335:     $this->keepTransparancy($optimalWidth, $optimalHeight, $this->imageResized);
 336:     imagecopyresampled($this->imageResized, $this->image, 0, 0, 0, 0, $optimalWidth, $optimalHeight, $this->width, $this->height);
 337: 
 338: 
 339:     // *** If '4', then crop too
 340:     if ($option == 4 || $option === 'crop') {
 341: 
 342:       if (($optimalWidth >= $newWidth && $optimalHeight >= $newHeight)) {
 343:         $this->crop($optimalWidth, $optimalHeight, $newWidth, $newHeight, $cropPos);
 344:       }
 345:     }
 346: 
 347:     // *** If Rotate.
 348:     if ($autoRotate) {
 349: 
 350:       $exifData = $this->getExif(false);
 351:       if (count($exifData) > 0) {
 352: 
 353:         switch($exifData['orientation']) {
 354:             case 8:
 355:                 $this->imageResized = imagerotate($this->imageResized,90,0);
 356:                 break;
 357:             case 3:
 358:                 $this->imageResized = imagerotate($this->imageResized,180,0);
 359:                 break;
 360:             case 6:
 361:                 $this->imageResized = imagerotate($this->imageResized,-90,0);
 362:                 break;
 363:         }
 364:       }
 365:     }
 366: 
 367:     // *** Sharpen image (if jpg and the user wishes to do so)
 368:     if ($sharpen && in_array($this->fileExtension, $this->sharpenArray)) {
 369: 
 370:       // *** Sharpen
 371:       $this->sharpen();
 372:     }
 373:     }
 374: 
 375: ## --------------------------------------------------------
 376: 
 377:   public function cropImage($newWidth, $newHeight, $cropPos = 'm')
 378:     # Author:     Jarrod Oberto
 379:     # Date:       08-09-11
 380:     # Purpose:    Crops the image
 381:     # Param in:   $newWidth: crop with
 382:     #             $newHeight: crop height
 383:   #       $cropPos: Can be any of the following:
 384:   #             tl, t, tr, l, m, r, bl, b, br, auto
 385:   #           Or:
 386:   #             a custom position such as '30x50'
 387:     # Param out:  n/a
 388:     # Reference:
 389:     # Notes:
 390:     #
 391:   {
 392: 
 393:     // *** Make sure the file passed in is valid
 394:     if (!$this->image) { if ($this->debug) { throw new Exception('file ' . $this->getFileName() .' is missing or invalid'); }else{ throw new Exception(); }};
 395: 
 396:     $this->imageResized = $this->image;
 397:     $this->crop($this->width, $this->height, $newWidth, $newHeight, $cropPos);
 398: 
 399:   }
 400: 
 401: ## --------------------------------------------------------
 402: 
 403:   private function keepTransparancy($width, $height, $im)
 404:     # Author:     Jarrod Oberto
 405:     # Date:       08-04-11
 406:     # Purpose:    Keep transparency for png and gif image
 407:     # Param in:
 408:     # Param out:  n/a
 409:     # Reference:
 410:     # Notes:
 411:     #
 412:   {
 413:     // *** If PNG, perform some transparency retention actions (gif untested)
 414:     if (in_array($this->fileExtension, $this->transparentArray) && $this->keepTransparency) {
 415:       imagealphablending($im, false);
 416:       imagesavealpha($im, true);
 417:       $transparent = imagecolorallocatealpha($im, 255, 255, 255, 127);
 418:       imagefilledrectangle($im, 0, 0, $width, $height, $transparent);
 419:     } else {
 420:       $color = imagecolorallocate($im, $this->fillColorArray['r'], $this->fillColorArray['g'], $this->fillColorArray['b']);
 421:       imagefilledrectangle($im, 0, 0, $width, $height, $color);
 422:     }
 423:   }
 424: 
 425: ## --------------------------------------------------------
 426: 
 427:     private function crop($optimalWidth, $optimalHeight, $newWidth, $newHeight, $cropPos)
 428:     # Author:     Jarrod Oberto
 429:     # Date:       15-09-08
 430:     # Purpose:    Crops the image
 431:     # Param in:   $newWidth:
 432:     #             $newHeight:
 433:     # Param out:  n/a
 434:     # Reference:
 435:     # Notes:
 436:     #
 437:     {
 438: 
 439:     // *** Get cropping co-ordinates
 440:     $cropArray = $this->getCropPlacing($optimalWidth, $optimalHeight, $newWidth, $newHeight, $cropPos);
 441:     $cropStartX = $cropArray['x'];
 442:     $cropStartY = $cropArray['y'];
 443: 
 444:     // *** Crop this bad boy
 445:     $crop = imagecreatetruecolor($newWidth , $newHeight);
 446:     $this->keepTransparancy($optimalWidth, $optimalHeight, $crop);
 447:     imagecopyresampled($crop, $this->imageResized, 0, 0, $cropStartX, $cropStartY, $newWidth, $newHeight , $newWidth, $newHeight);
 448: 
 449:     $this->imageResized = $crop;
 450: 
 451:     // *** Set new width and height to our variables
 452:     $this->width = $newWidth;
 453:     $this->height = $newHeight;
 454: 
 455:     }
 456: 
 457: ## --------------------------------------------------------
 458: 
 459:   private function getCropPlacing($optimalWidth, $optimalHeight, $newWidth, $newHeight, $pos='m')
 460:   #
 461:   # Author:   Jarrod Oberto
 462:   # Date:   July 11
 463:   # Purpose:  Set the cropping area.
 464:   # Params in:
 465:   # Params out: (array) the crop x and y co-ordinates.
 466:   # Notes:    When specifying the exact pixel crop position (eg 10x15), be
 467:   #       very careful as it's easy to crop out of the image leaving
 468:   #       black borders.
 469:   #
 470:   {
 471:     $pos = fix_strtolower($pos);
 472: 
 473:     // *** If co-ords have been entered
 474:     if (strstr($pos, 'x')) {
 475:       $pos = str_replace(' ', '', $pos);
 476: 
 477:       $xyArray = explode('x', $pos);
 478:       list($cropStartX, $cropStartY) = $xyArray;
 479: 
 480:     } else {
 481: 
 482:       switch ($pos) {
 483:         case 'tl':
 484:           $cropStartX = 0;
 485:           $cropStartY = 0;
 486:           break;
 487: 
 488:         case 't':
 489:           $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
 490:           $cropStartY = 0;
 491:           break;
 492: 
 493:         case 'tr':
 494:           $cropStartX = $optimalWidth - $newWidth;
 495:           $cropStartY = 0;
 496:           break;
 497: 
 498:         case 'l':
 499:           $cropStartX = 0;
 500:           $cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 );
 501:           break;
 502: 
 503:         case 'm':
 504:           $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
 505:           $cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 );
 506:           break;
 507: 
 508:         case 'r':
 509:           $cropStartX = $optimalWidth - $newWidth;
 510:           $cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 );
 511:           break;
 512: 
 513:         case 'bl':
 514:           $cropStartX = 0;
 515:           $cropStartY = $optimalHeight - $newHeight;
 516:           break;
 517: 
 518:         case 'b':
 519:           $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
 520:           $cropStartY = $optimalHeight - $newHeight;
 521:           break;
 522: 
 523:         case 'br':
 524:           $cropStartX = $optimalWidth - $newWidth;
 525:           $cropStartY = $optimalHeight - $newHeight;
 526:           break;
 527: 
 528:         case 'auto':
 529:           // *** If image is a portrait crop from top, not center. v1.5
 530:           if ($optimalHeight > $optimalWidth) {
 531:             $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
 532:             $cropStartY = ($this->cropFromTopPercent /100) * $optimalHeight;
 533:           } else {
 534: 
 535:             // *** Else crop from the center
 536:             $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
 537:             $cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 );
 538:           }
 539:           break;
 540: 
 541:         default:
 542:           // *** Default to center
 543:           $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
 544:           $cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 );
 545:           break;
 546:       }
 547:     }
 548: 
 549:     return array('x' => $cropStartX, 'y' => $cropStartY);
 550:   }
 551: 
 552: ## --------------------------------------------------------
 553: 
 554:   private function getDimensions($newWidth, $newHeight, $option)
 555:     # Author:     Jarrod Oberto
 556:     # Date:       17-11-09
 557:     # Purpose:    Get new image dimensions based on user specificaions
 558:     # Param in:   $newWidth:
 559:     #             $newHeight:
 560:     # Param out:  Array of new width and height values
 561:     # Reference:
 562:     # Notes:    If $option = 3 then this function is call recursivly
 563:   #
 564:   #       To clarify the $option input:
 565:     #               0 = The exact height and width dimensions you set.
 566:     #               1 = Whatever height is passed in will be the height that
 567:     #                   is set. The width will be calculated and set automatically
 568:     #                   to a the value that keeps the original aspect ratio.
 569:     #               2 = The same but based on the width.
 570:     #               3 = Depending whether the image is landscape or portrait, this
 571:     #                   will automatically determine whether to resize via
 572:     #                   dimension 1,2 or 0.
 573:   #               4 = Resize the image as much as possible, then crop the
 574:   #         remainder.
 575:   {
 576: 
 577:         switch ((string)($option))
 578:         {
 579:             case '0':
 580:       case 'exact':
 581:                 $optimalWidth = $newWidth;
 582:                 $optimalHeight= $newHeight;
 583:                 break;
 584:             case '1':
 585:       case 'portrait':
 586:                 $dimensionsArray = $this->getSizeByFixedHeight($newWidth, $newHeight);
 587:         $optimalWidth = $dimensionsArray['optimalWidth'];
 588:         $optimalHeight = $dimensionsArray['optimalHeight'];
 589:                 break;
 590:             case '2':
 591:       case 'landscape':
 592:                 $dimensionsArray = $this->getSizeByFixedWidth($newWidth, $newHeight);
 593:         $optimalWidth = $dimensionsArray['optimalWidth'];
 594:         $optimalHeight = $dimensionsArray['optimalHeight'];
 595:                 break;
 596:             case '3':
 597:       case 'auto':
 598:                 $dimensionsArray = $this->getSizeByAuto($newWidth, $newHeight);
 599:         $optimalWidth = $dimensionsArray['optimalWidth'];
 600:         $optimalHeight = $dimensionsArray['optimalHeight'];
 601:                 break;
 602:       case '4':
 603:       case 'crop':
 604:                 $dimensionsArray = $this->getOptimalCrop($newWidth, $newHeight);
 605:         $optimalWidth = $dimensionsArray['optimalWidth'];
 606:         $optimalHeight = $dimensionsArray['optimalHeight'];
 607:                 break;
 608:         }
 609: 
 610:     return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight);
 611:   }
 612: 
 613: ## --------------------------------------------------------
 614: 
 615:     private function getSizeByFixedHeight($newWidth, $newHeight)
 616:     {
 617:     // *** If forcing is off...
 618:     if (!$this->forceStretch) {
 619: 
 620:       // *** ...check if actual height is less than target height
 621:       if ($this->height < $newHeight) {
 622:         return array('optimalWidth' => $this->width, 'optimalHeight' => $this->height);
 623:       }
 624:     }
 625: 
 626:         $ratio = $this->width / $this->height;
 627: 
 628:         $newWidth = $newHeight * $ratio;
 629: 
 630:         //return $newWidth;
 631:     return array('optimalWidth' => $newWidth, 'optimalHeight' => $newHeight);
 632:     }
 633: 
 634: ## --------------------------------------------------------
 635: 
 636:     private function getSizeByFixedWidth($newWidth, $newHeight)
 637:     {
 638:     // *** If forcing is off...
 639:     if (!$this->forceStretch) {
 640: 
 641:       // *** ...check if actual width is less than target width
 642:       if ($this->width < $newWidth) {
 643:         return array('optimalWidth' => $this->width, 'optimalHeight' => $this->height);
 644:       }
 645:     }
 646: 
 647:     $ratio = $this->height / $this->width;
 648: 
 649:         $newHeight = $newWidth * $ratio;
 650: 
 651:         //return $newHeight;
 652:     return array('optimalWidth' => $newWidth, 'optimalHeight' => $newHeight);
 653:     }
 654: 
 655: ## --------------------------------------------------------
 656: 
 657:     private function getSizeByAuto($newWidth, $newHeight)
 658:     # Author:     Jarrod Oberto
 659:     # Date:       19-08-08
 660:     # Purpose:    Depending on the height, choose to resize by 0, 1, or 2
 661:     # Param in:   The new height and new width
 662:     # Notes:
 663:     #
 664:     {
 665:     // *** If forcing is off...
 666:     if (!$this->forceStretch) {
 667: 
 668:       // *** ...check if actual size is less than target size
 669:       if ($this->width < $newWidth && $this->height < $newHeight) {
 670:         return array('optimalWidth' => $this->width, 'optimalHeight' => $this->height);
 671:       }
 672:     }
 673: 
 674:         if ($this->height < $this->width)
 675:         // *** Image to be resized is wider (landscape)
 676:         {
 677:             //$optimalWidth = $newWidth;
 678:             //$optimalHeight= $this->getSizeByFixedWidth($newWidth);
 679: 
 680:             $dimensionsArray = $this->getSizeByFixedWidth($newWidth, $newHeight);
 681:       $optimalWidth = $dimensionsArray['optimalWidth'];
 682:       $optimalHeight = $dimensionsArray['optimalHeight'];
 683:         }
 684:         elseif ($this->height > $this->width)
 685:         // *** Image to be resized is taller (portrait)
 686:         {
 687:             //$optimalWidth = $this->getSizeByFixedHeight($newHeight);
 688:             //$optimalHeight= $newHeight;
 689: 
 690:             $dimensionsArray = $this->getSizeByFixedHeight($newWidth, $newHeight);
 691:       $optimalWidth = $dimensionsArray['optimalWidth'];
 692:       $optimalHeight = $dimensionsArray['optimalHeight'];
 693:         }
 694:     else
 695:         // *** Image to be resizerd is a square
 696:         {
 697: 
 698:       if ($newHeight < $newWidth) {
 699:           //$optimalWidth = $newWidth;
 700:         //$optimalHeight= $this->getSizeByFixedWidth($newWidth);
 701:                 $dimensionsArray = $this->getSizeByFixedWidth($newWidth, $newHeight);
 702:         $optimalWidth = $dimensionsArray['optimalWidth'];
 703:         $optimalHeight = $dimensionsArray['optimalHeight'];
 704:       } else if ($newHeight > $newWidth) {
 705:           //$optimalWidth = $this->getSizeByFixedHeight($newHeight);
 706:             //$optimalHeight= $newHeight;
 707:                 $dimensionsArray = $this->getSizeByFixedHeight($newWidth, $newHeight);
 708:         $optimalWidth = $dimensionsArray['optimalWidth'];
 709:         $optimalHeight = $dimensionsArray['optimalHeight'];
 710:       } else {
 711:         // *** Sqaure being resized to a square
 712:         $optimalWidth = $newWidth;
 713:         $optimalHeight= $newHeight;
 714:       }
 715:         }
 716: 
 717:     return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight);
 718:     }
 719: 
 720: ## --------------------------------------------------------
 721: 
 722:     private function getOptimalCrop($newWidth, $newHeight)
 723:   # Author:     Jarrod Oberto
 724:     # Date:       17-11-09
 725:     # Purpose:    Get optimal crop dimensions
 726:     # Param in:   width and height as requested by user (fig 3)
 727:     # Param out:  Array of optimal width and height (fig 2)
 728:     # Reference:
 729:     # Notes:      The optimal width and height return are not the same as the
 730:   #       same as the width and height passed in. For example:
 731:   #
 732:   #
 733:   #   |-----------------|     |------------|       |-------|
 734:   #   |             |   =>  |**|      |**|   =>  |       |
 735:   #   |             |     |**|      |**|       |       |
 736:     #   |           |       |------------|       |-------|
 737:   #   |-----------------|
 738:   #        original                optimal             crop
 739:   #              size                   size               size
 740:   #  Fig          1                      2                  3
 741:   #
 742:   #       300 x 250           150 x 125          150 x 100
 743:   #
 744:   #    The optimal size is the smallest size (that is closest to the crop size)
 745:   #    while retaining proportion/ratio.
 746:   #
 747:   #  The crop size is the optimal size that has been cropped on one axis to
 748:   #  make the image the exact size specified by the user.
 749:   #
 750:   #               * represent cropped area
 751:   #
 752:   {
 753: 
 754:     // *** If forcing is off...
 755:     if (!$this->forceStretch) {
 756: 
 757:       // *** ...check if actual size is less than target size
 758:       if ($this->width < $newWidth && $this->height < $newHeight) {
 759:         return array('optimalWidth' => $this->width, 'optimalHeight' => $this->height);
 760:       }
 761:     }
 762: 
 763:     $heightRatio = $this->height / $newHeight;
 764:     $widthRatio  = $this->width /  $newWidth;
 765: 
 766:     if ($heightRatio < $widthRatio) {
 767:       $optimalRatio = $heightRatio;
 768:     } else {
 769:       $optimalRatio = $widthRatio;
 770:     }
 771: 
 772:     $optimalHeight = round( $this->height / $optimalRatio );
 773:     $optimalWidth  = round( $this->width  / $optimalRatio );
 774: 
 775:     return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight);
 776:   }
 777: 
 778: ## --------------------------------------------------------
 779: 
 780:   private function sharpen()
 781:     # Author:     Jarrod Oberto
 782:     # Date:       08 04 2011
 783:     # Purpose:    Sharpen image
 784:     # Param in:   n/a
 785:     # Param out:  n/a
 786:     # Reference:
 787:     # Notes:
 788:     # Credit:   Incorporates Joe Lencioni (August 6, 2008) code
 789:   {
 790: 
 791:     if (version_compare(PHP_VERSION, '5.1.0') >= 0) {
 792: 
 793:       // ***
 794:       if ($this->aggresiveSharpening) { # A more aggressive sharpening solution
 795: 
 796:         $sharpenMatrix = array( array( -1, -1, -1 ),
 797:                          array( -1, 16, -1 ),
 798:                          array( -1, -1, -1 ) );
 799:         $divisor = 8;
 800:         $offset = 0;
 801: 
 802:         imageconvolution($this->imageResized, $sharpenMatrix, $divisor, $offset);
 803:       }
 804:       else # More subtle and personally more desirable
 805:       {
 806:         $sharpness  = $this->findSharp($this->widthOriginal, $this->width);
 807: 
 808:         $sharpenMatrix  = array(
 809:           array(-1, -2, -1),
 810:           array(-2, $sharpness + 12, -2), //Lessen the effect of a filter by increasing the value in the center cell
 811:           array(-1, -2, -1)
 812:         );
 813:         $divisor    = $sharpness; // adjusts brightness
 814:         $offset     = 0;
 815:         imageconvolution($this->imageResized, $sharpenMatrix, $divisor, $offset);
 816:       }
 817:     }
 818:     else
 819:     {
 820:       if ($this->debug) { throw new Exception('Sharpening required PHP 5.1.0 or greater.'); }
 821:     }
 822:   }
 823: 
 824:   ## --------------------------------------------------------
 825: 
 826:   private function sharpen2($level)
 827:   {
 828:       $sharpenMatrix  = array(
 829:         array($level, $level, $level),
 830:         array($level, (8*$level)+1, $level), //Lessen the effect of a filter by increasing the value in the center cell
 831:         array($level, $level, $level)
 832:       );
 833: 
 834:   }
 835: 
 836: ## --------------------------------------------------------
 837: 
 838:   private function findSharp($orig, $final)
 839:     # Author:     Ryan Rud (http://adryrun.com)
 840:     # Purpose:    Find optimal sharpness
 841:     # Param in:   n/a
 842:     # Param out:  n/a
 843:     # Reference:
 844:     # Notes:
 845:     #
 846:   {
 847:     $final  = $final * (750.0 / $orig);
 848:     $a    = 52;
 849:     $b    = -0.27810650887573124;
 850:     $c    = .00047337278106508946;
 851: 
 852:     $result = $a + $b * $final + $c * $final * $final;
 853: 
 854:     return max(round($result), 0);
 855:   }
 856: 
 857: ## --------------------------------------------------------
 858: 
 859:   private function prepOption($option)
 860:     # Author:     Jarrod Oberto
 861:     # Purpose:    Prep option like change the passed in option to lowercase
 862:     # Param in:   (str/int) $option: eg. 'exact', 'crop'. 0, 4
 863:     # Param out:  lowercase string
 864:     # Reference:
 865:     # Notes:
 866:     #
 867:   {
 868:     if (is_array($option)) {
 869:       if (fix_strtolower($option[0]) === 'crop' && count($option) == 2) {
 870:         return 'crop';
 871:       } else {
 872:         throw new Exception('Crop resize option array is badly formatted.');
 873:       }
 874:     } else if (strpos($option, 'crop') !== false) {
 875:       return 'crop';
 876:     }
 877: 
 878:     if (is_string($option)) {
 879:       return fix_strtolower($option);
 880:     }
 881: 
 882:     return $option;
 883:   }
 884: 
 885: 
 886: /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
 887:   Presets
 888: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
 889: 
 890: #
 891: # Preset are pre-defined templates you can apply to your image.
 892: #
 893: # These are inteded to be applied to thumbnail images.
 894: #
 895: 
 896: 
 897:   public function borderPreset($preset)
 898:   {
 899:     switch ($preset)
 900:     {
 901: 
 902:       case 'simple':
 903:         $this->addBorder(7, '#fff');
 904:         $this->addBorder(6, '#f2f1f0');
 905:         $this->addBorder(2, '#fff');
 906:         $this->addBorder(1, '#ccc');
 907:         break;
 908:       default:
 909:         break;
 910:     }
 911: 
 912:   }
 913: 
 914: 
 915: /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
 916:   Draw border
 917: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
 918: 
 919:   public function addBorder($thickness = 1, $rgbArray = array(255, 255, 255))
 920:     # Author:     Jarrod Oberto
 921:     # Date:       05-05-11
 922:     # Purpose:    Add a border to the image
 923:     # Param in:
 924:     # Param out:
 925:     # Reference:
 926:     # Notes:    This border is added to the INSIDE of the image
 927:     #
 928:   {
 929:     if ($this->imageResized) {
 930: 
 931:       $rgbArray = $this->formatColor($rgbArray);
 932:       $r = $rgbArray['r'];
 933:       $g = $rgbArray['g'];
 934:       $b = $rgbArray['b'];
 935: 
 936: 
 937:       $x1 = 0;
 938:       $y1 = 0;
 939:       $x2 = imagesx($this->imageResized) - 1;
 940:       $y2 = imagesy($this->imageResized) - 1;
 941: 
 942:       $rgbArray = imagecolorallocate($this->imageResized, $r, $g, $b);
 943: 
 944: 
 945:       for($i = 0; $i < $thickness; $i++) {
 946:           imagerectangle($this->imageResized, $x1++, $y1++, $x2--, $y2--, $rgbArray);
 947:       }
 948:     }
 949:   }
 950: 
 951: 
 952: /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
 953:   Gray Scale
 954: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
 955: 
 956:   public function greyScale()
 957:     # Author:     Jarrod Oberto
 958:     # Date:       07-05-2011
 959:     # Purpose:    Make image greyscale
 960:     # Param in:   n/a
 961:     # Param out:
 962:     # Reference:
 963:     # Notes:
 964:     #
 965:   {
 966:     if ($this->imageResized) {
 967:       imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
 968:     }
 969: 
 970:   }
 971: 
 972:   ## --------------------------------------------------------
 973: 
 974:   public function greyScaleEnhanced()
 975:     # Author:     Jarrod Oberto
 976:     # Date:       07-05-2011
 977:     # Purpose:    Make image greyscale
 978:     # Param in:   n/a
 979:     # Param out:
 980:     # Reference:
 981:     # Notes:
 982:     #
 983:   {
 984:     if ($this->imageResized) {
 985:       imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
 986:       imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -15);
 987:       imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, 2);
 988:       $this->sharpen($this->width);
 989:     }
 990:   }
 991: 
 992:   ## --------------------------------------------------------
 993: 
 994:   public function greyScaleDramatic()
 995:   # Alias of gd_filter_monopin
 996:   {
 997:     $this->gd_filter_monopin();
 998:   }
 999: 
1000: 
1001: /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1002:   Black 'n White
1003: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1004: 
1005:   public function blackAndWhite()
1006:     # Author:     Jarrod Oberto
1007:     # Date:       07-05-2011
1008:     # Purpose:    Make image black and white
1009:     # Param in:   n/a
1010:     # Param out:
1011:     # Reference:
1012:     # Notes:
1013:     #
1014:   {
1015:     if ($this->imageResized) {
1016: 
1017:       imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
1018:       imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -1000);
1019:     }
1020: 
1021:   }
1022: 
1023: 
1024: /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1025:   Negative
1026: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1027: 
1028:   public function negative()
1029:     # Author:     Jarrod Oberto
1030:     # Date:       07-05-2011
1031:     # Purpose:    Make image negative
1032:     # Param in:   n/a
1033:     # Param out:
1034:     # Reference:
1035:     # Notes:
1036:     #
1037:   {
1038:     if ($this->imageResized) {
1039: 
1040:       imagefilter($this->imageResized, IMG_FILTER_NEGATE);
1041:     }
1042: 
1043:   }
1044: 
1045: 
1046: /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1047:   Sepia
1048: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1049: 
1050:   public function sepia()
1051:     # Author:     Jarrod Oberto
1052:     # Date:       07-05-2011
1053:     # Purpose:    Make image sepia
1054:     # Param in:   n/a
1055:     # Param out:
1056:     # Reference:
1057:     # Notes:
1058:     #
1059:   {
1060:     if ($this->imageResized) {
1061:       imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
1062:       imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, -10);
1063:       imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -20);
1064:       imagefilter($this->imageResized, IMG_FILTER_COLORIZE, 60, 30, -15);
1065:     }
1066:   }
1067: 
1068:   ## --------------------------------------------------------
1069: 
1070:   public function sepia2()
1071: 
1072:   {
1073:     if ($this->imageResized) {
1074: 
1075:       $total = imagecolorstotal( $this->imageResized );
1076:       for ( $i = 0; $i < $total; $i++ ) {
1077:         $index = imagecolorsforindex( $this->imageResized, $i );
1078:         $red = ( $index["red"] * 0.393 + $index["green"] * 0.769 + $index["blue"] * 0.189 ) / 1.351;
1079:         $green = ( $index["red"] * 0.349 + $index["green"] * 0.686 + $index["blue"] * 0.168 ) / 1.203;
1080:         $blue = ( $index["red"] * 0.272 + $index["green"] * 0.534 + $index["blue"] * 0.131 ) / 2.140;
1081:         imagecolorset( $this->imageResized, $i, $red, $green, $blue );
1082:       }
1083: 
1084: 
1085:     }
1086:   }
1087: 
1088: 
1089: /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1090:   Vintage
1091: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1092: 
1093:   public function vintage()
1094:   # Alias of gd_filter_monopin
1095:   {
1096:     $this->gd_filter_vintage();
1097:   }
1098: 
1099: /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1100:   Presets By Marc Hibbins
1101: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1102: 
1103: 
1104:   /** Apply 'Monopin' preset */
1105:   public function gd_filter_monopin()
1106:   {
1107: 
1108:     if ($this->imageResized) {
1109:       imagefilter($this->imageResized, IMG_FILTER_GRAYSCALE);
1110:       imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, -15);
1111:       imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -15);
1112:       $this->imageResized = $this->gd_apply_overlay($this->imageResized, 'vignette', 100);
1113:     }
1114:   }
1115: 
1116:   ## --------------------------------------------------------
1117: 
1118:   public function gd_filter_vintage()
1119:   {
1120:     if ($this->imageResized) {
1121:       $this->imageResized = $this->gd_apply_overlay($this->imageResized, 'vignette', 45);
1122:       imagefilter($this->imageResized, IMG_FILTER_BRIGHTNESS, 20);
1123:       imagefilter($this->imageResized, IMG_FILTER_CONTRAST, -35);
1124:       imagefilter($this->imageResized, IMG_FILTER_COLORIZE, 60, -10, 35);
1125:       imagefilter($this->imageResized, IMG_FILTER_SMOOTH, 7);
1126:       $this->imageResized = $this->gd_apply_overlay($this->imageResized, 'scratch', 10);
1127:     }
1128:   }
1129: 
1130:   ## --------------------------------------------------------
1131: 
1132:   /** Apply a PNG overlay */
1133:   private function gd_apply_overlay($im, $type, $amount)
1134:   #
1135:   # Original Author:    Marc Hibbins
1136:   # License:  Attribution-ShareAlike 3.0
1137:   # Purpose:
1138:   # Params in:
1139:   # Params out:
1140:   # Notes:
1141:   #
1142:   {
1143:     $width = imagesx($im);
1144:     $height = imagesy($im);
1145:     $filter = imagecreatetruecolor($width, $height);
1146: 
1147:     imagealphablending($filter, false);
1148:     imagesavealpha($filter, true);
1149: 
1150:     $transparent = imagecolorallocatealpha($filter, 255, 255, 255, 127);
1151:     imagefilledrectangle($filter, 0, 0, $width, $height, $transparent);
1152: 
1153:     // *** Resize overlay
1154:     $overlay = $this->filterOverlayPath . '/' . $type . '.png';
1155:     $png = imagecreatefrompng($overlay);
1156:     imagecopyresampled($filter, $png, 0, 0, 0, 0, $width, $height, imagesx($png), imagesy($png));
1157: 
1158:     $comp = imagecreatetruecolor($width, $height);
1159:     imagecopy($comp, $im, 0, 0, 0, 0, $width, $height);
1160:     imagecopy($comp, $filter, 0, 0, 0, 0, $width, $height);
1161:     imagecopymerge($im, $comp, 0, 0, 0, 0, $width, $height, $amount);
1162: 
1163:     imagedestroy($comp);
1164:     return $im;
1165:   }
1166: 
1167: 
1168: /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1169:   Colorise
1170: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1171: 
1172:   public function image_colorize($rgb) {
1173:       imagetruecolortopalette($this->imageResized,true,256);
1174:     $numColors = imagecolorstotal($this->imageResized);
1175: 
1176:     for ($x = 0; $x < $numColors; $x++) {
1177:     list($r,$g,$b) = array_values(imagecolorsforindex($this->imageResized,$x));
1178: 
1179:     // calculate grayscale in percent
1180:     $grayscale = ($r + $g + $b) / 3 / 0xff;
1181: 
1182:       imagecolorset($this->imageResized,$x,
1183:       $grayscale * $rgb[0],
1184:       $grayscale * $rgb[1],
1185:       $grayscale * $rgb[2]
1186:     );
1187: 
1188:     }
1189: 
1190:     return true;
1191:   }
1192: 
1193: 
1194: /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1195:   Reflection
1196: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1197: 
1198:   public function addReflection($reflectionHeight = 50, $startingTransparency = 30, $inside = false, $bgColor = '#fff', $stretch=false, $divider = 0)
1199:   {
1200: 
1201:     // *** Convert color
1202:     $rgbArray = $this->formatColor($bgColor);
1203:     $r = $rgbArray['r'];
1204:     $g = $rgbArray['g'];
1205:     $b = $rgbArray['b'];
1206: 
1207:     $im = $this->imageResized;
1208:     $li = imagecreatetruecolor($this->width, 1);
1209: 
1210:     $bgc = imagecolorallocate($li, $r, $g, $b);
1211:     imagefilledrectangle($li, 0, 0, $this->width, 1, $bgc);
1212: 
1213:     $bg = imagecreatetruecolor($this->width, $reflectionHeight);
1214:     $wh = imagecolorallocate($im, 255, 255, 255);
1215: 
1216:     $im = imagerotate($im, -180, $wh);
1217:     imagecopyresampled($bg, $im, 0, 0, 0, 0, $this->width, $this->height, $this->width, $this->height);
1218: 
1219:     $im = $bg;
1220: 
1221:     $bg = imagecreatetruecolor($this->width, $reflectionHeight);
1222: 
1223:     for ($x = 0; $x < $this->width; $x++) {
1224:       imagecopy($bg, $im, $x, 0, $this->width-$x -1, 0, 1, $reflectionHeight);
1225:     }
1226:     $im = $bg;
1227: 
1228:     $transaprencyAmount = $this->invertTransparency($startingTransparency, 100);
1229: 
1230: 
1231:     // *** Fade
1232:     if ($stretch) {
1233:       $step = 100/($reflectionHeight + $startingTransparency);
1234:     } else{
1235:       $step = 100/$reflectionHeight;
1236:     }
1237:     for($i=0; $i<=$reflectionHeight; $i++){
1238: 
1239:       if($startingTransparency>100) $startingTransparency = 100;
1240:       if($startingTransparency< 1) $startingTransparency = 1;
1241:       imagecopymerge($bg, $li, 0, $i, 0, 0, $this->width, 1, $startingTransparency);
1242:       $startingTransparency+=$step;
1243:     }
1244: 
1245:     // *** Apply fade
1246:     imagecopymerge($im, $li, 0, 0, 0, 0, $this->width, $divider, 100); // Divider
1247: 
1248: 
1249:     // *** width, height of reflection.
1250:     $x = imagesx($im);
1251:     $y = imagesy($im);
1252: 
1253: 
1254:     // *** Determines if the reflection should be displayed inside or outside the image
1255:     if ($inside) {
1256: 
1257:       // Create new blank image with sizes.
1258:       $final = imagecreatetruecolor($this->width, $this->height);
1259: 
1260:       imagecopymerge ($final, $this->imageResized, 0, 0, 0, $reflectionHeight, $this->width, $this->height - $reflectionHeight, 100);
1261:       imagecopymerge ($final, $im, 0, $this->height - $reflectionHeight, 0, 0, $x, $y, 100);
1262: 
1263:     } else {
1264: 
1265:       // Create new blank image with sizes.
1266:       $final = imagecreatetruecolor($this->width, $this->height + $y);
1267: 
1268:       imagecopymerge ($final, $this->imageResized, 0, 0, 0, 0, $this->width, $this->height, 100);
1269:       imagecopymerge ($final, $im, 0, $this->height, 0, 0, $x, $y, 100);
1270:     }
1271: 
1272:     $this->imageResized = $final;
1273: 
1274:     imagedestroy($li);
1275:     imagedestroy($im);
1276:   }
1277: 
1278: 
1279: /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1280:   Rotate
1281: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1282: 
1283:   public function rotate($value = 90, $bgColor = 'transparent')
1284:     # Author:     Jarrod Oberto
1285:     # Date:       07-05-2011
1286:     # Purpose:    Rotate image
1287:     # Param in:   (mixed) $degrees: (int) number of degress to rotate image
1288:   #               (str) param "left": rotate left
1289:   #               (str) param "right": rotate right
1290:   #               (str) param "upside": upside-down image
1291:     # Param out:
1292:     # Reference:
1293:     # Notes:    The default direction of imageRotate() is counter clockwise.
1294:     #
1295:   {
1296:     if ($this->imageResized) {
1297: 
1298:       if (is_integer($value)) {
1299:         $degrees = $value;
1300:       }
1301: 
1302:       // *** Convert color
1303:       $rgbArray = $this->formatColor($bgColor);
1304:       $r = $rgbArray['r'];
1305:       $g = $rgbArray['g'];
1306:       $b = $rgbArray['b'];
1307:       if (isset($rgbArray['a'])) {$a = $rgbArray['a']; }
1308: 
1309:       if (is_string($value)) {
1310: 
1311:         $value = fix_strtolower($value);
1312: 
1313:         switch ($value) {
1314:           case 'left':
1315:             $degrees = 90;
1316:             break;
1317:           case 'right':
1318:             $degrees = 270;
1319:             break;
1320:           case 'upside':
1321:             $degrees = 180;
1322:             break;
1323:           default:
1324:             break;
1325:         }
1326: 
1327:       }
1328: 
1329:       // *** The default direction of imageRotate() is counter clockwise
1330:       //   * This makes it clockwise
1331:       $degrees = 360 - $degrees;
1332: 
1333:       // *** Create background color
1334:       $bg = imagecolorallocatealpha($this->imageResized, $r, $g, $b, $a);
1335: 
1336:       // *** Fill with background
1337:         imagefill($this->imageResized, 0, 0 , $bg);
1338: 
1339:       // *** Rotate
1340:       $this->imageResized = imagerotate($this->imageResized, $degrees, $bg); // Rotate 45 degrees and allocated the transparent colour as the one to make transparent (obviously)
1341: 
1342:       // Ensure alpha transparency
1343:         imagesavealpha($this->imageResized,true);
1344: 
1345:     }
1346:   }
1347: 
1348: 
1349: /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1350:   Round corners
1351: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1352: 
1353:   public function roundCorners($radius = 5,  $bgColor = 'transparent')
1354:     # Author:     Jarrod Oberto
1355:     # Date:       19-05-2011
1356:     # Purpose:    Create rounded corners on your image
1357:     # Param in:   (int) radius = the amount of curvature
1358:   #       (mixed) $bgColor = the corner background color
1359:     # Param out:  n/a
1360:     # Reference:
1361:     # Notes:
1362:     #
1363:   {
1364: 
1365:     // *** Check if the user wants transparency
1366:     $isTransparent = false;
1367:     if (!is_array($bgColor)) {
1368:       if (fix_strtolower($bgColor) === 'transparent') {
1369:         $isTransparent = true;
1370:       }
1371:     }
1372: 
1373: 
1374:     // *** If we use transparency, we need to color our curved mask with a unique color
1375:     if ($isTransparent) {
1376:       $bgColor = $this->findUnusedGreen();
1377:     }
1378: 
1379:     // *** Convert color
1380:     $rgbArray = $this->formatColor($bgColor);
1381:     $r = $rgbArray['r'];
1382:     $g = $rgbArray['g'];
1383:     $b = $rgbArray['b'];
1384:     if (isset($rgbArray['a'])) {$a = $rgbArray['a']; }
1385: 
1386: 
1387: 
1388:     // *** Create top-left corner mask (square)
1389:     $cornerImg = imagecreatetruecolor($radius, $radius);
1390:     //$cornerImg = imagecreate($radius, $radius);
1391: 
1392:       //imagealphablending($cornerImg, true);
1393:       //imagesavealpha($cornerImg, true);
1394: 
1395:       //imagealphablending($this->imageResized, false);
1396:       //imagesavealpha($this->imageResized, true);
1397: 
1398:     // *** Give it a color
1399:     $maskColor = imagecolorallocate($cornerImg, 0, 0, 0);
1400: 
1401: 
1402: 
1403:     // *** Replace the mask color (black) to transparent
1404:     imagecolortransparent($cornerImg, $maskColor);
1405: 
1406: 
1407: 
1408:     // *** Create the image background color
1409:     $imagebgColor = imagecolorallocate($cornerImg, $r, $g, $b);
1410: 
1411: 
1412: 
1413:     // *** Fill the corner area to the user defined color
1414:     imagefill($cornerImg, 0, 0, $imagebgColor);
1415: 
1416: 
1417:     imagefilledellipse($cornerImg, $radius, $radius, $radius * 2, $radius * 2, $maskColor );
1418: 
1419: 
1420:     // *** Map to top left corner
1421:     imagecopymerge($this->imageResized, $cornerImg, 0, 0, 0, 0, $radius, $radius, 100); #tl
1422: 
1423:     // *** Map rounded corner to other corners by rotating and applying the mask
1424:     $cornerImg = imagerotate($cornerImg, 90, 0);
1425:     imagecopymerge($this->imageResized, $cornerImg, 0, $this->height - $radius, 0, 0, $radius, $radius, 100); #bl
1426: 
1427:     $cornerImg = imagerotate($cornerImg, 90, 0);
1428:     imagecopymerge($this->imageResized, $cornerImg, $this->width - $radius, $this->height - $radius, 0, 0, $radius, $radius, 100); #br
1429: 
1430:     $cornerImg = imagerotate($cornerImg, 90, 0);
1431:     imagecopymerge($this->imageResized, $cornerImg, $this->width - $radius, 0, 0, 0, $radius, $radius, 100); #tr
1432: 
1433: 
1434:     // *** If corners are to be transparent, we fill our chromakey color as transparent.
1435:     if ($isTransparent) {
1436:       //imagecolortransparent($this->imageResized, $imagebgColor);
1437:       $this->imageResized = $this->transparentImage($this->imageResized);
1438:       imagesavealpha($this->imageResized, true);
1439:     }
1440: 
1441:   }
1442: 
1443: 
1444: /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1445:   Shadow
1446: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1447: 
1448:   public function addShadow($shadowAngle=45, $blur=15, $bgColor='transparent')
1449:   #
1450:   # Author:   Jarrod Oberto (Adapted from Pascal Naidon)
1451:   # Ref:    http://www.les-stooges.org/pascal/webdesign/vignettes/index.php?la=en
1452:   # Purpose:  Add a drop shadow to your image
1453:   # Params in:  (int) $angle: the angle of the shadow
1454:   #       (int) $blur: the blur distance
1455:   #       (mixed) $bgColor: the color of the background
1456:   # Params out:
1457:   # Notes:
1458:   #
1459:   {
1460:     // *** A higher number results in a smoother shadow
1461:     define('STEPS', $blur*2);
1462: 
1463:     // *** Set the shadow distance
1464:     $shadowDistance = $blur*0.25;
1465: 
1466:     // *** Set blur width and height
1467:     $blurWidth = $blurHeight = $blur;
1468: 
1469: 
1470:     if ($shadowAngle == 0) {
1471:       $distWidth = 0;
1472:       $distHeight = 0;
1473:     } else {
1474:       $distWidth = $shadowDistance * cos(deg2rad($shadowAngle));
1475:       $distHeight = $shadowDistance * sin(deg2rad($shadowAngle));
1476:     }
1477: 
1478: 
1479:     // *** Convert color
1480:     if (fix_strtolower($bgColor) !== 'transparent') {
1481:       $rgbArray = $this->formatColor($bgColor);
1482:       $r0 = $rgbArray['r'];
1483:       $g0 = $rgbArray['g'];
1484:       $b0 = $rgbArray['b'];
1485:     }
1486: 
1487: 
1488:     $image = $this->imageResized;
1489:     $width = $this->width;
1490:     $height = $this->height;
1491: 
1492: 
1493:       $newImage = imagecreatetruecolor($width, $height);
1494:     imagecopyresampled($newImage, $image, 0, 0, 0, 0, $width, $height, $width, $height);
1495: 
1496: 
1497:     // *** RGB
1498:     $rgb = imagecreatetruecolor($width+$blurWidth,$height+$blurHeight);
1499:     $colour = imagecolorallocate($rgb, 0, 0, 0);
1500:     imagefilledrectangle($rgb, 0, 0, $width+$blurWidth, $height+$blurHeight, $colour);
1501:     $colour = imagecolorallocate($rgb, 255, 255, 255);
1502:     //imagefilledrectangle($rgb, $blurWidth*0.5-$distWidth, $blurHeight*0.5-$distHeight, $width+$blurWidth*0.5-$distWidth, $height+$blurWidth*0.5-$distHeight, $colour);
1503:     imagefilledrectangle($rgb, $blurWidth*0.5-$distWidth, $blurHeight*0.5-$distHeight, $width+$blurWidth*0.5-$distWidth, $height+$blurWidth*0.5-$distHeight, $colour);
1504:     //imagecopymerge($rgb, $newImage, 1+$blurWidth*0.5-$distWidth, 1+$blurHeight*0.5-$distHeight, 0,0, $width, $height, 100);
1505:     imagecopymerge($rgb, $newImage, $blurWidth*0.5-$distWidth, $blurHeight*0.5-$distHeight, 0,0, $width+$blurWidth, $height+$blurHeight, 100);
1506: 
1507: 
1508:     // *** Shadow (alpha)
1509:     $shadow = imagecreatetruecolor($width+$blurWidth,$height+$blurHeight);
1510:       imagealphablending($shadow, false);
1511:     $colour = imagecolorallocate($shadow, 0, 0, 0);
1512:     imagefilledrectangle($shadow, 0, 0, $width+$blurWidth, $height+$blurHeight, $colour);
1513: 
1514: 
1515:     for($i=0;$i<=STEPS;$i++) {
1516: 
1517:       $t = ((1.0*$i)/STEPS);
1518:       $intensity = 255*$t*$t;
1519: 
1520:       $colour = imagecolorallocate($shadow, $intensity, $intensity, $intensity);
1521:       $points = array(
1522:         $blurWidth*$t,        $blurHeight,     // Point 1 (x, y)
1523:         $blurWidth,         $blurHeight*$t,  // Point 2 (x, y)
1524:         $width,           $blurHeight*$t,  // Point 3 (x, y)
1525:         $width+$blurWidth*(1-$t), $blurHeight,     // Point 4 (x, y)
1526:         $width+$blurWidth*(1-$t), $height,     // Point 5 (x, y)
1527:         $width,           $height+$blurHeight*(1-$t),  // Point 6 (x, y)
1528:         $blurWidth,         $height+$blurHeight*(1-$t),  // Point 7 (x, y)
1529:         $blurWidth*$t,        $height      // Point 8 (x, y)
1530:       );
1531:       imagepolygon($shadow, $points, 8, $colour);
1532:     }
1533: 
1534:     for($i=0;$i<=STEPS;$i++) {
1535: 
1536:       $t = ((1.0*$i)/STEPS);
1537:         $intensity = 255*$t*$t;
1538: 
1539:       $colour = imagecolorallocate($shadow, $intensity, $intensity, $intensity);
1540:       imagefilledarc($shadow, $blurWidth-1, $blurHeight-1, 2*(1-$t)*$blurWidth, 2*(1-$t)*$blurHeight, 180, 268, $colour, IMG_ARC_PIE);
1541:       imagefilledarc($shadow, $width, $blurHeight-1, 2*(1-$t)*$blurWidth, 2*(1-$t)*$blurHeight, 270, 358, $colour, IMG_ARC_PIE);
1542:       imagefilledarc($shadow, $width, $height, 2*(1-$t)*$blurWidth, 2*(1-$t)*$blurHeight, 0, 90, $colour, IMG_ARC_PIE);
1543:       imagefilledarc($shadow, $blurWidth-1, $height, 2*(1-$t)*$blurWidth, 2*(1-$t)*$blurHeight, 90, 180, $colour, IMG_ARC_PIE);
1544:     }
1545: 
1546: 
1547:     $colour = imagecolorallocate($shadow, 255, 255, 255);
1548:     imagefilledrectangle($shadow, $blurWidth, $blurHeight, $width, $height, $colour);
1549:     imagefilledrectangle($shadow, $blurWidth*0.5-$distWidth, $blurHeight*0.5-$distHeight, $width+$blurWidth*0.5-1-$distWidth, $height+$blurHeight*0.5-1-$distHeight, $colour);
1550: 
1551: 
1552:     // *** The magic
1553:         imagealphablending($rgb, false);
1554: 
1555:         for ($theX=0;$theX<imagesx($rgb);$theX++){
1556:       for ($theY=0;$theY<imagesy($rgb);$theY++){
1557: 
1558:         // *** Get the RGB values for every pixel of the RGB image
1559:         $colArray = imagecolorat($rgb,$theX,$theY);
1560:         $r = ($colArray >> 16) & 0xFF;
1561:         $g = ($colArray >> 8) & 0xFF;
1562:         $b = $colArray & 0xFF;
1563: 
1564:         // *** Get the alpha value for every pixel of the shadow image
1565:         $colArray = imagecolorat($shadow,$theX,$theY);
1566:         $a = $colArray & 0xFF;
1567:         $a = 127-floor($a/2);
1568:         $t = $a/128.0;
1569: 
1570:         // *** Create color
1571:         if(fix_strtolower($bgColor) === 'transparent') {
1572:           $myColour = imagecolorallocatealpha($rgb,$r,$g,$b,$a);
1573:         } else {
1574:           $myColour = imagecolorallocate($rgb,$r*(1.0-$t)+$r0*$t,$g*(1.0-$t)+$g0*$t,$b*(1.0-$t)+$b0*$t);
1575:         }
1576: 
1577:         // *** Add color to new rgb image
1578:         imagesetpixel($rgb, $theX, $theY, $myColour);
1579:       }
1580:     }
1581: 
1582:     imagealphablending($rgb, true);
1583:     imagesavealpha($rgb, true);
1584: 
1585:     $this->imageResized = $rgb;
1586: 
1587:     imagedestroy($image);
1588:     imagedestroy($newImage);
1589:     imagedestroy($shadow);
1590:   }
1591: 
1592: 
1593: /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1594:   Add Caption Box
1595: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1596: 
1597:   public function addCaptionBox($side='b', $thickness=50, $padding=0, $bgColor='#000', $transaprencyAmount=30)
1598:   #
1599:   # Author:   Jarrod Oberto
1600:   # Date:   26 May 2011
1601:   # Purpose:  Add a caption box
1602:   # Params in:  (str) $side: the side to add the caption box (t, r, b, or l).
1603:   #       (int) $thickness: how thick you want the caption box to be.
1604:   #       (mixed) $bgColor: The color of the caption box.
1605:   #       (int) $transaprencyAmount: The amount of transparency to be
1606:   #       applied.
1607:   # Params out: n/a
1608:   # Notes:
1609:   #
1610:   {
1611:       $side = fix_strtolower($side);
1612: 
1613:       // *** Convert color
1614:       $rgbArray = $this->formatColor($bgColor);
1615:       $r = $rgbArray['r'];
1616:       $g = $rgbArray['g'];
1617:       $b = $rgbArray['b'];
1618: 
1619:       $positionArray = $this->calculateCaptionBoxPosition($side, $thickness, $padding);
1620: 
1621:       // *** Store incase we want to use method addTextToCaptionBox()
1622:       $this->captionBoxPositionArray = $positionArray;
1623: 
1624: 
1625:       $transaprencyAmount = $this->invertTransparency($transaprencyAmount, 127, false);
1626:       $transparent = imagecolorallocatealpha($this->imageResized, $r, $g, $b, $transaprencyAmount);
1627:       imagefilledrectangle($this->imageResized, $positionArray['x1'], $positionArray['y1'], $positionArray['x2'], $positionArray['y2'], $transparent);
1628:   }
1629: 
1630:   ## --------------------------------------------------------
1631: 
1632:   public function addTextToCaptionBox($text, $fontColor='#fff', $fontSize = 12, $angle = 0, $font = null)
1633:   #
1634:   # Author:   Jarrod Oberto
1635:   # Date:   03 Aug 11
1636:   # Purpose:  Simplify adding text to a caption box by automatically
1637:   #       locating the center of the caption box
1638:   # Params in:  The usually text paams (less a couple)
1639:   # Params out: n/a
1640:   # Notes:
1641:   #
1642:   {
1643: 
1644:     // *** Get the caption box measurements
1645:     if (count($this->captionBoxPositionArray) == 4) {
1646:       $x1 = $this->captionBoxPositionArray['x1'];
1647:       $x2 = $this->captionBoxPositionArray['x2'];
1648:       $y1 = $this->captionBoxPositionArray['y1'];
1649:       $y2 = $this->captionBoxPositionArray['y2'];
1650:     } else {
1651:       if ($this->debug) { throw new Exception('No caption box found.'); }else{ return false; }
1652:     }
1653: 
1654: 
1655:     // *** Get text font
1656:     $font = $this->getTextFont($font);
1657: 
1658:     // *** Get text size
1659:     $textSizeArray = $this->getTextSize($fontSize, $angle, $font, $text);
1660:     $textWidth = $textSizeArray['width'];
1661:     $textHeight = $textSizeArray['height'];
1662: 
1663:     // *** Find the width/height middle points
1664:     $boxXMiddle = (($x2 - $x1) / 2);
1665:     $boxYMiddle = (($y2 - $y1) / 2);
1666: 
1667:     // *** Box middle - half the text width/height
1668:     $xPos = ($x1 + $boxXMiddle) - ($textWidth/2);
1669:     $yPos = ($y1 + $boxYMiddle) - ($textHeight/2);
1670: 
1671:     $pos = $xPos . 'x' . $yPos;
1672: 
1673:     $this->addText($text, $pos, $padding = 0, $fontColor, $fontSize, $angle, $font);
1674: 
1675:   }
1676: 
1677:   ## --------------------------------------------------------
1678: 
1679:   private function calculateCaptionBoxPosition($side, $thickness, $padding)
1680:   {
1681:     $positionArray = array();
1682: 
1683:     switch ($side) {
1684:       case 't':
1685:         $positionArray['x1'] = 0;
1686:         $positionArray['y1'] = $padding;
1687:         $positionArray['x2'] = $this->width;
1688:         $positionArray['y2'] = $thickness + $padding;
1689:         break;
1690:       case 'r':
1691:         $positionArray['x1'] = $this->width - $thickness - $padding;
1692:         $positionArray['y1'] = 0;
1693:         $positionArray['x2'] = $this->width - $padding;
1694:         $positionArray['y2'] = $this->height;
1695:         break;
1696:       case 'b':
1697:         $positionArray['x1'] = 0;
1698:         $positionArray['y1'] = $this->height - $thickness - $padding;
1699:         $positionArray['x2'] = $this->width;
1700:         $positionArray['y2'] = $this->height - $padding;
1701:         break;
1702:       case 'l':
1703:         $positionArray['x1'] = $padding;
1704:         $positionArray['y1'] = 0;
1705:         $positionArray['x2'] = $thickness + $padding;
1706:         $positionArray['y2'] = $this->height;
1707:         break;
1708: 
1709:       default:
1710:         break;
1711:     }
1712: 
1713:     return $positionArray;
1714: 
1715:   }
1716: 
1717: /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
1718:   Get EXIF Data
1719: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
1720: 
1721:   public function getExif($debug=false)
1722:     # Author:     Jarrod Oberto
1723:     # Date:       07-05-2011
1724:     # Purpose:    Get image EXIF data
1725:     # Param in:   n/a
1726:     # Param out:  An associate array of EXIF data
1727:     # Reference:
1728:     # Notes:
1729:     # 23 May 13 : added orientation flag -jco
1730:     #
1731:   {
1732: 
1733:     if (!$this->debug || !$debug) { $debug = false; }
1734: 
1735:     // *** Check all is good - check the EXIF library exists and the file exists, too.
1736:     if (!$this->testEXIFInstalled()) { if ($debug) { throw new Exception('The EXIF Library is not installed.'); }else{ return array(); }};
1737:     if (!file_exists($this->fileName)) { if ($debug) { throw new Exception('Image not found.'); }else{ return array(); }};
1738:     if ($this->fileExtension !== '.jpg') { if ($debug) { throw new Exception('Metadata not supported for this image type.'); }else{ return array(); }};
1739:     $exifData = exif_read_data($this->fileName, 'IFD0');
1740: 
1741:     // *** Format the apperture value
1742:     $ev = $exifData['ApertureValue'];
1743:     $apPeicesArray = explode('/', $ev);
1744:     if (count($apPeicesArray) == 2) {
1745:       $apertureValue = round($apPeicesArray[0] / $apPeicesArray[1], 2, PHP_ROUND_HALF_DOWN) . ' EV';
1746:     } else { $apertureValue = '';}
1747: 
1748:     // *** Format the focal length
1749:     $focalLength = $exifData['FocalLength'];
1750:     $flPeicesArray = explode('/', $focalLength);
1751:     if (count($flPeicesArray) == 2) {
1752:       $focalLength = $flPeicesArray[0] / $flPeicesArray[1] . '.0 mm';
1753:     } else { $focalLength = '';}
1754: 
1755:     // *** Format fNumber
1756:     $fNumber = $exifData['FNumber'];
1757:     $fnPeicesArray = explode('/', $fNumber);
1758:     if (count($fnPeicesArray) == 2) {
1759:       $fNumber = $fnPeicesArray[0] / $fnPeicesArray[1];
1760:     } else { $fNumber = '';}
1761: 
1762:     // *** Resolve ExposureProgram
1763:     if (isset($exifData['ExposureProgram'])) { $ep =  $exifData['ExposureProgram']; }
1764:     if (isset($ep)) { $ep = $this->resolveExposureProgram($ep); }
1765: 
1766: 
1767:     // *** Resolve MeteringMode
1768:     $mm = $exifData['MeteringMode'];
1769:     $mm = $this->resolveMeteringMode($mm);
1770: 
1771:     // *** Resolve Flash
1772:     $flash = $exifData['Flash'];
1773:     $flash = $this->resolveFlash($flash);
1774: 
1775: 
1776:     if (isset($exifData['Make'])) {
1777:       $exifDataArray['make'] = $exifData['Make'];
1778:     } else { $exifDataArray['make'] = ''; }
1779: 
1780:     if (isset($exifData['Model'])) {
1781:       $exifDataArray['model'] = $exifData['Model'];
1782:     } else { $exifDataArray['model'] = ''; }
1783: 
1784:     if (isset($exifData['DateTime'])) {
1785:       $exifDataArray['date'] = $exifData['DateTime'];
1786:     } else { $exifDataArray['date'] = ''; }
1787: 
1788:     if (isset($exifData['ExposureTime'])) {
1789:       $exifDataArray['exposure time'] = $exifData['ExposureTime'] . ' sec.';
1790:     } else { $exifDataArray['exposure time'] = ''; }
1791: 
1792:     if ($apertureValue != '') {
1793:       $exifDataArray['aperture value'] = $apertureValue;
1794:     } else { $exifDataArray['aperture value'] = ''; }
1795: 
1796:     if (isset($exifData['COMPUTED']['ApertureFNumber'])) {
1797:       $exifDataArray['f-stop'] = $exifData['COMPUTED']['ApertureFNumber'];
1798:     } else { $exifDataArray['f-stop'] = ''; }
1799: 
1800:     if (isset($exifData['FNumber'])) {
1801:       $exifDataArray['fnumber'] = $exifData['FNumber'];
1802:     } else { $exifDataArray['fnumber'] = ''; }
1803: 
1804:     if ($fNumber != '') {
1805:       $exifDataArray['fnumber value'] = $fNumber;
1806:     } else { $exifDataArray['fnumber value'] = ''; }
1807: 
1808:     if (isset($exifData['ISOSpeedRatings'])) {
1809:       $exifDataArray['iso'] = $exifData['ISOSpeedRatings'];
1810:     } else { $exifDataArray['iso'] = ''; }
1811: 
1812:     if ($focalLength != '') {
1813:       $exifDataArray['focal length'] = $focalLength;
1814:     } else { $exifDataArray['focal length'] = ''; }
1815: 
1816:     if (isset($ep)) {
1817:       $exifDataArray['exposure program'] = $ep;
1818:     } else { $exifDataArray['exposure program'] = ''; }
1819: 
1820:     if ($mm != '') {
1821:       $exifDataArray['metering mode'] = $mm;
1822:     } else { $exifDataArray['metering mode'] = ''; }
1823: 
1824:     if ($flash != '') {
1825:       $exifDataArray['flash status'] = $flash;
1826:     } else { $exifDataArray['flash status'] = ''; }
1827: 
1828:     if (isset($exifData['Artist'])) {
1829:       $exifDataArray['creator'] = $exifData['Artist'] ;
1830:     } else { $exifDataArray['creator'] = ''; }
1831: 
1832:     if (isset($exifData['Copyright'])) {
1833:       $exifDataArray['copyright'] = $exifData['Copyright'];
1834:     } else { $exifDataArray['copyright'] = ''; }
1835: 
1836:     // *** Orientation
1837:     if (isset($exifData['Orientation'])) {
1838:         $exifDataArray['orientation'] = $exifData['Orientation'];
1839:     } else { $exifDataArray['orientation'] = ''; }
1840: 
1841:     return $exifDataArray;
1842:   }
1843: 
1844:   ## --------------------------------------------------------
1845: 
1846:   private function resolveExposureProgram($ep)
1847:   {
1848:     switch ($ep) {
1849:       case 0:
1850:         $ep = '';
1851:         break;
1852:       case 1:
1853:         $ep = 'manual';
1854:         break;
1855:       case 2:
1856:         $ep = 'normal program';
1857:         break;
1858:       case 3:
1859:         $ep = 'aperture priority';
1860:         break;
1861:       case 4:
1862:         $ep = 'shutter priority';
1863:         break;
1864:       case 5:
1865:         $ep = 'creative program';
1866:         break;
1867:       case 6:
1868:         $ep = 'action program';
1869:         break;
1870:       case 7:
1871:         $ep = 'portrait mode';
1872:         break;
1873:       case 8:
1874:         $ep = 'landscape mode';
1875:         break;
1876: 
1877:       default:
1878:         break;
1879:     }
1880: 
1881:     return $ep;
1882:   }
1883: 
1884:   ## --------------------------------------------------------
1885: 
1886:   private function resolveMeteringMode($mm)
1887:   {
1888:     switch ($mm) {
1889:       case 0:
1890:         $mm = 'unknown';
1891:         break;
1892:       case 1:
1893:         $mm = 'average';
1894:         break;
1895:       case 2:
1896:         $mm = 'center weighted average';
1897:         break;
1898:       case 3:
1899:         $mm = 'spot';
1900:         break;
1901:       case 4:
1902:         $mm = 'multi spot';
1903:         break;
1904:       case 5:
1905:         $mm = 'pattern';
1906:         break;
1907:       case 6:
1908:         $mm = 'partial';
1909:         break;
1910:       case 255:
1911:         $mm = 'other';
1912:         break;
1913: 
1914:       default:
1915:         break;
1916:     }
1917: 
1918:     return $mm;
1919:   }
1920: 
1921:   ## --------------------------------------------------------
1922: 
1923:   private function resolveFlash($flash)
1924:   {
1925:     switch ($flash) {
1926:       case 0:
1927:         $flash = 'flash did not fire';
1928:         break;
1929:       case 1:
1930:         $flash = 'flash fired';
1931:         break;
1932:       case 5:
1933:         $flash = 'strobe return light not detected';
1934:         break;
1935:       case 7:
1936:         $flash = 'strobe return light detected';
1937:         break;
1938:       case 9:
1939:         $flash = 'flash fired, compulsory flash mode';
1940:         break;
1941:       case 13:
1942:         $flash = 'flash fired, compulsory flash mode, return light not detected';
1943:         break;
1944:       case 15:
1945:         $flash = 'flash fired, compulsory flash mode, return light detected';
1946:         break;
1947:       case 16:
1948:         $flash = 'flash did not fire, compulsory flash mode';
1949:         break;
1950:       case 24:
1951:         $flash = 'flash did not fire, auto mode';
1952:         break;
1953:       case 25:
1954:         $flash = 'flash fired, auto mode';
1955:         break;
1956:       case 29:
1957:         $flash = 'flash fired, auto mode, return light not detected';
1958:         break;
1959:       case 31:
1960:         $flash = 'flash fired, auto mode, return light detected';
1961:         break;
1962:       case 32:
1963:         $flash = 'no flash function';
1964:         break;
1965:       case 65:
1966:         $flash = 'flash fired, red-eye reduction mode';
1967:         break;
1968:       case 69:
1969:         $flash = 'flash fired, red-eye reduction mode, return light not detected';
1970:         break;
1971:       case 71:
1972:         $flash = 'flash fired, red-eye reduction mode, return light detected';
1973:         break;
1974:       case 73:
1975:         $flash = 'flash fired, compulsory flash mode, red-eye reduction mode';
1976:         break;
1977:       case 77:
1978:         $flash = 'flash fired, compulsory flash mode, red-eye reduction mode, return light not detected';
1979:         break;
1980:       case 79:
1981:         $flash = 'flash fired, compulsory flash mode, red-eye reduction mode, return light detected';
1982:         break;
1983:       case 89:
1984:         $flash = 'flash fired, auto mode, red-eye reduction mode';
1985:         break;
1986:       case 93:
1987:         $flash = 'flash fired, auto mode, return light not detected, red-eye reduction mode';
1988:         break;
1989:       case 95:
1990:         $flash = 'flash fired, auto mode, return light detected, red-eye reduction mode';
1991:         break;
1992: 
1993:       default:
1994:         break;
1995:     }
1996: 
1997:     return $flash;
1998: 
1999:   }
2000: 
2001: 
2002: /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
2003:   Get IPTC Data
2004: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
2005: 
2006: 
2007: /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
2008:   Write IPTC Data
2009: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
2010: 
2011:   public function writeIPTCcaption($value)
2012:   # Caption
2013:   {
2014:     $this->writeIPTC(120, $value);
2015:   }
2016: 
2017:   ## --------------------------------------------------------
2018: 
2019:   public function writeIPTCwriter($value)
2020:   {
2021:     //$this->writeIPTC(65, $value);
2022:   }
2023: 
2024:   ## --------------------------------------------------------
2025: 
2026:   private function writeIPTC($dat, $value)
2027:   {
2028: 
2029:     # LIMIT TO JPG
2030: 
2031:     $caption_block = $this->iptc_maketag(2, $dat, $value);
2032:     $image_string = iptcembed($caption_block, $this->fileName);
2033:     file_put_contents('iptc.jpg', $image_string);
2034:   }
2035: 
2036: ## --------------------------------------------------------
2037: 
2038:   private function iptc_maketag($rec,$dat,$val)
2039:   # Author:   Thies C. Arntzen
2040:   # Purpose:    Function to format the new IPTC text
2041:   # Param in:   $rec: Application record. (We’re working with #2)
2042:   #       $dat: Index. (120 for caption, 118 for contact. See the IPTC IIM
2043:   #         specification:
2044:   #         http://www.iptc.org/std/IIM/4.1/specification/IIMV4.1.pdf
2045:   #       $val: Value/data/text. Make sure this is within the length
2046:   #         constraints of the IPTC IIM specification
2047:   # Ref:      http://blog.peterhaza.no/working-with-image-meta-data-in-exif-and-iptc-headers-from-php/
2048:   #       http://php.net/manual/en/function.iptcembed.php
2049:   #
2050:   {
2051:     $len = strlen($val);
2052:     if ($len < 0x8000)
2053:       return chr(0x1c).chr($rec).chr($dat).
2054:       chr($len >> 8).
2055:       chr($len & 0xff).
2056:       $val;
2057:     else
2058:       return chr(0x1c).chr($rec).chr($dat).
2059:       chr(0x80).chr(0x04).
2060:       chr(($len >> 24) & 0xff).
2061:       chr(($len >> 16) & 0xff).
2062:       chr(($len >> 8 ) & 0xff).
2063:       chr(($len ) & 0xff).
2064:       $val;
2065:   }
2066: 
2067: 
2068: 
2069: /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
2070:   Write XMP Data
2071: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
2072: 
2073:   //http://xmpphptoolkit.sourceforge.net/
2074: 
2075: 
2076: /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
2077:   Add Text
2078: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
2079: 
2080:   public function addText($text, $pos = '20x20', $padding = 0, $fontColor='#fff', $fontSize = 12, $angle = 0, $font = null)
2081:     # Author:     Jarrod Oberto
2082:   # Date:       18-11-09
2083:     # Purpose:    Add text to an image
2084:     # Param in:
2085:     # Param out:
2086:     # Reference:  http://php.net/manual/en/function.imagettftext.php
2087:     # Notes:      Make sure you supply the font.
2088:     #
2089:   {
2090: 
2091:     // *** Convert color
2092:     $rgbArray = $this->formatColor($fontColor);
2093:     $r = $rgbArray['r'];
2094:     $g = $rgbArray['g'];
2095:     $b = $rgbArray['b'];
2096: 
2097:     // *** Get text font
2098:     $font = $this->getTextFont($font);
2099: 
2100:     // *** Get text size
2101:     $textSizeArray = $this->getTextSize($fontSize, $angle, $font, $text);
2102:     $textWidth = $textSizeArray['width'];
2103:     $textHeight = $textSizeArray['height'];
2104: 
2105:     // *** Find co-ords to place text
2106:     $posArray = $this->calculatePosition($pos, $padding, $textWidth, $textHeight, false);
2107:     $x = $posArray['width'];
2108:     $y = $posArray['height'];
2109: 
2110:     $fontColor = imagecolorallocate($this->imageResized, $r, $g, $b);
2111: 
2112:     // *** Add text
2113:     imagettftext($this->imageResized, $fontSize, $angle, $x, $y, $fontColor, $font, $text);
2114:   }
2115: 
2116:   ## --------------------------------------------------------
2117: 
2118:   private function getTextFont($font)
2119:   {
2120:     // *** Font path (shou
2121:     $fontPath =  __DIR__ . '/' . $this->fontDir;
2122: 
2123: 
2124:     // *** The below is/may be needed depending on your version (see ref)
2125:     putenv('GDFONTPATH=' . realpath('.'));
2126: 
2127:     // *** Check if the passed in font exsits...
2128:     if ($font == null || !file_exists($font)) {
2129: 
2130:       // *** ...If not, default to this font.
2131:       $font = $fontPath . '/arimo.ttf';
2132: 
2133:       // *** Check our default font exists...
2134:       if (!file_exists($font)) {
2135: 
2136:         // *** If not, return false
2137:         if ($this->debug) { throw new Exception('Font not found'); }else{ return false; }
2138:       }
2139:     }
2140: 
2141:     return $font;
2142: 
2143:   }
2144: 
2145:   ## --------------------------------------------------------
2146: 
2147:   private function getTextSize($fontSize, $angle, $font, $text)
2148:   {
2149: 
2150:     // *** Define box (so we can get the width)
2151:     $box = @imagettfbbox($fontSize, $angle, $font, $text);
2152: 
2153:     // ***  Get width of text from dimensions
2154:     $textWidth = abs($box[4] - $box[0]);
2155: 
2156:     // ***  Get height of text from dimensions (should also be same as $fontSize)
2157:     $textHeight = abs($box[5] - $box[1]);
2158: 
2159:     return array('height' => $textHeight, 'width' => $textWidth);
2160:   }
2161: 
2162: 
2163: /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
2164:   Add Watermark
2165: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
2166: 
2167:   public function addWatermark($watermarkImage, $pos, $padding = 0, $opacity = 0)
2168:     # Author:     Jarrod Oberto
2169:     # Date:       18-11-09
2170:     # Purpose:    Add watermark image
2171:     # Param in:   (str) $watermark: The watermark image
2172:   #       (str) $pos: Could be a pre-determined position such as:
2173:   #           tl = top left,
2174:   #           t  = top (middle),
2175:   #           tr = top right,
2176:   #           l  = left,
2177:   #           m  = middle,
2178:   #           r  = right,
2179:   #           bl = bottom left,
2180:   #           b  = bottom (middle),
2181:   #           br = bottom right
2182:   #         Or, it could be a co-ordinate position such as: 50x100
2183:   #
2184:   #       (int) $padding: If using a pre-determined position you can
2185:   #         adjust the padding from the edges by passing an amount
2186:   #         in pixels. If using co-ordinates, this value is ignored.
2187:     # Param out:
2188:     # Reference:  http://www.php.net/manual/en/image.examples-watermark.php
2189:     # Notes:      Based on example in reference.
2190:   #
2191:     #
2192:   {
2193: 
2194:     // Load the stamp and the photo to apply the watermark to
2195:     $stamp = $this->openImage ($watermarkImage);    # stamp
2196:     $im = $this->imageResized;            # photo
2197: 
2198:     // *** Get stamps width and height
2199:     $sx = imagesx($stamp);
2200:     $sy = imagesy($stamp);
2201: 
2202:     // *** Find co-ords to place image
2203:     $posArray = $this->calculatePosition($pos, $padding, $sx, $sy);
2204:     $x = $posArray['width'];
2205:     $y = $posArray['height'];
2206: 
2207:     // *** Set watermark opacity
2208:     if (fix_strtolower(strrchr($watermarkImage, '.')) === '.png') {
2209: 
2210:       $opacity = $this->invertTransparency($opacity, 100);
2211:       $this->filterOpacity($stamp, $opacity);
2212:     }
2213: 
2214:     // Copy the watermark image onto our photo
2215:     imagecopy($im, $stamp, $x, $y, 0, 0, imagesx($stamp), imagesy($stamp));
2216: 
2217:   }
2218: 
2219:   ## --------------------------------------------------------
2220: 
2221:   private function calculatePosition($pos, $padding, $assetWidth, $assetHeight, $upperLeft = true)
2222:   #
2223:   # Author:   Jarrod Oberto
2224:   # Date:   08-05-11
2225:   # Purpose:  Calculate the x, y pixel cordinates of the asset to place
2226:   # Params in:  (str) $pos: Either something like: "tl", "l", "br" or an
2227:   #         exact position like: "100x50"
2228:   #       (int) $padding: The amount of padding from the edge. Only
2229:   #         used for the predefined $pos.
2230:   #       (int) $assetWidth: The width of the asset to add to the image
2231:   #       (int) $assetHeight: The height of the asset to add to the image
2232:   #       (bol) $upperLeft: if true, the asset will be positioned based
2233:   #         on the upper left x, y coords. If false, it means you're
2234:   #         using the lower left as the basepoint and this will
2235:   #         convert it to the upper left position
2236:   # Params out:
2237:   # NOTE: this is done from the UPPER left corner!! But will convert lower
2238:   #   left basepoints to upper left if $upperleft is set to false
2239:   #
2240:   #
2241:   {
2242:     $pos = fix_strtolower($pos);
2243: 
2244:     // *** If co-ords have been entered
2245:     if (strstr($pos, 'x')) {
2246:       $pos = str_replace(' ', '', $pos);
2247: 
2248:       $xyArray = explode('x', $pos);
2249:       list($width, $height) = $xyArray;
2250: 
2251:     } else {
2252: 
2253:       switch ($pos) {
2254:         case 'tl':
2255:           $width = 0 + $padding;
2256:           $height = 0 + $padding;
2257:           break;
2258: 
2259:         case 't':
2260:           $width = ($this->width / 2) - ($assetWidth / 2);
2261:           $height = 0 + $padding;
2262:           break;
2263: 
2264:         case 'tr':
2265:           $width = $this->width - $assetWidth - $padding;
2266:           $height = 0 + $padding;;
2267:           break;
2268: 
2269:         case 'l':
2270:           $width = 0 + $padding;
2271:           $height = ($this->height / 2) - ($assetHeight / 2);
2272:           break;
2273: 
2274:         case 'm':
2275:           $width = ($this->width / 2) - ($assetWidth / 2);
2276:           $height = ($this->height / 2) - ($assetHeight / 2);
2277:           break;
2278: 
2279:         case 'r':
2280:           $width = $this->width - $assetWidth - $padding;
2281:           $height = ($this->height / 2) - ($assetHeight / 2);
2282:           break;
2283: 
2284:         case 'bl':
2285:           $width = 0 + $padding;
2286:           $height = $this->height - $assetHeight - $padding;
2287:           break;
2288: 
2289:         case 'b':
2290:           $width = ($this->width / 2) - ($assetWidth / 2);
2291:           $height = $this->height - $assetHeight - $padding;
2292:           break;
2293: 
2294:         case 'br':
2295:           $width = $this->width - $assetWidth - $padding;
2296:           $height = $this->height - $assetHeight - $padding;
2297:           break;
2298: 
2299:         default:
2300:           $width = 0;
2301:           $height = 0;
2302:           break;
2303:       }
2304:     }
2305: 
2306:     if (!$upperLeft) {
2307:       $height = $height + $assetHeight;
2308:     }
2309: 
2310:     return array('width' => $width, 'height' => $height);
2311:   }
2312: 
2313: 
2314:   ## --------------------------------------------------------
2315: 
2316:   private function filterOpacity(&$img, $opacity = 75)
2317:   #
2318:   # Author:     aiden dot mail at freemail dot hu
2319:   # Author date:  29-03-08 08:16
2320:   # Date added:   08-05-11
2321:   # Purpose:    Change opacity of image
2322:   # Params in:    $img: Image resource id
2323:   #         (int) $opacity: the opacity amount: 0-100, 100 being not opaque.
2324:   # Params out:   (bool) true on success, else false
2325:   # Ref:      http://www.php.net/manual/en/function.imagefilter.php#82162
2326:   # Notes:      png only
2327:   #
2328:   {
2329: 
2330:     if (!isset($opacity)) {
2331:       return false;
2332:     }
2333: 
2334:     if ($opacity == 100) {
2335:       return true;
2336:     }
2337: 
2338:     $opacity /= 100;
2339: 
2340:     //get image width and height
2341:     $w = imagesx($img);
2342:     $h = imagesy($img);
2343: 
2344:     //turn alpha blending off
2345:     imagealphablending($img, false);
2346: 
2347:     //find the most opaque pixel in the image (the one with the smallest alpha value)
2348:     $minalpha = 127;
2349:     for ($x = 0; $x < $w; $x++)
2350:       for ($y = 0; $y < $h; $y++) {
2351:         $alpha = ( imagecolorat($img, $x, $y) >> 24 ) & 0xFF;
2352:         if ($alpha < $minalpha) {
2353:           $minalpha = $alpha;
2354:         }
2355:       }
2356: 
2357:     //loop through image pixels and modify alpha for each
2358:     for ($x = 0; $x < $w; $x++) {
2359:       for ($y = 0; $y < $h; $y++) {
2360:         //get current alpha value (represents the TANSPARENCY!)
2361:         $colorxy = imagecolorat($img, $x, $y);
2362:         $alpha = ( $colorxy >> 24 ) & 0xFF;
2363:         //calculate new alpha
2364:         if ($minalpha !== 127) {
2365:           $alpha = 127 + 127 * $opacity * ( $alpha - 127 ) / ( 127 - $minalpha );
2366:         } else {
2367:           $alpha += 127 * $opacity;
2368:         }
2369:         //get the color index with new alpha
2370:         $alphacolorxy = imagecolorallocatealpha($img, ( $colorxy >> 16 ) & 0xFF, ( $colorxy >> 8 ) & 0xFF, $colorxy & 0xFF, $alpha);
2371:         //set pixel with the new color + opacity
2372:         if (!imagesetpixel($img, $x, $y, $alphacolorxy)) {
2373: 
2374:           return false;
2375:         }
2376:       }
2377:     }
2378: 
2379:     return true;
2380:   }
2381: 
2382: ## --------------------------------------------------------
2383: 
2384:     private function openImage($file)
2385:     # Author:     Jarrod Oberto
2386:     # Date:       27-02-08
2387:     # Purpose:
2388:     # Param in:
2389:     # Param out:  n/a
2390:     # Reference:
2391:     # Notes:
2392:     #
2393:     {
2394: 
2395:     if (!file_exists($file) && !$this->checkStringStartsWith('http://', $file)) { if ($this->debug) { throw new Exception('Image not found.'); }else{ throw new Exception(); }};
2396: 
2397:         // *** Get extension
2398:         $extension = strrchr($file, '.');
2399:         $extension = fix_strtolower($extension);
2400:         switch($extension)
2401:         {
2402:             case '.jpg':
2403:             case '.jpeg':
2404:                 $img = @imagecreatefromjpeg($file);
2405:                 break;
2406:             case '.gif':
2407:                 $img = @imagecreatefromgif($file);
2408:                 break;
2409:             case '.png':
2410:                 $img = @imagecreatefrompng($file);
2411:                 break;
2412:             case '.bmp':
2413:                 $img = @$this->imagecreatefrombmp($file);
2414:                 break;
2415:             case '.psd':
2416:                 $img = @$this->imagecreatefrompsd($file);
2417:                 break;
2418: 
2419: 
2420:             // ... etc
2421: 
2422:             default:
2423:                 $img = false;
2424:                 break;
2425:         }
2426: 
2427:         return $img;
2428:     }
2429: 
2430: ## --------------------------------------------------------
2431: 
2432:   public function reset()
2433:   #
2434:   # Author:   Jarrod Oberto
2435:   # Date:   30-08-11
2436:   # Purpose:  Reset the resource (allow further editing)
2437:   # Params in:
2438:   # Params out:
2439:   # Notes:
2440:   #
2441:   {
2442:     $this->__construct($this->fileName);
2443:   }
2444: 
2445: ## --------------------------------------------------------
2446: 
2447:     public function saveImage($savePath, $imageQuality="100")
2448:     # Author:     Jarrod Oberto
2449:     # Date:       27-02-08
2450:     # Purpose:    Saves the image
2451:     # Param in:   $savePath: Where to save the image including filename:
2452:     #             $imageQuality: image quality you want the image saved at 0-100
2453:     # Param out:  n/a
2454:     # Reference:
2455:     # Notes:    * gif doesn't have a quality parameter
2456:   #       * jpg has a quality setting 0-100 (100 being the best)
2457:     #       * png has a quality setting 0-9 (0 being the best)
2458:   #
2459:   #             * bmp files have no native support for bmp files. We use a
2460:   #       third party class to save as bmp.
2461:     {
2462: 
2463:     // *** Perform a check or two.
2464:     if (!is_resource($this->imageResized)) { if ($this->debug) { throw new Exception('saveImage: This is not a resource.'); }else{ throw new Exception(); }}
2465:     $fileInfoArray = pathinfo($savePath);
2466:     clearstatcache();
2467:     if (!is_writable($fileInfoArray['dirname'])) {  if ($this->debug) { throw new Exception('The path is not writable. Please check your permissions.'); }else{ throw new Exception(); }}
2468: 
2469:     // *** Get extension
2470:         $extension = strrchr($savePath, '.');
2471:         $extension = fix_strtolower($extension);
2472: 
2473:     $error = '';
2474: 
2475:         switch($extension)
2476:         {
2477:             case '.jpg':
2478:             case '.jpeg':
2479:         $this->checkInterlaceImage($this->isInterlace);
2480:         if (imagetypes() & IMG_JPG) {
2481:           imagejpeg($this->imageResized, $savePath, $imageQuality);
2482:         } else { $error = 'jpg'; }
2483:                 break;
2484: 
2485:             case '.gif':
2486:         $this->checkInterlaceImage($this->isInterlace);
2487:         if (imagetypes() & IMG_GIF) {
2488:           imagegif($this->imageResized, $savePath);
2489:         } else { $error = 'gif'; }
2490:                 break;
2491: 
2492:             case '.png':
2493:         // *** Scale quality from 0-100 to 0-9
2494:         $scaleQuality = round(($imageQuality/100) * 9);
2495: 
2496:         // *** Invert qualit setting as 0 is best, not 9
2497:         $invertScaleQuality = 9 - $scaleQuality;
2498: 
2499:         $this->checkInterlaceImage($this->isInterlace);
2500:         if (imagetypes() & IMG_PNG) {
2501:            imagepng($this->imageResized, $savePath, $invertScaleQuality);
2502:         } else { $error = 'png'; }
2503:                 break;
2504: 
2505:             case '.bmp':
2506:         file_put_contents($savePath, $this->GD2BMPstring($this->imageResized));
2507:           break;
2508: 
2509: 
2510:             // ... etc
2511: 
2512:             default:
2513:         // *** No extension - No save.
2514:         $this->errorArray[] = 'This file type (' . $extension . ') is not supported. File not saved.';
2515:                 break;
2516:         }
2517: 
2518:     //imagedestroy($this->imageResized);
2519: 
2520:     // *** Display error if a file type is not supported.
2521:     if ($error != '') {
2522:       $this->errorArray[] = $error . ' support is NOT enabled. File not saved.';
2523:     }
2524:     }
2525: 
2526: ## --------------------------------------------------------
2527: 
2528:   public function displayImage($fileType = 'jpg', $imageQuality="100")
2529:     # Author:     Jarrod Oberto
2530:     # Date:       18-11-09
2531:     # Purpose:    Display images directly to the browser
2532:     # Param in:   The image type you want to display
2533:     # Param out:
2534:     # Reference:
2535:     # Notes:
2536:     #
2537:   {
2538: 
2539:     if (!is_resource($this->imageResized)) { if ($this->debug) { throw new Exception('saveImage: This is not a resource.'); }else{ throw new Exception(); }}
2540: 
2541:         switch($fileType)
2542:         {
2543:             case 'jpg':
2544:             case 'jpeg':
2545:         header('Content-type: image/jpeg');
2546:         imagejpeg($this->imageResized, '', $imageQuality);
2547:                 break;
2548:             case 'gif':
2549:         header('Content-type: image/gif');
2550:         imagegif($this->imageResized);
2551:                 break;
2552:             case 'png':
2553:         header('Content-type: image/png');
2554: 
2555:         // *** Scale quality from 0-100 to 0-9
2556:         $scaleQuality = round(($imageQuality/100) * 9);
2557: 
2558:         // *** Invert qualit setting as 0 is best, not 9
2559:         $invertScaleQuality = 9 - $scaleQuality;
2560: 
2561:         imagepng($this->imageResized, '', $invertScaleQuality);
2562:         break;
2563:       case 'bmp':
2564:         echo 'bmp file format is not supported.';
2565:         break;
2566: 
2567:             // ... etc
2568: 
2569:             default:
2570:         // *** No extension - No save.
2571:                 break;
2572:         }
2573: 
2574: 
2575:     //imagedestroy($this->imageResized);
2576:   }
2577: 
2578: ## --------------------------------------------------------
2579: 
2580:   public function setTransparency($bool)
2581:   # Sep 2011
2582:   {
2583:     $this->keepTransparency = $bool;
2584:   }
2585: 
2586: ## --------------------------------------------------------
2587: 
2588:   public function setFillColor($value)
2589:   # Sep 2011
2590:     # Param in:   (mixed) $value: (array) Could be an array of RGB
2591:   #               (str) Could be hex #ffffff or #fff, fff, ffffff
2592:   #
2593:   # If the keepTransparency is set to false, then no transparency is to be used.
2594:   # This is ideal when you want to save as jpg.
2595:   #
2596:   # this method allows you to set the background color to use instead of
2597:   # transparency.
2598:   #
2599:   {
2600:     $colorArray = $this->formatColor($value);
2601:     $this->fillColorArray = $colorArray;
2602:   }
2603: 
2604: ## --------------------------------------------------------
2605: 
2606:   public function setCropFromTop($value)
2607:   # Sep 2011
2608:   {
2609:     $this->cropFromTopPercent = $value;
2610:   }
2611: 
2612: ## --------------------------------------------------------
2613: 
2614:     public function testGDInstalled()
2615:     # Author:     Jarrod Oberto
2616:     # Date:       27-02-08
2617:     # Purpose:    Test to see if GD is installed
2618:     # Param in:   n/a
2619:     # Param out:  (bool) True is gd extension loaded otherwise false
2620:     # Reference:
2621:     # Notes:
2622:     #
2623:     {
2624:         if(extension_loaded('gd') && function_exists('gd_info'))
2625:         {
2626:             $gdInstalled = true;
2627:         }
2628:         else
2629:         {
2630:             $gdInstalled = false;
2631:         }
2632: 
2633:         return $gdInstalled;
2634:     }
2635: 
2636: ## --------------------------------------------------------
2637: 
2638:     public function testEXIFInstalled()
2639:     # Author:     Jarrod Oberto
2640:     # Date:       08-05-11
2641:     # Purpose:    Test to see if EXIF is installed
2642:     # Param in:   n/a
2643:     # Param out:  (bool) True is exif extension loaded otherwise false
2644:     # Reference:
2645:     # Notes:
2646:     #
2647:     {
2648:         if(extension_loaded('exif'))
2649:         {
2650:             $exifInstalled = true;
2651:         }
2652:         else
2653:         {
2654:             $exifInstalled = false;
2655:         }
2656: 
2657:         return $exifInstalled;
2658:     }
2659: 
2660: ## --------------------------------------------------------
2661: 
2662:     public function testIsImage($image)
2663:     # Author:     Jarrod Oberto
2664:     # Date:       27-02-08
2665:     # Purpose:    Test if file is an image
2666:     # Param in:   n/a
2667:     # Param out:  n/a
2668:     # Reference:
2669:     # Notes:
2670:     #
2671:     {
2672:         if ($image)
2673:         {
2674:             $fileIsImage = true;
2675:         }
2676:         else
2677:         {
2678:             $fileIsImage = false;
2679:         }
2680: 
2681:         return $fileIsImage;
2682:     }
2683: 
2684: ## --------------------------------------------------------
2685: 
2686:     public function testFunct()
2687:     # Author:     Jarrod Oberto
2688:     # Date:       27-02-08
2689:     # Purpose:    Test Function
2690:     # Param in:   n/a
2691:     # Param out:  n/a
2692:     # Reference:
2693:     # Notes:
2694:     #
2695:     {
2696:         echo $this->height;
2697:     }
2698: 
2699: ## --------------------------------------------------------
2700: 
2701:     public function setForceStretch($value)
2702:     # Author:     Jarrod Oberto
2703:     # Date:       23-12-10
2704:     # Purpose:
2705:     # Param in:   (bool) $value
2706:     # Param out:  n/a
2707:     # Reference:
2708:     # Notes:
2709:     #
2710:     {
2711:         $this->forceStretch = $value;
2712:     }
2713: 
2714: ## --------------------------------------------------------
2715: 
2716:     public function setFile($fileName)
2717:     # Author:     Jarrod Oberto
2718:     # Date:       28-02-08
2719:     # Purpose:
2720:     # Param in:   n/a
2721:     # Param out:  n/a
2722:     # Reference:
2723:     # Notes:
2724:     #
2725:     {
2726:         self::__construct($fileName);
2727:     }
2728: 
2729: ## --------------------------------------------------------
2730: 
2731:   public function getFileName()
2732:     # Author:     Jarrod Oberto
2733:     # Date:       10-09-08
2734:     # Purpose:
2735:     # Param in:   n/a
2736:     # Param out:  n/a
2737:     # Reference:
2738:     # Notes:
2739:     #
2740:     {
2741:       return $this->fileName;
2742:     }
2743: 
2744: ## --------------------------------------------------------
2745: 
2746:   public function getHeight()
2747:     {
2748:       return $this->height;
2749:     }
2750: 
2751: ## --------------------------------------------------------
2752: 
2753:   public function getWidth()
2754:     {
2755:       return $this->width;
2756:     }
2757: 
2758: ## --------------------------------------------------------
2759: 
2760:   public function getOriginalHeight()
2761:     {
2762:       return $this->heightOriginal;
2763:     }
2764: 
2765: ## --------------------------------------------------------
2766: 
2767:   public function getOriginalWidth()
2768:     {
2769:       return $this->widthOriginal;
2770:     }
2771: 
2772: ## --------------------------------------------------------
2773: 
2774:   public function getErrors()
2775:     # Author:     Jarrod Oberto
2776:     # Date:       19-11-09
2777:     # Purpose:    Returns the error array
2778:     # Param in:   n/a
2779:     # Param out:  Array of errors
2780:     # Reference:
2781:     # Notes:
2782:     #
2783:   {
2784:     return $this->errorArray;
2785:   }
2786: 
2787: ## --------------------------------------------------------
2788: 
2789:   private function checkInterlaceImage($isEnabled)
2790:   # jpg will use progressive (they don't use interace)
2791:   {
2792:     if ($isEnabled) {
2793:       imageinterlace($this->imageResized, $isEnabled);
2794:     }
2795:   }
2796: 
2797: ## --------------------------------------------------------
2798: 
2799:   protected function formatColor($value)
2800:     # Author:     Jarrod Oberto
2801:     # Date:       09-05-11
2802:     # Purpose:    Determine color method passed in and return color as RGB
2803:     # Param in:   (mixed) $value: (array) Could be an array of RGB
2804:   #               (str) Could be hex #ffffff or #fff, fff, ffffff
2805:     # Param out:
2806:     # Reference:
2807:     # Notes:
2808:     #
2809:   {
2810:     $rgbArray = array();
2811: 
2812:     // *** If it's an array it should be R, G, B
2813:     if (is_array($value)) {
2814: 
2815:       if (key($value) == 0 && count($value) == 3) {
2816: 
2817:         $rgbArray['r'] = $value[0];
2818:         $rgbArray['g'] = $value[1];
2819:         $rgbArray['b'] = $value[2];
2820: 
2821:       } else {
2822:         $rgbArray = $value;
2823:       }
2824:     } else if (fix_strtolower($value) === 'transparent') {
2825: 
2826:       $rgbArray = array(
2827:         'r' => 255,
2828:         'g' => 255,
2829:         'b' => 255,
2830:         'a' => 127
2831:       );
2832: 
2833:     } else {
2834: 
2835:       // *** ...Else it should be hex. Let's make it RGB
2836:       $rgbArray = $this -> hex2dec($value);
2837:     }
2838: 
2839:     return $rgbArray;
2840:   }
2841: 
2842:   ## --------------------------------------------------------
2843: 
2844:   function hex2dec($hex)
2845:   # Purpose:  Convert #hex color to RGB
2846:   {
2847:     $color = str_replace('#', '', $hex);
2848: 
2849:     if (strlen($color) == 3) {
2850:       $color = $color . $color;
2851:     }
2852: 
2853:     $rgb = array(
2854:       'r' => hexdec(substr($color, 0, 2)),
2855:       'g' => hexdec(substr($color, 2, 2)),
2856:       'b' => hexdec(substr($color, 4, 2)),
2857:       'a' => 0
2858:     );
2859:     return $rgb;
2860:   }
2861: 
2862:   ## --------------------------------------------------------
2863: 
2864:   private function createImageColor ($colorArray)
2865:   {
2866:     $r = $colorArray['r'];
2867:     $g = $colorArray['g'];
2868:     $b = $colorArray['b'];
2869: 
2870:     return imagecolorallocate($this->imageResized, $r, $g, $b);
2871:   }
2872: 
2873:   ## --------------------------------------------------------
2874: 
2875:   private function testColorExists($colorArray)
2876:   {
2877:     $r = $colorArray['r'];
2878:     $g = $colorArray['g'];
2879:     $b = $colorArray['b'];
2880: 
2881:     if (imagecolorexact($this->imageResized, $r, $g, $b) == -1) {
2882:       return false;
2883:     } else {
2884:       return true;
2885:     }
2886:   }
2887: 
2888:   ## --------------------------------------------------------
2889: 
2890:   private function findUnusedGreen()
2891:   # Purpose:  We find a green color suitable to use like green-screen effect.
2892:   #     Therefore, the color must not exist in the image.
2893:   {
2894:     $green = 255;
2895: 
2896:     do {
2897: 
2898:       $greenChroma = array(0, $green, 0);
2899:       $colorArray = $this->formatColor($greenChroma);
2900:       $match = $this->testColorExists($colorArray);
2901:       $green--;
2902: 
2903:     } while ($match == false && $green > 0);
2904: 
2905:     // *** If no match, just bite the bullet and use green value of 255
2906:     if (!$match) {
2907:       $greenChroma = array(0, $green, 0);
2908:     }
2909: 
2910:     return $greenChroma;
2911:   }
2912: 
2913:   ## --------------------------------------------------------
2914: 
2915:   private function findUnusedBlue()
2916:   # Purpose:  We find a green color suitable to use like green-screen effect.
2917:   #     Therefore, the color must not exist in the image.
2918:   {
2919:     $blue = 255;
2920: 
2921:     do {
2922: 
2923:       $blueChroma = array(0, 0, $blue);
2924:       $colorArray = $this->formatColor($blueChroma);
2925:       $match = $this->testColorExists($colorArray);
2926:       $blue--;
2927: 
2928:     } while ($match == false && $blue > 0);
2929: 
2930:     // *** If no match, just bite the bullet and use blue value of 255
2931:     if (!$match) {
2932:       $blueChroma = array(0, 0, $blue);
2933:     }
2934: 
2935:     return $blueChroma;
2936:   }
2937: 
2938:   ## --------------------------------------------------------
2939: 
2940:   private function invertTransparency($value, $originalMax, $invert=true)
2941:   # Purpose:  This does two things:
2942:   #       1) Convert the range from 0-127 to 0-100
2943:   #       2) Inverts value to 100 is not transparent while 0 is fully
2944:   #          transparent (like Photoshop)
2945:   {
2946:     // *** Test max range
2947:     if ($value > $originalMax) {
2948:       $value = $originalMax;
2949:     }
2950: 
2951:     // *** Test min range
2952:     if ($value < 0) {
2953:       $value = 0;
2954:     }
2955: 
2956:     if ($invert) {
2957:       return $originalMax - (($value/100) * $originalMax);
2958:     } else {
2959:       return ($value/100) * $originalMax;
2960:     }
2961:   }
2962: 
2963:   ## --------------------------------------------------------
2964: 
2965:   private function transparentImage($src)
2966:   {
2967:     // *** making images with white bg transparent
2968:     $r1 = 0;
2969:     $g1 = 255;
2970:     $b1 = 0;
2971:     for ($x = 0; $x < imagesx($src); ++$x) {
2972:       for ($y = 0; $y < imagesy($src); ++$y) {
2973:         $color = imagecolorat($src, $x, $y);
2974:         $r = ($color >> 16) & 0xFF;
2975:         $g = ($color >> 8) & 0xFF;
2976:         $b = $color & 0xFF;
2977:         for ($i = 0; $i < 270; $i++) {
2978:           //if ($r . $g . $b == ($r1 + $i) . ($g1 + $i) . ($b1 + $i)) {
2979:           if ($r == 0 && $g == 255 && $b == 0) {
2980:           //if ($g == 255) {
2981:             $trans_colour = imagecolorallocatealpha($src, 0, 0, 0, 127);
2982:             imagefill($src, $x, $y, $trans_colour);
2983:           }
2984:         }
2985:       }
2986:     }
2987: 
2988:     return $src;
2989:   }
2990: 
2991:   ## --------------------------------------------------------
2992: 
2993:   function checkStringStartsWith($needle, $haystack)
2994:   # Check if a string starts with a specific pattern
2995:   {
2996:     return (substr($haystack, 0, strlen($needle))==$needle);
2997:   }
2998: 
2999: 
3000: /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
3001:   BMP SUPPORT (SAVING) - James Heinrich
3002: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
3003: 
3004:   private function GD2BMPstring(&$gd_image)
3005:     # Author:     James Heinrich
3006:     # Purpose:    Save file as type bmp
3007:     # Param in:   The image canvas (passed as ref)
3008:     # Param out:
3009:     # Reference:
3010:     # Notes:    This code was stripped out of two external files
3011:   #       (phpthumb.bmp.php,phpthumb.functions.php) and added below to
3012:   #       avoid dependancies.
3013:     #
3014:   {
3015:     $imageX = imagesx($gd_image);
3016:     $imageY = imagesy($gd_image);
3017: 
3018:     $BMP = '';
3019:     for ($y = ($imageY - 1); $y >= 0; $y--) {
3020:       $thisline = '';
3021:       for ($x = 0; $x < $imageX; $x++) {
3022:         $argb = $this->GetPixelColor($gd_image, $x, $y);
3023:         $thisline .= chr($argb['blue']).chr($argb['green']).chr($argb['red']);
3024:       }
3025:       while (strlen($thisline) % 4) {
3026:         $thisline .= "\x00";
3027:       }
3028:       $BMP .= $thisline;
3029:     }
3030: 
3031:     $bmpSize = strlen($BMP) + 14 + 40;
3032:     // BITMAPFILEHEADER [14 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_62uq.asp
3033:     $BITMAPFILEHEADER  = 'BM';                                    // WORD    bfType;
3034:     $BITMAPFILEHEADER .= $this->LittleEndian2String($bmpSize, 4); // DWORD   bfSize;
3035:     $BITMAPFILEHEADER .= $this->LittleEndian2String(       0, 2); // WORD    bfReserved1;
3036:     $BITMAPFILEHEADER .= $this->LittleEndian2String(       0, 2); // WORD    bfReserved2;
3037:     $BITMAPFILEHEADER .= $this->LittleEndian2String(      54, 4); // DWORD   bfOffBits;
3038: 
3039:     // BITMAPINFOHEADER - [40 bytes] http://msdn.microsoft.com/library/en-us/gdi/bitmaps_1rw2.asp
3040:     $BITMAPINFOHEADER  = $this->LittleEndian2String(      40, 4); // DWORD  biSize;
3041:     $BITMAPINFOHEADER .= $this->LittleEndian2String( $imageX, 4); // LONG   biWidth;
3042:     $BITMAPINFOHEADER .= $this->LittleEndian2String( $imageY, 4); // LONG   biHeight;
3043:     $BITMAPINFOHEADER .= $this->LittleEndian2String(       1, 2); // WORD   biPlanes;
3044:     $BITMAPINFOHEADER .= $this->LittleEndian2String(      24, 2); // WORD   biBitCount;
3045:     $BITMAPINFOHEADER .= $this->LittleEndian2String(       0, 4); // DWORD  biCompression;
3046:     $BITMAPINFOHEADER .= $this->LittleEndian2String(       0, 4); // DWORD  biSizeImage;
3047:     $BITMAPINFOHEADER .= $this->LittleEndian2String(    2835, 4); // LONG   biXPelsPerMeter;
3048:     $BITMAPINFOHEADER .= $this->LittleEndian2String(    2835, 4); // LONG   biYPelsPerMeter;
3049:     $BITMAPINFOHEADER .= $this->LittleEndian2String(       0, 4); // DWORD  biClrUsed;
3050:     $BITMAPINFOHEADER .= $this->LittleEndian2String(       0, 4); // DWORD  biClrImportant;
3051: 
3052:     return $BITMAPFILEHEADER.$BITMAPINFOHEADER.$BMP;
3053:   }
3054: 
3055: ## --------------------------------------------------------
3056: 
3057:   private function GetPixelColor(&$img, $x, $y)
3058:     # Author:     James Heinrich
3059:     # Purpose:
3060:     # Param in:
3061:     # Param out:
3062:     # Reference:
3063:     # Notes:
3064:     #
3065:   {
3066:     if (!is_resource($img)) {
3067:       return false;
3068:     }
3069:     return @imagecolorsforindex($img, @imagecolorat($img, $x, $y));
3070:   }
3071: 
3072: ## --------------------------------------------------------
3073: 
3074:   private function LittleEndian2String($number, $minbytes=1)
3075:     # Author:     James Heinrich
3076:     # Purpose:    BMP SUPPORT (SAVING)
3077:     # Param in:
3078:     # Param out:
3079:     # Reference:
3080:     # Notes:
3081:     #
3082:   {
3083:     $intstring = '';
3084:     while ($number > 0) {
3085:       $intstring = $intstring.chr($number & 255);
3086:       $number >>= 8;
3087:     }
3088:     return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT);
3089:   }
3090: 
3091: 
3092: /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
3093:   BMP SUPPORT (READING)
3094: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
3095: 
3096:   private function ImageCreateFromBMP($filename)
3097:     # Author:     DHKold
3098:     # Date:     The 15th of June 2005
3099:   # Version:    2.0B
3100:     # Purpose:    To create an image from a BMP file.
3101:     # Param in:   BMP file to open.
3102:     # Param out:  Return a resource like the other ImageCreateFrom functions
3103:     # Reference:  http://us3.php.net/manual/en/function.imagecreate.php#53879
3104:   # Bug fix:    Author:   domelca at terra dot es
3105:   #       Date:   06 March 2008
3106:   #       Fix:    Correct 16bit BMP support
3107:     # Notes:
3108:   #
3109:   {
3110: 
3111:     //Ouverture du fichier en mode binaire
3112:     if (! $f1 = fopen($filename,"rb")) return FALSE;
3113: 
3114:     //1 : Chargement des ent�tes FICHIER
3115:     $FILE = unpack("vfile_type/Vfile_size/Vreserved/Vbitmap_offset", fread($f1,14));
3116:     if ($FILE['file_type'] != 19778) return FALSE;
3117: 
3118:     //2 : Chargement des ent�tes BMP
3119:     $BMP = unpack('Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel'.
3120:            '/Vcompression/Vsize_bitmap/Vhoriz_resolution'.
3121:            '/Vvert_resolution/Vcolors_used/Vcolors_important', fread($f1,40));
3122:     $BMP['colors'] = pow(2,$BMP['bits_per_pixel']);
3123: 
3124:     if ($BMP['size_bitmap'] == 0) $BMP['size_bitmap'] = $FILE['file_size'] - $FILE['bitmap_offset'];
3125: 
3126:     $BMP['bytes_per_pixel'] = $BMP['bits_per_pixel']/8;
3127:     $BMP['bytes_per_pixel2'] = ceil($BMP['bytes_per_pixel']);
3128:     $BMP['decal'] = ($BMP['width']*$BMP['bytes_per_pixel']/4);
3129:        $BMP['decal'] -= floor($BMP['width']*$BMP['bytes_per_pixel']/4);
3130:     $BMP['decal'] = 4-(4*$BMP['decal']);
3131: 
3132:     if ($BMP['decal'] == 4) $BMP['decal'] = 0;
3133: 
3134:     //3 : Chargement des couleurs de la palette
3135:     $PALETTE = array();
3136:     if ($BMP['colors'] < 16777216)
3137:     {
3138:       $PALETTE = unpack('V'.$BMP['colors'], fread($f1,$BMP['colors']*4));
3139:     }
3140: 
3141:     //4 : Cr�ation de l'image
3142:     $IMG = fread($f1,$BMP['size_bitmap']);
3143:     $VIDE = chr(0);
3144: 
3145:     $res = imagecreatetruecolor($BMP['width'],$BMP['height']);
3146:     $P = 0;
3147:     $Y = $BMP['height']-1;
3148:     while ($Y >= 0)
3149:     {
3150:       $X=0;
3151:       while ($X < $BMP['width'])
3152:       {
3153:         if ($BMP['bits_per_pixel'] == 24)
3154:           $COLOR = unpack("V",substr($IMG,$P,3).$VIDE);
3155:         elseif ($BMP['bits_per_pixel'] == 16)
3156:         {
3157: 
3158:           /*
3159:            * BMP 16bit fix
3160:            * =================
3161:            *
3162:            * Ref: http://us3.php.net/manual/en/function.imagecreate.php#81604
3163:            *
3164:            * Notes:
3165:            * "don't work with bmp 16 bits_per_pixel. change pixel
3166:            * generator for this."
3167:            *
3168:            */
3169: 
3170:           // *** Original code (don't work)
3171:           //$COLOR = unpack("n",substr($IMG,$P,2));
3172:           //$COLOR[1] = $PALETTE[$COLOR[1]+1];
3173: 
3174:           $COLOR = unpack("v",substr($IMG,$P,2));
3175:           $blue = ($COLOR[1] & 0x001f) << 3;
3176:           $green = ($COLOR[1] & 0x07e0) >> 3;
3177:           $red = ($COLOR[1] & 0xf800) >> 8;
3178:           $COLOR[1] = $red * 65536 + $green * 256 + $blue;
3179: 
3180:         }
3181:         elseif ($BMP['bits_per_pixel'] == 8)
3182:         {
3183:           $COLOR = unpack("n",$VIDE.substr($IMG,$P,1));
3184:           $COLOR[1] = $PALETTE[$COLOR[1]+1];
3185:         }
3186:         elseif ($BMP['bits_per_pixel'] == 4)
3187:         {
3188:           $COLOR = unpack("n",$VIDE.substr($IMG,floor($P),1));
3189:           if (($P*2)%2 == 0) $COLOR[1] = ($COLOR[1] >> 4) ; else $COLOR[1] = ($COLOR[1] & 0x0F);
3190:           $COLOR[1] = $PALETTE[$COLOR[1]+1];
3191:         }
3192:         elseif ($BMP['bits_per_pixel'] == 1)
3193:         {
3194:           $COLOR = unpack("n",$VIDE.substr($IMG,floor($P),1));
3195:           if     (($P*8)%8 == 0) $COLOR[1] =  $COLOR[1]        >>7;
3196:           elseif (($P*8)%8 == 1) $COLOR[1] = ($COLOR[1] & 0x40)>>6;
3197:           elseif (($P*8)%8 == 2) $COLOR[1] = ($COLOR[1] & 0x20)>>5;
3198:           elseif (($P*8)%8 == 3) $COLOR[1] = ($COLOR[1] & 0x10)>>4;
3199:           elseif (($P*8)%8 == 4) $COLOR[1] = ($COLOR[1] & 0x8)>>3;
3200:           elseif (($P*8)%8 == 5) $COLOR[1] = ($COLOR[1] & 0x4)>>2;
3201:           elseif (($P*8)%8 == 6) $COLOR[1] = ($COLOR[1] & 0x2)>>1;
3202:           elseif (($P*8)%8 == 7) $COLOR[1] = ($COLOR[1] & 0x1);
3203:           $COLOR[1] = $PALETTE[$COLOR[1]+1];
3204:         }
3205:         else
3206:           return FALSE;
3207: 
3208:         imagesetpixel($res,$X,$Y,$COLOR[1]);
3209:         $X++;
3210:         $P += $BMP['bytes_per_pixel'];
3211:       }
3212: 
3213:       $Y--;
3214:       $P+=$BMP['decal'];
3215:     }
3216:     //Fermeture du fichier
3217:     fclose($f1);
3218: 
3219:     return $res;
3220:   }
3221: 
3222: 
3223: /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*-
3224:   PSD SUPPORT (READING)
3225: *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**-*-*-*-*-*-*-*-*-*-*-*-*-*/
3226: 
3227:   private function imagecreatefrompsd($fileName)
3228:   # Author:     Tim de Koning
3229:   # Version:    1.3
3230:   # Purpose:    To create an image from a PSD file.
3231:   # Param in:   PSD file to open.
3232:   # Param out:  Return a resource like the other ImageCreateFrom functions
3233:   # Reference:  http://www.kingsquare.nl/phppsdreader
3234:   # Notes:
3235:   #
3236:   {
3237:     if (file_exists($this->psdReaderPath)) {
3238: 
3239: 
3240:       include_once($this->psdReaderPath);
3241: 
3242:       $psdReader = new PhpPsdReader($fileName);
3243: 
3244:       if (isset($psdReader->infoArray['error'])) return '';
3245:       else return $psdReader->getImage();
3246:     } else {
3247:       return false;
3248:     }
3249:   }
3250: 
3251: ## --------------------------------------------------------
3252: 
3253:     public function __destruct() {
3254:     if (is_resource($this->imageResized)) {
3255:       imagedestroy($this->imageResized);
3256:     }
3257:   }
3258: 
3259: ## --------------------------------------------------------
3260: 
3261: }
3262: 
3263: 
3264: 
3265: 
3266: /*
3267:  *    Example with some API calls (outdated):
3268:  *
3269:  *
3270:  *      ===============================
3271:  *      Compulsary
3272:  *      ===============================
3273:  *
3274:  *      include("classes/resize_class.php");
3275:  *
3276:  *      // *** Initialise object
3277:  *      $magicianObj = new resize('images/cars/large/a.jpg');
3278:  *
3279:  *      // *** Turn off stretching (optional)
3280:  *      $magicianObj -> setForceStretch(false);
3281:  *
3282:  *      // *** Resize object
3283:  *      $magicianObj -> resizeImage(150, 100, 0);
3284:  *
3285:  *      ===============================
3286:  *      Image options - can run none, one, or all.
3287:  *      ===============================
3288:  *
3289:  *      //  *** Add watermark
3290:  *        $magicianObj -> addWatermark('stamp.png');
3291:  *
3292:  *          // *** Add text
3293:  *      $magicianObj -> addText('testing...');
3294:  *
3295:  *      ===============================
3296:  *      Output options - can run one, or the other, or both.
3297:  *      ===============================
3298:  *
3299:  *      // *** Save image to disk
3300:  *      $magicianObj -> saveImage('images/cars/large/b.jpg', 100);
3301:  *
3302:  *          // *** Or output to screen (params in can be jpg, gif, png)
3303:  *      $magicianObj -> displayImage('png');
3304:  *
3305:  *      ===============================
3306:  *      Return options - return errors. nice for debuggin.
3307:  *      ===============================
3308:  *
3309:  *      // *** Return error array
3310:  *      $errorArray = $magicianObj -> getErrors();
3311:  *
3312:  *
3313:  *      ===============================
3314:  *      Cleanup options - not really neccessary, but good practice
3315:  *      ===============================
3316:  *
3317:  *      // *** Free used memory
3318:  *      $magicianObj -> __destruct();
3319:  */
3320: 
API documentation generated by ApiGen