├── .gitignore ├── LICENSE ├── README.md ├── demo ├── app │ ├── App_Resources │ │ ├── Android │ │ │ ├── AndroidManifest.xml │ │ │ ├── app.gradle │ │ │ ├── drawable-hdpi │ │ │ │ └── icon.png │ │ │ ├── drawable-ldpi │ │ │ │ └── icon.png │ │ │ ├── drawable-mdpi │ │ │ │ └── icon.png │ │ │ └── drawable-nodpi │ │ │ │ └── splashscreen.9.png │ │ └── iOS │ │ │ ├── Default-568h@2x.png │ │ │ ├── Default-667h@2x.png │ │ │ ├── Default-736h@3x.png │ │ │ ├── Default-Landscape-568h@2x.png │ │ │ ├── Default-Landscape-667h@2x.png │ │ │ ├── Default-Landscape.png │ │ │ ├── Default-Landscape@2x.png │ │ │ ├── Default-Landscape@3x.png │ │ │ ├── Default-Portrait.png │ │ │ ├── Default-Portrait@2x.png │ │ │ ├── Default.png │ │ │ ├── Default@2x.png │ │ │ ├── Icon-Small-50.png │ │ │ ├── Icon-Small-50@2x.png │ │ │ ├── Icon-Small.png │ │ │ ├── Icon-Small@2x.png │ │ │ ├── Info.plist │ │ │ ├── build.xcconfig │ │ │ ├── icon-40.png │ │ │ ├── icon-40@2x.png │ │ │ ├── icon-60.png │ │ │ ├── icon-60@2x.png │ │ │ ├── icon-72.png │ │ │ ├── icon-72@2x.png │ │ │ ├── icon-76.png │ │ │ ├── icon-76@2x.png │ │ │ ├── icon.png │ │ │ └── icon@2x.png │ ├── app.css │ ├── app.js │ ├── fonts │ │ ├── FontAwesome.otf │ │ ├── LICENSE.txt │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 │ ├── main-page.js │ ├── main-page.xml │ ├── main-view-model.js │ ├── main-view-model.ts │ ├── package.json │ └── references.d.ts ├── hooks │ ├── before-prepare │ │ └── nativescript-dev-typescript.js │ └── before-watch │ │ └── nativescript-dev-typescript.js ├── livesync.cmd ├── package.json ├── references.d.ts └── tsconfig.json └── plugin ├── .npmignore ├── BitmapFactory.android.js ├── BitmapFactory.commons.js ├── BitmapFactory.ios.js ├── README.md ├── index.d.ts ├── index.js ├── index.ts ├── package-lock.json ├── package.json ├── references.d.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | /pushall.sh 2 | /demo/platforms 3 | /demo/node_modules 4 | /plugin/index.js.map 5 | /demo/app/*.map 6 | /demo/.vscode 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Marcel Kloubert 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![npm](https://img.shields.io/npm/v/nativescript-bitmap-factory.svg)](https://www.npmjs.com/package/nativescript-bitmap-factory) 2 | [![npm](https://img.shields.io/npm/dt/nativescript-bitmap-factory.svg?label=npm%20downloads)](https://www.npmjs.com/package/nativescript-bitmap-factory) 3 | 4 | # NativeScript Bitmap Factory 5 | 6 | A [NativeScript](https://nativescript.org/) module for creating and manipulating bitmap images. 7 | 8 | [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=U3FY9F6QMDQ4L&lc=DE&item_name=Marcel%20Kloubert&item_number=nativescript%2dbitmap%2dfactory&no_note=1&no_shipping=2¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted) 9 | 10 | ## NativeScript Toolbox 11 | 12 | This module is part of [nativescript-toolbox](https://github.com/mkloubert/nativescript-toolbox). 13 | 14 | ## License 15 | 16 | [MIT license](https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/master/LICENSE) 17 | 18 | ## Platforms 19 | 20 | * Android 21 | * iOS 22 | 23 | ## Installation 24 | 25 | Run 26 | 27 | ```bash 28 | tns plugin add nativescript-bitmap-factory 29 | ``` 30 | 31 | inside your app project to install the module. 32 | 33 | ## Usage 34 | 35 | ```typescript 36 | import BitmapFactory = require("nativescript-bitmap-factory"); 37 | import KnownColors = require("color/known-colors"); 38 | 39 | // create a bitmap with 640x480 40 | var bmp = BitmapFactory.create(640, 480); 41 | 42 | // work with bitmap and 43 | // keep sure to free memory 44 | // after we do not need it anymore 45 | bmp.dispose(() => { 46 | // draw an oval with a size of 300x150 47 | // and start at position x=0, y=75 48 | // and use 49 | // "red" as border color and "black" as background color. 50 | bmp.drawOval("300x150", "0,75", 51 | KnownColors.Red, KnownColors.Black); 52 | 53 | // draw a circle with a radius of 80 54 | // at the center of the bitmap (null => default) 55 | // and use 56 | // "dark green" as border color 57 | bmp.drawCircle(80, null, 58 | KnownColors.DarkGreen); 59 | 60 | // draws an arc with a size of 100x200 61 | // at x=10 and y=20 62 | // beginning at angle 0 with a sweep angle of 90 degrees 63 | // and a black border and a yellow fill color 64 | bmp.drawArc("100x200", "10,20", 65 | 0, 90, 66 | KnownColors.Black, KnownColors.Yellow); 67 | 68 | // set a yellow point at x=160, y=150 69 | bmp.setPoint("160,150", "ff0"); 70 | 71 | // draws a line from (0|150) to (300|75) 72 | // with blue color 73 | bmp.drawLine("0,150", "300,75", '#0000ff'); 74 | 75 | // writes a text in yellow color 76 | // at x=100, y=100 77 | // by using "Roboto" as font 78 | // with a size of 10 79 | bmp.writeText("This is a test!", "100,100", { 80 | color: KnownColors.Yellow, 81 | size: 10, 82 | name: "Roboto" 83 | }); 84 | 85 | // returns the current bitmap as data URL 86 | // which can be used as ImageSource 87 | // in JPEG format with a quality of 75% 88 | var data = bmp.toDataUrl(BitmapFactory.OutputFormat.JPEG, 75); 89 | 90 | // ... and in Base64 format 91 | var base64JPEG = bmp.toBase64(BitmapFactory.OutputFormat.JPEG, 75); 92 | 93 | // ... and as ImageSource 94 | var imgSrc = bmp.toImageSource(); 95 | }); 96 | ``` 97 | 98 | ## Functions 99 | 100 | | Name | Description | 101 | | ---- | --------- | 102 | | asBitmap | Returns a value as wrapped bitmap. | 103 | | create | Creates a new bitmap instance. | 104 | | getDefaultOptions | Returns the default options for creating a new bitmap. | 105 | | makeMutable | A helper function that keeps sure to return a native image object that is able to be used as wrapped bitmap object. | 106 | | setDefaultOptions | Sets the default options for creating a new bitmap. | 107 | 108 | ## Platform specific stuff 109 | 110 | You can access the `nativeObject` property to access the platform specific object. 111 | 112 | For Android this is a [Bitmap](https://developer.android.com/reference/android/graphics/Bitmap.html) object and for iOS this is an [UIImage](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIImage_Class/) object. 113 | 114 | To check the platform you can use the `android` and `ios` properties which have the same values as the corresponding properties from `application` core module. 115 | 116 | ### Android 117 | 118 | You also can access the underlying [Canvas](https://developer.android.com/reference/android/graphics/Canvas.html) object by `__canvas` property. 119 | 120 | ### iOS 121 | 122 | You also can access the underlying [CGImage](https://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CGImage/) object by`__CGImage` property. 123 | 124 | ## Data types 125 | 126 | ### IArgb 127 | 128 | Stores data of an RGB value with alpha value. 129 | 130 | These values can also be submitted as strings (like `#ff0` or `ffffff`) or numbers. 131 | 132 | ```typescript 133 | interface IArgb { 134 | /** 135 | * Gets the alpha value. 136 | */ 137 | a: number; 138 | 139 | /** 140 | * Gets the red value. 141 | */ 142 | r: number; 143 | 144 | /** 145 | * Gets the green value. 146 | */ 147 | g: number; 148 | 149 | /** 150 | * Gets the blue value. 151 | */ 152 | b: number; 153 | } 154 | ``` 155 | 156 | ### IBitmapData 157 | 158 | Used by `toObject()` method. 159 | 160 | ```typescript 161 | interface IBitmapData { 162 | /** 163 | * Gets the data as Base64 string. 164 | */ 165 | base64: string; 166 | 167 | /** 168 | * Gets the mime type. 169 | */ 170 | mime: string; 171 | } 172 | ``` 173 | 174 | ### IFont 175 | 176 | Font settings. 177 | 178 | ```typescript 179 | interface IFont { 180 | /** 181 | * Anti alias or not. 182 | */ 183 | antiAlias?: boolean; 184 | 185 | /** 186 | * Gets the custom forground color. 187 | */ 188 | color?: string | number | IArgb; 189 | 190 | /** 191 | * Gets the name. 192 | */ 193 | name?: string; 194 | 195 | /** 196 | * Gets the size. 197 | */ 198 | size?: number; 199 | } 200 | ``` 201 | 202 | ### IPoint2D 203 | 204 | Coordinates, can also be a string like `0,0` or `150|300`. 205 | 206 | ```typescript 207 | interface IPoint2D { 208 | /** 209 | * Gets the X coordinate. 210 | */ 211 | x: number; 212 | 213 | /** 214 | * Gets the Y coordinate. 215 | */ 216 | y: number; 217 | } 218 | ``` 219 | 220 | ### IPoint2D 221 | 222 | Size, can also be a string like `0,0` or `150x300`. 223 | 224 | ```typescript 225 | interface ISize { 226 | /** 227 | * Gets the height. 228 | */ 229 | height: number; 230 | 231 | /** 232 | * Gets the width. 233 | */ 234 | width: number; 235 | } 236 | ``` 237 | 238 | ### OutputFormat 239 | 240 | Supported output formats. 241 | 242 | ```typescript 243 | enum OutputFormat { 244 | /** 245 | * PNG 246 | */ 247 | PNG = 1, 248 | 249 | /** 250 | * JPEG 251 | */ 252 | JPEG = 2, 253 | } 254 | ``` 255 | 256 | ### Bitmap 257 | 258 | ```typescript 259 | interface IBitmap { 260 | /** 261 | * Get the android specific object provided by 'application' module. 262 | */ 263 | android: AndroidApplication; 264 | 265 | /** 266 | * Clones that bitmap. 267 | */ 268 | clone(): IBitmap; 269 | 270 | /** 271 | * Crops that bitmap and returns its copy. 272 | */ 273 | crop(leftTop?: IPoint2D | string, 274 | size?: ISize | string): IBitmap; 275 | 276 | /** 277 | * Gets or sets the default color. 278 | */ 279 | defaultColor: IPoint2D | string | number; 280 | 281 | /** 282 | * Disposes the bitmap. Similar to the IDisposable pattern of .NET Framework. 283 | */ 284 | dispose(action?: (bmp: IBitmap, tag?: T) => TResult, 285 | tag?: T): TResult; 286 | 287 | /** 288 | * Draws a circle. 289 | */ 290 | drawCircle(radius?: number, 291 | center?: IPoint2D | string, 292 | color?: string | number | IArgb, fillColor?: string | number | IArgb): IBitmap; 293 | 294 | /** 295 | * Draws an arc. 296 | */ 297 | drawArc(size?: ISize | string, 298 | leftTop?: IPoint2D | string, 299 | startAngle?: number, 300 | sweepAngle?: number, 301 | color?: string | number | IArgb, fillColor?: string | number | IArgb): IBitmap; 302 | 303 | /** 304 | * Draws a line. 305 | */ 306 | drawLine(start: IPoint2D | string, end: IPoint2D | string, 307 | color?: string | number | IArgb): IBitmap; 308 | 309 | /** 310 | * Draws an oval circle. 311 | */ 312 | drawOval(size?: ISize | string, 313 | leftTop?: IPoint2D | string, 314 | color?: string | number | IArgb, fillColor?: string | number | IArgb): IBitmap; 315 | 316 | /** 317 | * Draws a rectangle. 318 | */ 319 | drawRect(size?: ISize | string, 320 | leftTop?: IPoint2D | string, 321 | color?: string | number | IArgb, fillColor?: string | number | IArgb): IBitmap; 322 | 323 | /** 324 | * Gets the color of a point. 325 | */ 326 | getPoint(coordinates?: IPoint2D | string): IArgb; 327 | 328 | /** 329 | * Gets the height of the bitmap. 330 | */ 331 | height: number; 332 | 333 | /** 334 | * Get the iOS specific object provided by 'application' module. 335 | */ 336 | ios: iOSApplication; 337 | 338 | /** 339 | * Inserts another image into that bitmap. 340 | */ 341 | insert(other: any, 342 | leftTop?: IPoint2D | string): IBitmap; 343 | 344 | /** 345 | * Gets if the object has been disposed or not. 346 | */ 347 | isDisposed: boolean; 348 | 349 | /** 350 | * Gets the native platform specific object that represents that bitmap. 351 | */ 352 | nativeObject: any; 353 | 354 | /** 355 | * Normalizes a color value. 356 | */ 357 | normalizeColor(value: string | number | IArgb): IArgb; 358 | 359 | /** 360 | * Creates a copy of that bitmap with a new size. 361 | */ 362 | resize(newSize: ISize | string): IBitmap; 363 | 364 | /** 365 | * Resizes that image by defining a new height by keeping ratio. 366 | */ 367 | resizeHeight(newHeight: number): IBitmap; 368 | 369 | /** 370 | * Resizes that image by defining a new (maximum) size by keeping ratio. 371 | */ 372 | resizeMax(maxSize: number): IBitmap; 373 | 374 | /** 375 | * Resizes that image by defining a new width by keeping ratio. 376 | */ 377 | resizeWidth(newWidth: number): IBitmap; 378 | 379 | /** 380 | * Rotates the image. 381 | */ 382 | rotate(degrees?: number): IBitmap; 383 | 384 | /** 385 | * Sets a pixel / point. 386 | */ 387 | setPoint(coordinates?: IPoint2D | string, 388 | color?: string | number | IArgb): IBitmap; 389 | 390 | /** 391 | * Gets the size. 392 | */ 393 | size: ISize; 394 | 395 | /** 396 | * Converts that image to a Base64 string. 397 | */ 398 | toBase64(format?: OutputFormat, quality?: number): string; 399 | 400 | /** 401 | * Converts that image to a data URL. 402 | */ 403 | toDataUrl(format?: OutputFormat, quality?: number): string; 404 | 405 | /** 406 | * Returns that image as ImageSource. 407 | */ 408 | toImageSource(): ImageSource; 409 | 410 | /** 411 | * Converts that image to an object. 412 | */ 413 | toObject(format?: OutputFormat, quality?: number): IBitmapData; 414 | 415 | /** 416 | * Writes a text. 417 | */ 418 | writeText(txt: any, 419 | leftTop?: IPoint2D | string, font?: IFont | string): IBitmap; 420 | 421 | /** 422 | * Gets the width of the bitmap. 423 | */ 424 | width: number; 425 | } 426 | ``` 427 | 428 | ## Contributors 429 | 430 | * [Dimitar Topuzov](https://github.com/dtopuzov) 431 | * [Geoff Bullen](https://github.com/geoffbullen) 432 | * [Jonathan Salomon](https://github.com/abhayastudios) 433 | * [Josh Huckabee](https://github.com/jhuckabee) 434 | -------------------------------------------------------------------------------- /demo/app/App_Resources/Android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 27 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /demo/app/App_Resources/Android/app.gradle: -------------------------------------------------------------------------------- 1 | // Add your native dependencies here: 2 | 3 | // Uncomment to add recyclerview-v7 dependency 4 | //dependencies { 5 | // compile 'com.android.support:recyclerview-v7:+' 6 | //} 7 | 8 | android { 9 | defaultConfig { 10 | generatedDensities = [] 11 | } 12 | aaptOptions { 13 | additionalParameters "--no-version-vectors" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /demo/app/App_Resources/Android/drawable-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/Android/drawable-hdpi/icon.png -------------------------------------------------------------------------------- /demo/app/App_Resources/Android/drawable-ldpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/Android/drawable-ldpi/icon.png -------------------------------------------------------------------------------- /demo/app/App_Resources/Android/drawable-mdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/Android/drawable-mdpi/icon.png -------------------------------------------------------------------------------- /demo/app/App_Resources/Android/drawable-nodpi/splashscreen.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/Android/drawable-nodpi/splashscreen.9.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/Default-568h@2x.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/Default-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/Default-667h@2x.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/Default-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/Default-736h@3x.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/Default-Landscape-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/Default-Landscape-568h@2x.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/Default-Landscape-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/Default-Landscape-667h@2x.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/Default-Landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/Default-Landscape.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/Default-Landscape@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/Default-Landscape@2x.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/Default-Landscape@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/Default-Landscape@3x.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/Default-Portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/Default-Portrait.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/Default-Portrait@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/Default-Portrait@2x.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/Default.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/Default@2x.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/Icon-Small-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/Icon-Small-50.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/Icon-Small-50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/Icon-Small-50@2x.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/Icon-Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/Icon-Small.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/Icon-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/Icon-Small@2x.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFile 12 | icon.png 13 | CFBundleIcons 14 | 15 | CFBundlePrimaryIcon 16 | 17 | CFBundleIconFiles 18 | 19 | icon-40 20 | icon-60 21 | icon-72 22 | icon-76 23 | Icon-Small 24 | Icon-Small-50 25 | 26 | UIPrerenderedIcon 27 | 28 | 29 | 30 | CFBundleInfoDictionaryVersion 31 | 6.0 32 | CFBundleName 33 | ${PRODUCT_NAME} 34 | CFBundlePackageType 35 | APPL 36 | CFBundleShortVersionString 37 | 1.0 38 | CFBundleSignature 39 | ???? 40 | CFBundleVersion 41 | 1.0 42 | LSRequiresIPhoneOS 43 | 44 | UILaunchStoryboardName 45 | LaunchScreen 46 | UIRequiresFullScreen 47 | 48 | UIRequiredDeviceCapabilities 49 | 50 | armv7 51 | 52 | UISupportedInterfaceOrientations 53 | 54 | UIInterfaceOrientationPortrait 55 | UIInterfaceOrientationLandscapeLeft 56 | UIInterfaceOrientationLandscapeRight 57 | 58 | UISupportedInterfaceOrientations~ipad 59 | 60 | UIInterfaceOrientationPortrait 61 | UIInterfaceOrientationPortraitUpsideDown 62 | UIInterfaceOrientationLandscapeLeft 63 | UIInterfaceOrientationLandscapeRight 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/build.xcconfig: -------------------------------------------------------------------------------- 1 | // You can add custom settings here 2 | // for example you can uncomment the following line to force distribution code signing 3 | // CODE_SIGN_IDENTITY = iPhone Distribution 4 | // ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 5 | // ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = Brand Assets; 6 | -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/icon-40.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/icon-40@2x.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/icon-60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/icon-60.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/icon-60@2x.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/icon-72.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/icon-72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/icon-72@2x.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/icon-76.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/icon-76@2x.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/icon.png -------------------------------------------------------------------------------- /demo/app/App_Resources/iOS/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/App_Resources/iOS/icon@2x.png -------------------------------------------------------------------------------- /demo/app/app.css: -------------------------------------------------------------------------------- 1 | .title { 2 | font-size: 30; 3 | horizontal-align: center; 4 | margin: 20; 5 | } 6 | 7 | button { 8 | font-size: 42; 9 | horizontal-align: center; 10 | } 11 | 12 | .message { 13 | font-size: 20; 14 | color: #284848; 15 | horizontal-align: center; 16 | margin: 0 20; 17 | text-align: center; 18 | } 19 | -------------------------------------------------------------------------------- /demo/app/app.js: -------------------------------------------------------------------------------- 1 | var application = require("application"); 2 | application.start({ moduleName: "main-page" }); 3 | -------------------------------------------------------------------------------- /demo/app/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /demo/app/fonts/LICENSE.txt: -------------------------------------------------------------------------------- 1 | http://fontawesome.io/license/ -------------------------------------------------------------------------------- /demo/app/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /demo/app/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /demo/app/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /demo/app/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/0e16a64f4b7c5794a1c66cd025c6f5759be899f6/demo/app/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /demo/app/main-page.js: -------------------------------------------------------------------------------- 1 | var createViewModel = require("./main-view-model").createViewModel; 2 | 3 | function onNavigatingTo(args) { 4 | var page = args.object; 5 | page.bindingContext = createViewModel(); 6 | } 7 | exports.onNavigatingTo = onNavigatingTo; -------------------------------------------------------------------------------- /demo/app/main-page.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /demo/app/main-view-model.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var BitmapFactory = require("nativescript-bitmap-factory"); 3 | var observable_1 = require("data/observable"); 4 | var KnownColors = require("color/known-colors"); 5 | function createViewModel() { 6 | var viewModel = new observable_1.Observable(); 7 | var bmp = BitmapFactory.create(300); 8 | bmp.dispose(function (b) { 9 | try { 10 | /* b.drawRect({ x: 150, y: 150 }, 11 | '300x150', 12 | KnownColors.Red, KnownColors.Black); */ 13 | /* for (var i = 0; i < b.width; i++) { 14 | b.setPoint({ x: i, y: 150 }, 15 | KnownColors.Red); 16 | } */ 17 | b.drawOval("300,150", "0,75", KnownColors.Red, KnownColors.Black); 18 | b.drawCircle(80, null, KnownColors.DarkGreen); 19 | b.setPoint("160,150", KnownColors.Yellow); 20 | b.drawLine("0,150", "300,75", KnownColors.Blue); 21 | // b.drawRect("150,150", "30x20", KnownColors.White); 22 | // var p = b.getPoint({ x: 150, y: 150 }); 23 | // console.log("Point: " + [p.a, p.r, p.g, p.b]); 24 | b.writeText("This is a test! " + '\uf087', "100,100", { 25 | color: KnownColors.Yellow, 26 | size: 10, 27 | name: 'fontawesome-webfont', 28 | }); 29 | var b2 = b.clone().resize("20x20"); 30 | b.insert(b2, "25,25"); 31 | viewModel.set('image', b.rotate(-37).toDataUrl()); 32 | } 33 | catch (e) { 34 | console.log('ERROR: ' + e); 35 | } 36 | }); 37 | console.log("Bitmap disposed!"); 38 | console.log("Bitmap.isDisposed: " + bmp.isDisposed); 39 | return viewModel; 40 | } 41 | exports.createViewModel = createViewModel; 42 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi12aWV3LW1vZGVsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibWFpbi12aWV3LW1vZGVsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxJQUFPLGFBQWEsV0FBVyw2QkFBNkIsQ0FBQyxDQUFDO0FBQzlELDJCQUF5QixpQkFBaUIsQ0FBQyxDQUFBO0FBQzNDLElBQU8sV0FBVyxXQUFXLG9CQUFvQixDQUFDLENBQUM7QUFJbkQ7SUFDSSxJQUFJLFNBQVMsR0FBUSxJQUFJLHVCQUFVLEVBQUUsQ0FBQztJQUV0QyxJQUFJLEdBQUcsR0FBRyxhQUFhLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3BDLEdBQUcsQ0FBQyxPQUFPLENBQUMsVUFBQyxDQUFDO1FBQ1YsSUFBSSxDQUFDO1lBQ0Q7OzBEQUU4QztZQUU5Qzs7O2dCQUdJO1lBR0osQ0FBQyxDQUFDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsTUFBTSxFQUFFLFdBQVcsQ0FBQyxHQUFHLEVBQUUsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ2xFLENBQUMsQ0FBQyxVQUFVLENBQUMsRUFBRSxFQUFFLElBQUksRUFBRSxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUM7WUFFOUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBRTFDLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7WUFFaEQscURBQXFEO1lBRXJELDBDQUEwQztZQUMxQyxpREFBaUQ7WUFFakQsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxrQkFBa0IsR0FBRyxRQUFRLEVBQUUsU0FBUyxFQUFFO2dCQUNsRCxLQUFLLEVBQUUsV0FBVyxDQUFDLE1BQU07Z0JBQ3pCLElBQUksRUFBRSxFQUFFO2dCQUNSLElBQUksRUFBRSxxQkFBcUI7YUFDOUIsQ0FBQyxDQUFDO1lBRUgsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUNuQyxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUV0QixTQUFTLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQztRQUN0RCxDQUNBO1FBQUEsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNQLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQy9CLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILE9BQU8sQ0FBQyxHQUFHLENBQUMsa0JBQWtCLENBQUMsQ0FBQztJQUNoQyxPQUFPLENBQUMsR0FBRyxDQUFDLHFCQUFxQixHQUFHLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUVwRCxNQUFNLENBQUMsU0FBUyxDQUFDO0FBQ3JCLENBQUM7QUFoRGUsdUJBQWUsa0JBZ0Q5QixDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IEJpdG1hcEZhY3RvcnkgPSByZXF1aXJlKFwibmF0aXZlc2NyaXB0LWJpdG1hcC1mYWN0b3J5XCIpO1xuaW1wb3J0IHtPYnNlcnZhYmxlfSBmcm9tIFwiZGF0YS9vYnNlcnZhYmxlXCI7XG5pbXBvcnQgS25vd25Db2xvcnMgPSByZXF1aXJlKFwiY29sb3Iva25vd24tY29sb3JzXCIpO1xuaW1wb3J0IEltYWdlU291cmNlID0gcmVxdWlyZSgnaW1hZ2Utc291cmNlJyk7XG5pbXBvcnQgSW1hZ2UgPSByZXF1aXJlKCd1aS9pbWFnZScpO1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlVmlld01vZGVsKCkge1xuICAgIHZhciB2aWV3TW9kZWw6IGFueSA9IG5ldyBPYnNlcnZhYmxlKCk7XG5cbiAgICB2YXIgYm1wID0gQml0bWFwRmFjdG9yeS5jcmVhdGUoMzAwKTtcbiAgICBibXAuZGlzcG9zZSgoYikgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgLyogYi5kcmF3UmVjdCh7IHg6IDE1MCwgeTogMTUwIH0sXG4gICAgICAgICAgICAgICAgICAgJzMwMHgxNTAnLFxuICAgICAgICAgICAgICAgICAgIEtub3duQ29sb3JzLlJlZCwgS25vd25Db2xvcnMuQmxhY2spOyAqL1xuXG4gICAgICAgICAgICAvKiBmb3IgKHZhciBpID0gMDsgaSA8IGIud2lkdGg7IGkrKykge1xuICAgIGIuc2V0UG9pbnQoeyB4OiBpLCB5OiAxNTAgfSxcbiAgICAgICAgICAgICAgICAgICAgS25vd25Db2xvcnMuUmVkKTtcbiAgICAgICAgICAgIH0gKi9cbiAgICAgICAgICAgIFxuXG4gICAgICAgICAgICBiLmRyYXdPdmFsKFwiMzAwLDE1MFwiLCBcIjAsNzVcIiwgS25vd25Db2xvcnMuUmVkLCBLbm93bkNvbG9ycy5CbGFjayk7XG4gICAgICAgICAgICBiLmRyYXdDaXJjbGUoODAsIG51bGwsIEtub3duQ29sb3JzLkRhcmtHcmVlbik7XG5cbiAgICAgICAgICAgIGIuc2V0UG9pbnQoXCIxNjAsMTUwXCIsIEtub3duQ29sb3JzLlllbGxvdyk7XG5cbiAgICAgICAgICAgIGIuZHJhd0xpbmUoXCIwLDE1MFwiLCBcIjMwMCw3NVwiLCBLbm93bkNvbG9ycy5CbHVlKTtcblxuICAgICAgICAgICAgLy8gYi5kcmF3UmVjdChcIjE1MCwxNTBcIiwgXCIzMHgyMFwiLCBLbm93bkNvbG9ycy5XaGl0ZSk7XG5cbiAgICAgICAgICAgIC8vIHZhciBwID0gYi5nZXRQb2ludCh7IHg6IDE1MCwgeTogMTUwIH0pO1xuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJQb2ludDogXCIgKyBbcC5hLCBwLnIsIHAuZywgcC5iXSk7XG5cbiAgICAgICAgICAgIGIud3JpdGVUZXh0KFwiVGhpcyBpcyBhIHRlc3QhIFwiICsgJ1xcdWYwODcnLCBcIjEwMCwxMDBcIiwge1xuICAgICAgICAgICAgICAgIGNvbG9yOiBLbm93bkNvbG9ycy5ZZWxsb3csXG4gICAgICAgICAgICAgICAgc2l6ZTogMTAsXG4gICAgICAgICAgICAgICAgbmFtZTogJ2ZvbnRhd2Vzb21lLXdlYmZvbnQnLFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHZhciBiMiA9IGIuY2xvbmUoKS5yZXNpemUoXCIyMHgyMFwiKTtcbiAgICAgICAgICAgIGIuaW5zZXJ0KGIyLCBcIjI1LDI1XCIpO1xuXG4gICAgICAgICAgICB2aWV3TW9kZWwuc2V0KCdpbWFnZScsIGIucm90YXRlKC0zNykudG9EYXRhVXJsKCkpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnRVJST1I6ICcgKyBlKTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIFxuICAgIGNvbnNvbGUubG9nKFwiQml0bWFwIGRpc3Bvc2VkIVwiKTtcbiAgICBjb25zb2xlLmxvZyhcIkJpdG1hcC5pc0Rpc3Bvc2VkOiBcIiArIGJtcC5pc0Rpc3Bvc2VkKTtcblxuICAgIHJldHVybiB2aWV3TW9kZWw7XG59XG4iXX0= -------------------------------------------------------------------------------- /demo/app/main-view-model.ts: -------------------------------------------------------------------------------- 1 | import BitmapFactory = require("nativescript-bitmap-factory"); 2 | import {Observable} from "data/observable"; 3 | import KnownColors = require("color/known-colors"); 4 | import ImageSource = require('image-source'); 5 | import Image = require('ui/image'); 6 | 7 | export function createViewModel() { 8 | var viewModel: any = new Observable(); 9 | 10 | var bmp = BitmapFactory.create(300); 11 | bmp.dispose((b) => { 12 | try { 13 | /* b.drawRect({ x: 150, y: 150 }, 14 | '300x150', 15 | KnownColors.Red, KnownColors.Black); */ 16 | 17 | /* for (var i = 0; i < b.width; i++) { 18 | b.setPoint({ x: i, y: 150 }, 19 | KnownColors.Red); 20 | } */ 21 | 22 | 23 | b.drawOval("300,150", "0,75", KnownColors.Red, KnownColors.Black); 24 | b.drawCircle(80, null, KnownColors.DarkGreen); 25 | 26 | b.setPoint("160,150", KnownColors.Yellow); 27 | 28 | b.drawLine("0,150", "300,75", KnownColors.Blue); 29 | 30 | // b.drawRect("150,150", "30x20", KnownColors.White); 31 | 32 | // var p = b.getPoint({ x: 150, y: 150 }); 33 | // console.log("Point: " + [p.a, p.r, p.g, p.b]); 34 | 35 | b.writeText("This is a test! " + '\uf087', "100,100", { 36 | color: KnownColors.Yellow, 37 | size: 10, 38 | name: 'fontawesome-webfont', 39 | }); 40 | 41 | var b2 = b.clone().resize("20x20"); 42 | b.insert(b2, "25,25"); 43 | 44 | viewModel.set('image', b.rotate(-37).toDataUrl()); 45 | } 46 | catch (e) { 47 | console.log('ERROR: ' + e); 48 | } 49 | }); 50 | 51 | console.log("Bitmap disposed!"); 52 | console.log("Bitmap.isDisposed: " + bmp.isDisposed); 53 | 54 | return viewModel; 55 | } 56 | -------------------------------------------------------------------------------- /demo/app/package.json: -------------------------------------------------------------------------------- 1 | {"name":"tns-template-hello-world","main":"app.js","version":"2.0.0","author":{"name":"Telerik","email":"support@telerik.com"},"description":"Nativescript hello-world project template","license":"Apache-2.0","keywords":["telerik","mobile","nativescript","{N}","tns","appbuilder","template"],"repository":{"type":"git","url":"git://github.com/NativeScript/template-hello-world.git"},"bugs":{"url":"https://github.com/NativeScript/template-hello-world/issues"},"homepage":"https://github.com/NativeScript/template-hello-world","android":{"v8Flags":"--expose_gc"},"readme":"ERROR: No README data found!","_id":"tns-template-hello-world@2.0.0","_from":"tns-template-hello-world@2.0.0"} -------------------------------------------------------------------------------- /demo/app/references.d.ts: -------------------------------------------------------------------------------- 1 | /// Enable smart suggestions and completions in Visual Studio Code JavaScript projects. 2 | -------------------------------------------------------------------------------- /demo/hooks/before-prepare/nativescript-dev-typescript.js: -------------------------------------------------------------------------------- 1 | module.exports = require("nativescript-dev-typescript/lib/before-prepare.js"); 2 | -------------------------------------------------------------------------------- /demo/hooks/before-watch/nativescript-dev-typescript.js: -------------------------------------------------------------------------------- 1 | module.exports = require("nativescript-dev-typescript/lib/watch.js"); 2 | -------------------------------------------------------------------------------- /demo/livesync.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | CLS 3 | 4 | CALL tns plugin remove nativescript-bitmap-factory 5 | 6 | CD .. 7 | CD plugin 8 | ECHO Rebuild plugin... 9 | CALL tsc 10 | CALL tsc -d 11 | ECHO Done 12 | 13 | CD .. 14 | CD demo 15 | 16 | CALL tns plugin add ..\plugin 17 | 18 | CALL tns livesync --watch 19 | -------------------------------------------------------------------------------- /demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "NativeScript Application", 3 | "license": "SEE LICENSE IN ", 4 | "readme": "NativeScript Application", 5 | "repository": "", 6 | "nativescript": { 7 | "id": "org.nativescript.NativeScriptBitmapFactory", 8 | "tns-android": { 9 | "version": "2.5.0" 10 | } 11 | }, 12 | "dependencies": { 13 | "nativescript-bitmap-factory": "file:..\\plugin", 14 | "tns-core-modules": "^2.5.0" 15 | }, 16 | "devDependencies": { 17 | "babel-traverse": "6.19.0", 18 | "babel-types": "6.19.0", 19 | "babylon": "6.14.1", 20 | "lazy": "1.0.11", 21 | "nativescript-dev-typescript": "^0.3.2", 22 | "typescript": "^1.8.10" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /demo/references.d.ts: -------------------------------------------------------------------------------- 1 | /// Needed for autocompletion and compilation. -------------------------------------------------------------------------------- /demo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es5", 5 | "experimentalDecorators": true, 6 | "emitDecoratorMetadata": true, 7 | "noEmitHelpers": true, 8 | "noEmitOnError": true 9 | }, 10 | "exclude": [ 11 | "node_modules", 12 | "platforms" 13 | ] 14 | } -------------------------------------------------------------------------------- /plugin/.npmignore: -------------------------------------------------------------------------------- 1 | *.map 2 | index.ts 3 | tsconfig.json 4 | references.d.ts -------------------------------------------------------------------------------- /plugin/BitmapFactory.android.js: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) Marcel Joachim Kloubert 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to 7 | // deal in the Software without restriction, including without limitation the 8 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9 | // sell copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | // DEALINGS IN THE SOFTWARE. 22 | 23 | var Application = require('application'); 24 | var BitmapFactoryCommons = require('./BitmapFactory.commons'); 25 | var FS = require('file-system'); 26 | var ImageSource = require('image-source'); 27 | var TypeUtils = require("utils/types"); 28 | 29 | 30 | // default options 31 | var defaultOptions; 32 | function getDefaultOpts() { 33 | return defaultOptions; 34 | } 35 | exports.getDefaultOpts = getDefaultOpts; 36 | function setDefaultOpts(opts) { 37 | defaultOptions = opts; 38 | } 39 | exports.setDefaultOpts = setDefaultOpts; 40 | 41 | function AndroidBitmap(bitmap, opts) { 42 | if (!(this instanceof AndroidBitmap)) { 43 | return new AndroidBitmap(bitmap, opts); 44 | } 45 | 46 | this._isDisposed = false; 47 | this._nativeObject = bitmap; 48 | this._options = opts; 49 | this._c = new android.graphics.Canvas(bitmap); 50 | } 51 | exports.BitmapClass = AndroidBitmap; 52 | 53 | // [ANDROID INTERNAL] __canvas 54 | Object.defineProperty(AndroidBitmap.prototype, '__canvas', { 55 | get: function() { return this._c; } 56 | }); 57 | 58 | // [ANDROID INTERNAL] __context 59 | Object.defineProperty(AndroidBitmap.prototype, '__context', { 60 | get: function() { return this.android.context; } 61 | }); 62 | 63 | // [ANDROID INTERNAL] __createPaint() 64 | AndroidBitmap.prototype.__createPaint = function(color) { 65 | var paint = new android.graphics.Paint(); 66 | 67 | if (!TypeUtils.isNullOrUndefined(color)) { 68 | paint.setARGB(color.a, color.r, color.g, color.b); 69 | } 70 | 71 | return paint; 72 | }; 73 | 74 | // [INTERNAL] _clone() 75 | AndroidBitmap.prototype._clone = function() { 76 | return new AndroidBitmap(this._nativeObject 77 | .copy(this._nativeObject.getConfig(), true)); 78 | }; 79 | 80 | // [INTERNAL] _crop() 81 | AndroidBitmap.prototype._crop = function(leftTop, size) { 82 | return android.graphics.Bitmap.createBitmap(this._nativeObject, 83 | leftTop.x, leftTop.y, 84 | size.width, size.height); 85 | }; 86 | 87 | // [INTERNAL] _dispose() 88 | AndroidBitmap.prototype._dispose = function(action, tag) { 89 | this._nativeObject.recycle(); 90 | }; 91 | 92 | // [INTERNAL] _drawLine() 93 | AndroidBitmap.prototype._drawLine = function(start, end, color) { 94 | this.__canvas.drawLine(start.x, start.y, 95 | end.x, end.y, 96 | this.__createPaint(color)); 97 | }; 98 | 99 | // [INTERNAL] _drawOval() 100 | AndroidBitmap.prototype._drawOval = function(size, leftTop, color, fillColor) { 101 | var me = this; 102 | 103 | var paintLine = this.__createPaint(color); 104 | paintLine.setStyle(android.graphics.Paint.Style.STROKE); 105 | 106 | var paints = []; 107 | paints.push(paintLine); 108 | 109 | if (null !== fillColor) { 110 | var paintFill = this.__createPaint(fillColor); 111 | paintFill.setStyle(android.graphics.Paint.Style.FILL); 112 | 113 | paints.push(paintFill); 114 | } 115 | 116 | var drawer = function(r, p) { 117 | me.__canvas.drawOval(r, p); 118 | }; 119 | if (size.width == size.height) { 120 | var drawer = function(r, p) { 121 | var radius = (r.right - r.left) / 2.0; 122 | 123 | me.__canvas.drawCircle(r.left + radius, r.top + radius, 124 | radius, 125 | p); 126 | }; 127 | } 128 | 129 | for (var i = paints.length; i > 0; i--) { 130 | var left = leftTop.x; 131 | var top = leftTop.y; 132 | var right = left + size.width - 1; 133 | var bottom = top + size.height - 1; 134 | 135 | var rect = new android.graphics.RectF(left, top, 136 | right, bottom); 137 | 138 | drawer(rect, paints[i - 1]); 139 | } 140 | }; 141 | 142 | // [INTERNAL] _drawArc() 143 | AndroidBitmap.prototype._drawArc = function(size, leftTop, startAngle, sweepAngle, color, fillColor) { 144 | var me = this; 145 | 146 | var paintLine = this.__createPaint(color); 147 | paintLine.setStyle(android.graphics.Paint.Style.STROKE); 148 | 149 | var paints = []; 150 | paints.push(paintLine); 151 | 152 | if (null !== fillColor) { 153 | var paintFill = this.__createPaint(fillColor); 154 | paintFill.setStyle(android.graphics.Paint.Style.FILL); 155 | 156 | paints.push(paintFill); 157 | } 158 | 159 | var drawer = function(r, s, e, u, p) { 160 | me.__canvas.drawArc(r, s, e, u, p); 161 | }; 162 | 163 | for (var i = paints.length; i > 0; i--) { 164 | var left = leftTop.x; 165 | var top = leftTop.y; 166 | var right = left + size.width - 1; 167 | var bottom = top + size.height - 1; 168 | 169 | var rect = new android.graphics.RectF(left, top, 170 | right, bottom); 171 | 172 | drawer(rect, startAngle, sweepAngle, true, paints[i - 1]); 173 | } 174 | }; 175 | 176 | // [INTERNAL] _drawRect() 177 | AndroidBitmap.prototype._drawRect = function(size, leftTop, color, fillColor) { 178 | var paintLine = this.__createPaint(color); 179 | paintLine.setStyle(android.graphics.Paint.Style.STROKE); 180 | 181 | var paints = []; 182 | paints.push(paintLine); 183 | 184 | if (null !== fillColor) { 185 | var paintFill = this.__createPaint(fillColor); 186 | paintFill.setStyle(android.graphics.Paint.Style.FILL); 187 | 188 | paints.push(paintFill); 189 | } 190 | 191 | for (var i = paints.length; i > 0; i--) { 192 | var left = leftTop.x; 193 | var top = leftTop.y; 194 | var right = left + size.width - 1; 195 | var bottom = top + size.height - 1; 196 | 197 | var rect = new android.graphics.RectF(left, top, 198 | right, bottom); 199 | 200 | this.__canvas 201 | .drawRect(rect, paints[i - 1]); 202 | } 203 | }; 204 | 205 | // [INTERNAL] _getPoint() 206 | AndroidBitmap.prototype._getPoint = function(coordinates) { 207 | return this._nativeObject 208 | .getPixel(coordinates.x, coordinates.y); 209 | }; 210 | 211 | // [INTERNAL] _insert() 212 | AndroidBitmap.prototype._insert = function(other, leftTop) { 213 | var bmp = asBitmapObject(other); 214 | if (false === bmp) { 215 | throw "NO valid bitmap!"; 216 | } 217 | 218 | this.__canvas.drawBitmap(bmp._nativeObject, 219 | leftTop.x, leftTop.y, 220 | null); 221 | }; 222 | 223 | // [INTERNAL] _rotate() 224 | AndroidBitmap.prototype._rotate = function(degrees) { 225 | var matrix = new android.graphics.Matrix(); 226 | matrix.postRotate(degrees); 227 | 228 | return android.graphics.Bitmap.createBitmap( 229 | this._nativeObject, 230 | 0, 0, 231 | this.width, this.height, 232 | matrix, 233 | true 234 | ); 235 | }; 236 | 237 | // [INTERNAL] _resize() 238 | AndroidBitmap.prototype._resize = function(newSize) { 239 | var resizedImage = android.graphics.Bitmap.createScaledBitmap(this._nativeObject, 240 | newSize.width, newSize.height, 241 | false); 242 | return new AndroidBitmap(resizedImage); 243 | }; 244 | 245 | // [INTERNAL] _setPoint() 246 | AndroidBitmap.prototype._setPoint = function(coordinates, color) { 247 | this._nativeObject 248 | .setPixel(coordinates.x, coordinates.y, 249 | android.graphics.Color.argb(color.a, color.r, color.g, color.b)); 250 | }; 251 | 252 | // _toObject() 253 | AndroidBitmap.prototype._toObject = function(format, quality) { 254 | var bmpFormat; 255 | var mime; 256 | switch (format) { 257 | case 1: 258 | bmpFormat = android.graphics.Bitmap.CompressFormat.PNG; 259 | mime = 'image/png'; 260 | break; 261 | 262 | case 2: 263 | bmpFormat = android.graphics.Bitmap.CompressFormat.JPEG; 264 | mime = 'image/jpeg'; 265 | break; 266 | } 267 | 268 | if (TypeUtils.isNullOrUndefined(bmpFormat)) { 269 | throw "Format '" + format + "' is NOT supported!"; 270 | } 271 | 272 | var stream = new java.io.ByteArrayOutputStream(); 273 | try { 274 | this._nativeObject 275 | .compress(bmpFormat, quality, stream); 276 | 277 | var bitmapData = {}; 278 | 279 | var base64 = android.util.Base64.encodeToString(stream.toByteArray(), 280 | android.util.Base64.NO_WRAP); 281 | 282 | // base64 283 | Object.defineProperty(bitmapData, 'base64', { 284 | get: function() { return base64; } 285 | }); 286 | 287 | // mime 288 | Object.defineProperty(bitmapData, 'mime', { 289 | get: function() { return mime; } 290 | }); 291 | 292 | return bitmapData; 293 | } 294 | finally { 295 | stream.close(); 296 | } 297 | } 298 | 299 | // _writeText() 300 | AndroidBitmap.prototype._writeText = function(txt, leftTop, font) { 301 | var resources = this.__context.getResources(); 302 | var scale = resources.getDisplayMetrics().density; 303 | 304 | var antiAlias; 305 | var fontColor; 306 | var fontSize = 10; 307 | var fontName; 308 | if (null !== font) { 309 | fontColor = font.color; 310 | fontSize = font.size; 311 | fontName = font.name; 312 | } 313 | 314 | if (TypeUtils.isNullOrUndefined(antiAlias)) { 315 | antiAlias = true; 316 | } 317 | 318 | var paint; 319 | if (antiAlias) { 320 | paint = new android.graphics.Paint(android.graphics.Paint.ANTI_ALIAS_FLAG); 321 | } 322 | else { 323 | paint = new android.graphics.Paint(); 324 | } 325 | 326 | fontColor = this.normalizeColor(fontColor); 327 | if (!TypeUtils.isNullOrUndefined(fontColor)) { 328 | paint.setARGB(fontColor.a, fontColor.r, fontColor.g, fontColor.b); 329 | } 330 | 331 | if (!TypeUtils.isNullOrUndefined(fontSize)) { 332 | paint.setTextSize(fontSize * scale); 333 | } 334 | 335 | if (!TypeUtils.isNullOrUndefined(fontName)) { 336 | fontName = ('' + fontName).trim(); 337 | 338 | var typeFace; 339 | 340 | if ('' !== fontName) { 341 | // based on code by Nick Iliev (https://github.com/NickIliev) 342 | // s. https://github.com/mkloubert/nativescript-bitmap-factory/issues/7#issuecomment-275691248 343 | 344 | try { 345 | var fontAssetPath; 346 | var basePath = FS.path.join(FS.knownFolders.currentApp().path, "fonts", fontName); 347 | if (FS.File.exists(basePath + ".ttf")) { 348 | fontAssetPath = "/fonts/" + fontName + ".ttf"; 349 | } 350 | 351 | if (fontAssetPath) { 352 | fontAssetPath = FS.path.join(FS.knownFolders.currentApp().path, fontAssetPath); 353 | 354 | typeFace = android.graphics.Typeface.createFromFile(fontAssetPath); 355 | } 356 | } 357 | catch (e) { 358 | console.log('[nativescript-bitmap-factory] AndroidBitmap._writeText(): ' + e); 359 | } 360 | 361 | if (!typeFace) { 362 | // fallback 363 | typeFace = android.graphics.Typeface.create(fontName, android.graphics.Typeface.NORMAL); 364 | } 365 | } 366 | 367 | if (typeFace) { 368 | paint.setTypeface(typeFace); 369 | } 370 | } 371 | 372 | paint.setXfermode(new android.graphics.PorterDuffXfermode(android.graphics.PorterDuff.Mode.SRC_OVER)); 373 | 374 | this.__canvas.drawText(txt, 375 | leftTop.x, leftTop.y, 376 | paint); 377 | }; 378 | 379 | // height 380 | Object.defineProperty(AndroidBitmap.prototype, 'height', { 381 | get: function() { return this._nativeObject.getHeight(); } 382 | }); 383 | 384 | // isDisposed 385 | Object.defineProperty(AndroidBitmap.prototype, 'isDisposed', { 386 | get: function() { return this._isDisposed; } 387 | }); 388 | 389 | // nativeObject 390 | Object.defineProperty(AndroidBitmap.prototype, 'nativeObject', { 391 | get: function() { return this._nativeObject; } 392 | }); 393 | 394 | // width 395 | Object.defineProperty(AndroidBitmap.prototype, 'width', { 396 | get: function() { return this._nativeObject.getWidth(); } 397 | }); 398 | 399 | // setup common methods and properties 400 | BitmapFactoryCommons.setupBitmapClass(AndroidBitmap); 401 | 402 | 403 | function asBitmapObject(v) { 404 | var bmp = BitmapFactoryCommons.tryGetBitmapObject(AndroidBitmap, v); 405 | if (false !== bmp) { 406 | return bmp; 407 | } 408 | 409 | var opts = defaultOptions; 410 | if (!opts) { 411 | opts = {}; 412 | } 413 | 414 | if (typeof v === "string") { 415 | var decodedBytes = android.util.Base64.decode(v, 0); 416 | try { 417 | var options = new android.graphics.BitmapFactory.Options(); 418 | options.inMutable = true; 419 | 420 | var bmp = android.graphics.BitmapFactory.decodeByteArray(decodedBytes, 0, decodedBytes.length, 421 | options); 422 | try { 423 | return new AndroidBitmap(bmp, opts); 424 | } 425 | catch (e) { 426 | bmp.recycle(); 427 | bmp = null; 428 | 429 | throw e; 430 | } 431 | } 432 | finally { 433 | decodedBytes = null; 434 | } 435 | } 436 | else if (v instanceof android.graphics.Bitmap) { 437 | return new AndroidBitmap(v, opts); 438 | } 439 | else if (v instanceof ImageSource.ImageSource) { 440 | return new AndroidBitmap(v.android, opts); 441 | } 442 | 443 | return false; 444 | } 445 | exports.asBitmapObject = asBitmapObject; 446 | AndroidBitmap.asBitmap = asBitmapObject; 447 | 448 | function createBitmap(width, height, opts) { 449 | var newBitmap = android.graphics.Bitmap.createBitmap(width, height, 450 | android.graphics.Bitmap.Config.ARGB_8888); 451 | 452 | return new AndroidBitmap(newBitmap, opts); 453 | } 454 | exports.createBitmap = createBitmap; 455 | 456 | function makeBitmapMutable(bitmap, opts) { 457 | if (bitmap instanceof ImageSource.ImageSource) { 458 | return new makeBitmapMutable(bitmap.android, opts); 459 | } 460 | 461 | if (bitmap instanceof AndroidBitmap) { 462 | return new makeBitmapMutable(bitmap.nativeObject, opts); 463 | } 464 | 465 | if (!(bitmap instanceof android.graphics.Bitmap)) { 466 | throw "No valid bitmap object!"; 467 | } 468 | 469 | var ctx = Application.android.context; 470 | 471 | var disposeCurrent = false; 472 | if (!TypeUtils.isNullOrUndefined(opts.disposeCurrent)) { 473 | disposeCurrent = opts.disposeCurrent; 474 | } 475 | 476 | var customCacheDir; 477 | var stradegy = 1; 478 | if (!TypeUtils.isNullOrUndefined(opts.temp)) { 479 | if (!TypeUtils.isNullOrUndefined(opts.temp.directory)) { 480 | customCacheDir = opts.temp.directory; 481 | } 482 | 483 | if (!TypeUtils.isNullOrUndefined(opts.temp.stradegy)) { 484 | stradegy = parseInt(('' + opts.temp.stradegy).trim()); 485 | } 486 | } 487 | 488 | var mutable; 489 | 490 | var disposeOldBitmap = function() { 491 | if (!disposeCurrent) { 492 | return; 493 | } 494 | 495 | try { 496 | bitmap.recycle(); 497 | bitmap = null; 498 | 499 | java.lang.System.gc(); 500 | } 501 | catch (e) { /* ignore */ } 502 | }; 503 | 504 | var createFromTempFile = function(dir) { 505 | if (!dir.exists()) { 506 | throw "'" + dir.getAbsolutePath() + "' does NOT exist!"; 507 | } 508 | 509 | if (!dir.isDirectory()) { 510 | throw "'" + dir.getAbsolutePath() + "' is no valid directory!"; 511 | } 512 | 513 | var tempFile = java.io.File.createTempFile("nsbmpfac", "dat", dir); 514 | try { 515 | var randomAccessFile = new java.io.RandomAccessFile(tempFile, "rw"); 516 | try { 517 | var width = bitmap.getWidth(); 518 | var height = bitmap.getHeight(); 519 | var cfg = bitmap.getConfig(); 520 | 521 | var channel = randomAccessFile.getChannel(); 522 | try { 523 | var map = channel.map(java.nio.channels.FileChannel.MapMode.READ_WRITE, 0, bitmap.getRowBytes() * height); 524 | 525 | bitmap.copyPixelsToBuffer(map); 526 | disposeOldBitmap(); 527 | 528 | mutable = android.graphics.Bitmap.createBitmap(width, height, cfg); 529 | 530 | map.position(0); 531 | mutable.copyPixelsFromBuffer(map); 532 | } 533 | finally { 534 | channel.close(); 535 | } 536 | } 537 | finally { 538 | randomAccessFile.close(); 539 | } 540 | } 541 | finally { 542 | try { 543 | tempFile.delete(); 544 | } 545 | catch (e) { 546 | try { 547 | tempFile.deleteOnExit(); 548 | } 549 | catch (e) { /* ignore */ }; 550 | } 551 | } 552 | }; 553 | 554 | switch (stradegy) { 555 | case 2: 556 | // cache directory 557 | var cacheDir = ctx.getCacheDir(); 558 | createFromTempFile(cacheDir); 559 | break; 560 | 561 | case 3: 562 | // external cache directory 563 | var extCacheDir = ctx.getExternalCacheDir(); 564 | createFromTempFile(extCacheDir); 565 | break; 566 | 567 | case 4: 568 | // custom cache directory 569 | var customDir = customCacheDir; 570 | if (TypeUtils.isNullOrUndefined(customDir)) { 571 | customDir = ctx.getCacheDir(); 572 | } 573 | 574 | if (!(customDir instanceof java.io.File)) { 575 | customDir = new java.io.File('' + customDir); 576 | } 577 | 578 | createFromTempFile(customDir); 579 | break; 580 | 581 | default: 582 | // memory 583 | mutable = bitmap.copy(bitmap.getConfig(), true); 584 | disposeOldBitmap(); 585 | break; 586 | } 587 | 588 | return mutable; 589 | } 590 | exports.makeBitmapMutable = makeBitmapMutable; 591 | -------------------------------------------------------------------------------- /plugin/BitmapFactory.commons.js: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) Marcel Joachim Kloubert 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to 7 | // deal in the Software without restriction, including without limitation the 8 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9 | // sell copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | // DEALINGS IN THE SOFTWARE. 22 | 23 | var Application = require("application"); 24 | var ImageSource = require('image-source'); 25 | var KnownColors = require("color/known-colors"); 26 | var TypeUtils = require("utils/types"); 27 | 28 | const REGEX_COLOR = /^(#)?([a-f0-9]{3,4}|[a-f0-9]{6}|[a-f0-9]{8})$/i; 29 | exports.REGEX_COLOR = REGEX_COLOR; 30 | 31 | const REGEX_POINT_2D = /^([0-9]+[\.]?[0-9]*)+(\s)*([\||,])(\s)*([0-9]+[\.]?[0-9]*)+$/i; 32 | exports.REGEX_POINT_2D = REGEX_POINT_2D; 33 | 34 | const REGEX_SIZE = /^([0-9]+[\.]?[0-9]*)+(\s)*([x|,])(\s)*([0-9]+[\.]?[0-9]*)+$/i; 35 | exports.REGEX_SIZE = REGEX_SIZE; 36 | 37 | function setupBitmapClass(bitmapClass) { 38 | // android 39 | Object.defineProperty(bitmapClass.prototype, 'android', { 40 | get: function() { return Application.android; } 41 | }); 42 | 43 | // clone() 44 | bitmapClass.prototype.clone = function() { 45 | return bitmapClass.asBitmap(this._clone()); 46 | }; 47 | 48 | // crop() 49 | bitmapClass.prototype.crop = function(leftTop, size) { 50 | if (TypeUtils.isNullOrUndefined(leftTop)) { 51 | leftTop = { 52 | x: 0, 53 | y: 0 54 | }; 55 | } 56 | 57 | leftTop = toPoint2D(leftTop); 58 | 59 | if (TypeUtils.isNullOrUndefined(size)) { 60 | size = { 61 | width: this.width - leftTop.x, 62 | y: this.height - leftTop.y 63 | }; 64 | } 65 | 66 | size = toSize(size); 67 | 68 | return new bitmapClass(this._crop(leftTop, size)); 69 | }; 70 | 71 | // defaultColor 72 | var _defColor = { a: 255, r: 0, g: 0, b: 0 }; 73 | Object.defineProperty(bitmapClass.prototype, 'defaultColor', { 74 | get: function() { return _defColor; }, 75 | 76 | set: function(newValue) { _defColor = toARGB(newValue); } 77 | }); 78 | 79 | // dispose() 80 | bitmapClass.prototype.dispose = function(action, tag) { 81 | if (this.isDisposed) { 82 | return; 83 | } 84 | 85 | try { 86 | if (!TypeUtils.isNullOrUndefined(action)) { 87 | return action(this, tag); 88 | } 89 | } 90 | finally { 91 | this._dispose(); 92 | this._isDisposed = true; 93 | } 94 | }; 95 | 96 | // drawCircle() 97 | bitmapClass.prototype.drawCircle = function(radius, center, color, fillColor) { 98 | if (TypeUtils.isNullOrUndefined(center)) { 99 | center = { 100 | x: this.width / 2.0, 101 | y: this.height / 2.0 102 | }; 103 | } 104 | 105 | center = toPoint2D(center); 106 | 107 | if (TypeUtils.isNullOrUndefined(radius)) { 108 | radius = Math.min((this.width - center.x) / 2.0, 109 | (this.height - center.y) / 2.0); 110 | } 111 | 112 | return this.drawOval({ width: radius * 2, height: radius * 2 }, 113 | { x: center.x - radius, y: center.y - radius }, 114 | color, fillColor); 115 | }; 116 | 117 | // drawLine() 118 | bitmapClass.prototype.drawLine = function(start, end, color) { 119 | start = toPoint2D(start); 120 | end = toPoint2D(end); 121 | color = toARGB(color); 122 | 123 | this._drawLine(start, end, color); 124 | return this; 125 | }; 126 | 127 | // drawOval() 128 | bitmapClass.prototype.drawOval = function(size, leftTop, color, fillColor) { 129 | if (TypeUtils.isNullOrUndefined(size)) { 130 | size = { 131 | height: this.height, 132 | width: this.width 133 | }; 134 | } 135 | 136 | if (TypeUtils.isNullOrUndefined(leftTop)) { 137 | leftTop = { 138 | x: 0, 139 | y: 0 140 | }; 141 | } 142 | 143 | size = toSize(size); 144 | leftTop = toPoint2D(leftTop); 145 | color = this.normalizeColor(color); 146 | fillColor = toARGB(fillColor); 147 | 148 | this._drawOval(size, leftTop, color, fillColor); 149 | return this; 150 | }; 151 | 152 | // drawArc() 153 | bitmapClass.prototype.drawArc = function(size, leftTop, startAngle, sweepAngle, color, fillColor) { 154 | if (TypeUtils.isNullOrUndefined(size)) { 155 | size = { 156 | height: this.height, 157 | width: this.width 158 | }; 159 | } 160 | 161 | if (TypeUtils.isNullOrUndefined(leftTop)) { 162 | leftTop = { 163 | x: 0, 164 | y: 0 165 | }; 166 | } 167 | 168 | size = toSize(size); 169 | leftTop = toPoint2D(leftTop); 170 | color = this.normalizeColor(color); 171 | fillColor = toARGB(fillColor); 172 | 173 | this._drawArc(size, leftTop, startAngle, sweepAngle, color, fillColor); 174 | return this; 175 | }; 176 | 177 | // drawRect() 178 | bitmapClass.prototype.drawRect = function(size, leftTop, color, fillColor) { 179 | if (TypeUtils.isNullOrUndefined(size)) { 180 | size = { 181 | height: this.height, 182 | width: this.width 183 | }; 184 | } 185 | 186 | if (TypeUtils.isNullOrUndefined(leftTop)) { 187 | leftTop = { 188 | x: 0, 189 | y: 0 190 | }; 191 | } 192 | 193 | size = toSize(size); 194 | leftTop = toPoint2D(leftTop); 195 | color = this.normalizeColor(color); 196 | fillColor = toARGB(fillColor); 197 | 198 | this._drawRect(size, leftTop, color, fillColor); 199 | return this; 200 | }; 201 | 202 | // getPoint 203 | bitmapClass.prototype.getPoint = function(coordinates, color) { 204 | if (TypeUtils.isNullOrUndefined(coordinates)) { 205 | coordinates = { 206 | x: this.width / 2.0, 207 | y: this.height / 2.0 208 | }; 209 | } 210 | 211 | return toARGB(this._getPoint(coordinates)); 212 | }; 213 | 214 | // insert() 215 | bitmapClass.prototype.insert = function(other, leftTop) { 216 | if (TypeUtils.isNullOrUndefined(leftTop)) { 217 | leftTop = { 218 | x: 0, 219 | y: 0 220 | }; 221 | } 222 | 223 | leftTop = toPoint2D(leftTop); 224 | 225 | if (!TypeUtils.isNullOrUndefined(other)) { 226 | this._insert(other, leftTop); 227 | } 228 | return this; 229 | }; 230 | 231 | // ios 232 | Object.defineProperty(bitmapClass.prototype, 'ios', { 233 | get: function() { return Application.ios; } 234 | }); 235 | 236 | // normalizeColor() 237 | bitmapClass.prototype.normalizeColor = function(c) { 238 | c = toARGB(c) || this.defaultColor; 239 | 240 | return !TypeUtils.isNullOrUndefined(c) ? c : null; 241 | }; 242 | 243 | // resize() 244 | bitmapClass.prototype.resize = function(newSize) { 245 | if (TypeUtils.isNullOrUndefined(newSize)) { 246 | newSize = { 247 | width: this.width, 248 | height: this.height 249 | }; 250 | } 251 | 252 | newSize = toSize(newSize); 253 | 254 | return bitmapClass.asBitmap(this._resize(newSize)); 255 | }; 256 | 257 | // resizeHeight() 258 | bitmapClass.prototype.resizeHeight = function(newHeight) { 259 | if (TypeUtils.isNullOrUndefined(newHeight)) { 260 | return this.clone(); 261 | } 262 | 263 | var ratio; 264 | if (0 != this.height) { 265 | ratio = newHeight / this.height; 266 | } 267 | else { 268 | if (0 != this.width) { 269 | ratio = newHeight / this.width; 270 | } 271 | else { 272 | ratio = 0; 273 | } 274 | } 275 | 276 | return this.resize({ width: this.width * ratio, 277 | height: newHeight }); 278 | }; 279 | 280 | // resizeMax() 281 | bitmapClass.prototype.resizeMax = function(maxSize) { 282 | if (this.width > this.height) { 283 | return this.resizeWidth(maxSize); 284 | } 285 | 286 | return this.resizeHeight(maxSize); 287 | }; 288 | 289 | // resizeWidth() 290 | bitmapClass.prototype.resizeWidth = function(newWidth) { 291 | if (TypeUtils.isNullOrUndefined(newWidth)) { 292 | return this.clone(); 293 | } 294 | 295 | var ratio; 296 | if (0 != this.width) { 297 | ratio = newWidth / this.width; 298 | } 299 | else { 300 | if (0 != this.height) { 301 | ratio = newWidth / this.height; 302 | } 303 | else { 304 | ratio = 0; 305 | } 306 | } 307 | 308 | return this.resize({ width: newWidth, 309 | height: this.height * ratio }); 310 | }; 311 | 312 | // rotate() 313 | bitmapClass.prototype.rotate = function(degrees) { 314 | if (TypeUtils.isNullOrUndefined(degrees)) { 315 | degrees = 90; 316 | } 317 | 318 | degrees = parseFloat(('' + degrees).trim()); 319 | 320 | return bitmapClass.asBitmap(this._rotate(degrees)); 321 | }; 322 | 323 | // setPoint 324 | bitmapClass.prototype.setPoint = function(coordinates, color) { 325 | if (TypeUtils.isNullOrUndefined(coordinates)) { 326 | coordinates = { 327 | x: this.width / 2.0, 328 | y: this.height / 2.0 329 | }; 330 | } 331 | 332 | coordinates = toPoint2D(coordinates); 333 | 334 | color = this.normalizeColor(color); 335 | 336 | this._setPoint(coordinates, color); 337 | return this; 338 | }; 339 | 340 | // size 341 | Object.defineProperty(bitmapClass.prototype, 'size', { 342 | get: function() { 343 | var _me = this; 344 | 345 | var _size = {}; 346 | 347 | Object.defineProperty(_size, 'height', { 348 | get: function() { return _me.height; } 349 | }); 350 | 351 | Object.defineProperty(_size, 'width', { 352 | get: function() { return _me.width; } 353 | }); 354 | 355 | return _size; 356 | } 357 | }); 358 | 359 | // toBase64() 360 | bitmapClass.prototype.toBase64 = function(format, quality) { 361 | return this.toObject(format, quality) 362 | .base64; 363 | }; 364 | 365 | // toDataUrl() 366 | bitmapClass.prototype.toDataUrl = function(format, quality) { 367 | var bd = this.toObject(format, quality); 368 | return 'data:' + bd.mime + ';base64,' + bd.base64; 369 | }; 370 | 371 | // toImageSource() 372 | bitmapClass.prototype.toImageSource = function() { 373 | var imgSrc = new ImageSource.ImageSource(); 374 | imgSrc.setNativeSource(this.nativeObject); 375 | 376 | return imgSrc; 377 | }; 378 | 379 | // toObject() 380 | bitmapClass.prototype.toObject = function(format, quality) { 381 | if (TypeUtils.isNullOrUndefined(format)) { 382 | format = 1; 383 | } 384 | 385 | if (TypeUtils.isNullOrUndefined(quality)) { 386 | quality = 100; 387 | } 388 | 389 | return this._toObject(format, quality); 390 | }; 391 | 392 | // writeText() 393 | bitmapClass.prototype.writeText = function(txt, leftTop, font) { 394 | if (TypeUtils.isNullOrUndefined(txt)) { 395 | txt = ''; 396 | } 397 | 398 | if (TypeUtils.isNullOrUndefined(leftTop)) { 399 | leftTop = { 400 | x: 0, 401 | y: 0 402 | }; 403 | } 404 | 405 | leftTop = toPoint2D(leftTop); 406 | font = toFont(font); 407 | 408 | txt = '' + txt; 409 | if ('' !== txt) { 410 | this._writeText(txt, leftTop, font); 411 | } 412 | return this; 413 | }; 414 | 415 | var _size = {}; 416 | } 417 | exports.setupBitmapClass = setupBitmapClass; 418 | 419 | function toARGB(v, throwException) { 420 | if (TypeUtils.isNullOrUndefined(v)) { 421 | return null; 422 | } 423 | 424 | var argb = { 425 | a: 255, 426 | r: 0, 427 | g: 0, 428 | b: 0 429 | }; 430 | 431 | var isValid = true; 432 | 433 | if (arguments.length < 2) { 434 | throwException = true; 435 | } 436 | 437 | var throwOrReturn = function() { 438 | if (isValid) { 439 | return argb; 440 | } 441 | 442 | if (throwException) { 443 | throw "NO valid color value!"; 444 | } 445 | 446 | return false; 447 | }; 448 | 449 | if (typeof v === "string") { 450 | // string 451 | 452 | v = v.toLowerCase().trim(); 453 | if (KnownColors[v] !== undefined) { // known color? 454 | return toARGB(KnownColors[v]); 455 | } 456 | 457 | var match = REGEX_COLOR.exec(v); 458 | 459 | isValid = null !== match; 460 | if (isValid) { 461 | var colorVal = match[2]; 462 | if (colorVal.length < 5) { 463 | // #(A)RGB 464 | 465 | var argbStartIndex = 3 === colorVal.length ? 0 : 1; 466 | 467 | if (4 === colorVal.length) { 468 | argb.a = parseInt(colorVal[0] + colorVal[0], 16); 469 | } 470 | argb.r = parseInt(colorVal[argbStartIndex] + colorVal[argbStartIndex], 16); 471 | argb.g = parseInt(colorVal[argbStartIndex + 1] + colorVal[argbStartIndex + 1], 16); 472 | argb.b = parseInt(colorVal[argbStartIndex + 2] + colorVal[argbStartIndex + 2], 16); 473 | } 474 | else { 475 | // #(AA)RRGGBB 476 | 477 | var argbStartIndex = 6 === colorVal.length ? 0 : 2; 478 | 479 | if (8 === colorVal.length) { 480 | argb.a = parseInt(colorVal.substr(0, 2), 16); 481 | } 482 | argb.r = parseInt(colorVal.substr(argbStartIndex, 2), 16); 483 | argb.g = parseInt(colorVal.substr(argbStartIndex + 2, 2), 16); 484 | argb.b = parseInt(colorVal.substr(argbStartIndex + 4, 2), 16); 485 | } 486 | } 487 | } 488 | else if (!isNaN(v)) { 489 | // number 490 | v = parseInt('' + v); 491 | if (v < 0) { 492 | v += 4294967296; 493 | } 494 | 495 | isValid = (v >= 0) && (v <= 4294967295); 496 | if (isValid) { 497 | var hex = ('0000000' + v.toString(16)).substr(-8); 498 | return toARGB('#' + hex); 499 | } 500 | } 501 | else if (typeof v === "object") { 502 | // object 503 | 504 | isValid = (typeof v.a !== undefined) && 505 | (typeof v.r !== undefined) && 506 | (typeof v.g !== undefined) && 507 | (typeof v.b !== undefined); 508 | 509 | if (isValid) { 510 | argb = v; 511 | } 512 | } 513 | 514 | return throwOrReturn(); 515 | } 516 | exports.toARGB = toARGB; 517 | 518 | function toFont(v, throwException) { 519 | if (TypeUtils.isNullOrUndefined(v)) { 520 | return null; 521 | } 522 | 523 | var font = {}; 524 | 525 | var isValid = true; 526 | 527 | if (arguments.length < 2) { 528 | throwException = true; 529 | } 530 | 531 | var throwOrReturn = function() { 532 | if (isValid) { 533 | return font; 534 | } 535 | 536 | if (throwException) { 537 | throw "NO valid font value!"; 538 | } 539 | 540 | return false; 541 | }; 542 | 543 | if (typeof v === "string") { 544 | // string 545 | 546 | v = v.trim(); 547 | 548 | isValid = '' !== v; 549 | if (isValid) { 550 | font.name = v; 551 | } 552 | } 553 | else if (typeof v === "object") { 554 | // object 555 | 556 | isValid = (typeof v.name !== undefined); 557 | 558 | if (isValid) { 559 | font = v; 560 | } 561 | } 562 | 563 | return throwOrReturn(); 564 | } 565 | exports.toFont = toFont; 566 | 567 | function toPoint2D(v, throwException) { 568 | if (TypeUtils.isNullOrUndefined(v)) { 569 | return null; 570 | } 571 | 572 | var point = {}; 573 | 574 | var isValid = true; 575 | 576 | if (arguments.length < 2) { 577 | throwException = true; 578 | } 579 | 580 | var throwOrReturn = function() { 581 | if (isValid) { 582 | return point; 583 | } 584 | 585 | if (throwException) { 586 | throw "NO valid 2D point value!"; 587 | } 588 | 589 | return false; 590 | }; 591 | 592 | if (typeof v === "string") { 593 | // string 594 | 595 | var match = REGEX_POINT_2D.exec(v.toLowerCase().trim()); 596 | 597 | isValid = null !== match; 598 | if (isValid) { 599 | point.x = parseFloat(match[1]); 600 | point.y = parseFloat(match[5]); 601 | } 602 | } 603 | else if (typeof v === "object") { 604 | // object 605 | 606 | isValid = (typeof v.x !== undefined) && 607 | (typeof v.y !== undefined); 608 | 609 | if (isValid) { 610 | point = v; 611 | } 612 | } 613 | 614 | return throwOrReturn(); 615 | } 616 | exports.toPoint2D = toPoint2D; 617 | 618 | function toSize(v, throwException) { 619 | if (TypeUtils.isNullOrUndefined(v)) { 620 | return null; 621 | } 622 | 623 | var size = {}; 624 | 625 | var isValid = true; 626 | 627 | if (arguments.length < 2) { 628 | throwException = true; 629 | } 630 | 631 | var throwOrReturn = function() { 632 | if (isValid) { 633 | return size; 634 | } 635 | 636 | if (throwException) { 637 | throw "NO valid size value!"; 638 | } 639 | 640 | return false; 641 | }; 642 | 643 | if (typeof v === "string") { 644 | // string 645 | 646 | var match = REGEX_SIZE.exec(v.toLowerCase().trim()); 647 | 648 | isValid = null !== match; 649 | if (isValid) { 650 | size.width = parseFloat(match[1]); 651 | size.height = parseFloat(match[5]); 652 | } 653 | } 654 | else if (typeof v === "object") { 655 | // object 656 | 657 | isValid = (typeof v.width !== undefined) && 658 | (typeof v.height !== undefined); 659 | 660 | if (isValid) { 661 | size = v; 662 | } 663 | } 664 | 665 | return throwOrReturn(); 666 | } 667 | exports.toSize = toSize; 668 | 669 | function tryGetBitmapObject(bitmapClass, v) { 670 | if (v instanceof bitmapClass) { 671 | return v; 672 | } 673 | 674 | if (TypeUtils.isNullOrUndefined(v)) { 675 | return null; 676 | } 677 | 678 | if (typeof v === "string") { 679 | v = v.trim(); 680 | if ('' === v) { 681 | return null; 682 | } 683 | } 684 | 685 | return false; 686 | } 687 | exports.tryGetBitmapObject = tryGetBitmapObject; 688 | -------------------------------------------------------------------------------- /plugin/BitmapFactory.ios.js: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) Marcel Joachim Kloubert 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to 7 | // deal in the Software without restriction, including without limitation the 8 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9 | // sell copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | // DEALINGS IN THE SOFTWARE. 22 | 23 | var BitmapFactoryCommons = require('./BitmapFactory.commons'); 24 | var ImageSource = require('image-source'); 25 | var TypeUtils = require("utils/types"); 26 | 27 | // default options 28 | var defaultOptions; 29 | function getDefaultOpts() { 30 | return defaultOptions; 31 | } 32 | exports.getDefaultOpts = getDefaultOpts; 33 | function setDefaultOpts(opts) { 34 | defaultOptions = opts; 35 | } 36 | exports.setDefaultOpts = setDefaultOpts; 37 | 38 | function iOSImage(uiImage, opts) { 39 | if (!(this instanceof iOSImage)) { 40 | return new iOSImage(uiImage, opts); 41 | } 42 | 43 | this._isDisposed = false; 44 | this._nativeObject = uiImage; 45 | this._options = opts; 46 | } 47 | exports.BitmapClass = iOSImage; 48 | 49 | // [iOS INTERNAL] __CGImage 50 | Object.defineProperty(iOSImage.prototype, '__CGImage', { 51 | get: function() { return this._nativeObject.CGImage; } 52 | }); 53 | 54 | // [iOS INTERNAL] __doAutoRelease 55 | Object.defineProperty(iOSImage.prototype, '__doAutoRelease', { 56 | get: function() { 57 | var autoRelease = true; 58 | 59 | var opts = this._options || {}; 60 | if (!TypeUtils.isNullOrUndefined(opts.ios)) { 61 | if (!TypeUtils.isNullOrUndefined(opts.ios.autoRelease)) { 62 | autoRelease = !!opts.ios.autoRelease; 63 | } 64 | } 65 | 66 | return autoRelease; 67 | } 68 | }); 69 | 70 | // [iOS INTERNAL] __onImageContext() 71 | iOSImage.prototype.__onImageContext = function(action, tag) { 72 | var oldImg = this._nativeObject; 73 | 74 | UIGraphicsBeginImageContext(CGSizeMake(oldImg.size.width, oldImg.size.height)); 75 | var newImage; 76 | var result; 77 | try { 78 | var context = UIGraphicsGetCurrentContext(); 79 | 80 | oldImg.drawInRect(CGRectMake(0, 0, 81 | oldImg.size.width, oldImg.size.height)); 82 | 83 | result = action(context, tag, oldImg); 84 | 85 | newImage = UIGraphicsGetImageFromCurrentImageContext(); 86 | } 87 | finally { 88 | UIGraphicsEndImageContext(); 89 | } 90 | 91 | this._nativeObject = newImage; 92 | 93 | // free memory of old image 94 | try { 95 | var cImg = oldImg.CGImage; 96 | try { 97 | if (!TypeUtils.isNullOrUndefined(cImg)) { 98 | if (!this.__doAutoRelease) { 99 | CGImageRelease(oldImg.CGImage); // invoke manually 100 | } 101 | } 102 | } 103 | finally { 104 | cImg = null; 105 | } 106 | } 107 | finally { 108 | oldImg = null; 109 | } 110 | 111 | return result; 112 | }; 113 | 114 | // [iOS INTERNAL] __toIOSColor() 115 | iOSImage.prototype.__toIOSColor = function(color) { 116 | if (TypeUtils.isNullOrUndefined(color)) { 117 | return null; 118 | } 119 | 120 | return { 121 | a: color.a / 255.0, 122 | r: color.r / 255.0, 123 | g: color.g / 255.0, 124 | b: color.b / 255.0 125 | }; 126 | }; 127 | 128 | // [INTERNAL] _clone() 129 | iOSImage.prototype._clone = function() { 130 | return new iOSImage(UIImage.imageWithData(UIImagePNGRepresentation(this._nativeObject))); 131 | }; 132 | 133 | // [INTERNAL] _crop() 134 | iOSImage.prototype._crop = function(leftTop, size) { 135 | return this.__onImageContext(function(context, tag, oldImage) { 136 | var rect = CGRectMake(leftTop.x, leftTop.y, 137 | size.width, size.height); 138 | 139 | var imageRef = CGImageCreateWithImageInRect(oldImage.CGImage, rect); 140 | return UIImage(imageRef); 141 | }); 142 | }; 143 | 144 | // _dispose() 145 | iOSImage.prototype._dispose = function(action, tag) { 146 | var nObj = this._nativeObject; 147 | try { 148 | if (!TypeUtils.isNullOrUndefined(nObj)) { 149 | var cImg = nObj.CGImage; 150 | try { 151 | if (!TypeUtils.isNullOrUndefined(cImg)) { 152 | if (!this.__doAutoRelease) { 153 | CGImageRelease(cImg); 154 | } 155 | } 156 | } 157 | finally { 158 | cImg = null; 159 | } 160 | } 161 | } 162 | finally { 163 | this._nativeObject = null; 164 | nObj = null; 165 | } 166 | }; 167 | 168 | // [INTERNAL] _drawLine() 169 | iOSImage.prototype._drawLine = function(start, end, color) { 170 | color = this.__toIOSColor(color); 171 | 172 | this.__onImageContext(function(context, tag, oldImage) { 173 | CGContextSetRGBStrokeColor(context, 174 | color.r, color.g, color.b, color.a); 175 | 176 | CGContextSetLineWidth(context, 1.0); 177 | 178 | CGContextMoveToPoint(context, start.x, start.y); 179 | CGContextAddLineToPoint(context, 180 | end.x, end.y); 181 | 182 | CGContextStrokePath(context); 183 | }); 184 | }; 185 | 186 | // [INTERNAL] _drawOval() 187 | iOSImage.prototype._drawOval = function(size, leftTop, color, fillColor) { 188 | color = this.__toIOSColor(color); 189 | fillColor = this.__toIOSColor(fillColor); 190 | 191 | this.__onImageContext(function(context, tag, oldImage) { 192 | CGContextSetRGBStrokeColor(context, 193 | color.r, color.g, color.b, color.a); 194 | 195 | var rect = CGRectMake(leftTop.x, leftTop.y, 196 | size.width, size.height); 197 | 198 | if (null !== fillColor) { 199 | CGContextSetRGBFillColor(context, 200 | fillColor.r, fillColor.g, fillColor.b, fillColor.a); 201 | 202 | CGContextFillEllipseInRect(context, rect); 203 | } 204 | 205 | CGContextStrokeEllipseInRect(context, rect); 206 | }); 207 | }; 208 | 209 | // [INTERNAL] _drawArc() 210 | iOSImage.prototype._drawArc = function(size, leftTop, startAngle, endAngle, color, fillColor) { 211 | color = this.__toIOSColor(color); 212 | fillColor = this.__toIOSColor(fillColor); 213 | 214 | // Angles come in degrees, convert to radians for iOS 215 | var iosStartAngle = startAngle*(Math.PI/180.0); 216 | // We get a sweep angle, add to start angle to get iOS end angle 217 | var iosEndAngle = iosStartAngle + endAngle*(Math.PI/180.0); 218 | 219 | this.__onImageContext(function(context, tag, oldImage) { 220 | CGContextSetRGBStrokeColor(context, 221 | color.r, color.g, color.b, color.a); 222 | 223 | var radius = Math.min(size.width, size.height)*0.5 224 | 225 | if (null !== fillColor) { 226 | CGContextSetRGBFillColor(context, 227 | fillColor.r, fillColor.g, fillColor.b, fillColor.a); 228 | 229 | } 230 | CGContextMoveToPoint(context, (size.width*0.5)+leftTop.x, (size.height*0.5)+leftTop.y); 231 | CGContextAddArc(context, (size.width*0.5)+leftTop.x, (size.height*0.5)+leftTop.y, radius, iosStartAngle, iosEndAngle, 0); 232 | if (null !== fillColor) { 233 | CGContextFillPath(context); 234 | } 235 | }); 236 | }; 237 | 238 | // [INTERNAL] _drawRect() 239 | iOSImage.prototype._drawRect = function(size, leftTop, color, fillColor) { 240 | color = this.__toIOSColor(color); 241 | fillColor = this.__toIOSColor(fillColor); 242 | 243 | this.__onImageContext(function(context, tag, oldImage) { 244 | CGContextSetRGBStrokeColor(context, 245 | color.r, color.g, color.b, color.a); 246 | 247 | var rect = CGRectMake(leftTop.x, leftTop.y, 248 | size.width, size.height); 249 | 250 | if (null !== fillColor) { 251 | CGContextSetRGBFillColor(context, 252 | fillColor.r, fillColor.g, fillColor.b, fillColor.a); 253 | 254 | CGContextFillRect(context, rect); 255 | } 256 | 257 | CGContextStrokeRect(context, rect); 258 | }); 259 | }; 260 | 261 | // [INTERNAL] _getPoint() 262 | iOSImage.prototype._getPoint = function(coordinates) { 263 | var pixelData = CGDataProviderCopyData(CGImageGetDataProvider(this.__CGImage)); 264 | var data = CFDataGetBytePtr(pixelData); 265 | 266 | var pixelInfo = ((this.width * coordinates.y) + coordinates.x) * 4; 267 | 268 | var r = data[pixelInfo]; 269 | var g = data[pixelInfo + 1]; 270 | var b = data[pixelInfo + 2]; 271 | var a = data[pixelInfo + 3]; 272 | 273 | return (a << 24) | (r << 16) | (g << 8) | b; 274 | }; 275 | 276 | // [INTERNAL] _insert() 277 | iOSImage.prototype._insert = function(other, leftTop) { 278 | var bmp = asBitmapObject(other); 279 | if (false === bmp) { 280 | throw "NO valid bitmap!"; 281 | } 282 | 283 | this.__onImageContext(function(context, tag, oldImage) { 284 | var left = leftTop.x; 285 | var top = leftTop.y; 286 | var width = Math.min(bmp.width, 287 | oldImage.size.width - left); 288 | var height = Math.min(bmp.height, 289 | oldImage.size.height - top); 290 | 291 | bmp._nativeObject 292 | .drawInRect(CGRectMake(leftTop.x, leftTop.y, 293 | width, height)); 294 | }); 295 | }; 296 | 297 | // [INTERNAL] _resize() 298 | iOSImage.prototype._resize = function(newSize) { 299 | var oldImg = this._nativeObject; 300 | 301 | try { 302 | var ns = CGSizeMake(newSize.width, newSize.height); 303 | UIGraphicsBeginImageContextWithOptions(ns, false, 0.0); 304 | 305 | oldImg.drawInRect(CGRectMake(0, 0, 306 | ns.width, ns.height)); 307 | 308 | return new iOSImage(UIGraphicsGetImageFromCurrentImageContext()); 309 | } 310 | finally { 311 | UIGraphicsEndImageContext(); 312 | } 313 | }; 314 | 315 | // [INTERNAL] _rotate() 316 | iOSImage.prototype._rotate = function(degrees) { 317 | radians = degrees * Math.PI / 180.0; 318 | 319 | var oldImg = this._nativeObject; 320 | 321 | try { 322 | UIGraphicsBeginImageContext(oldImg.size); 323 | 324 | var context = UIGraphicsGetCurrentContext(); 325 | 326 | CGContextRotateCTM(context, radians); 327 | 328 | oldImg.drawAtPoint(CGPointMake(0, 0)); 329 | 330 | return UIGraphicsGetImageFromCurrentImageContext(); 331 | } 332 | finally { 333 | UIGraphicsEndImageContext(); 334 | } 335 | }; 336 | 337 | // [INTERNAL] _setPoint() 338 | iOSImage.prototype._setPoint = function(coordinates, color) { 339 | color = this.__toIOSColor(color); 340 | 341 | this.__onImageContext(function(context) { 342 | CGContextSetRGBFillColor(context, color.r, color.g, color.b, color.a); 343 | 344 | CGContextFillRect(context, CGRectMake(coordinates.x, coordinates.y, 345 | 1, 1)); 346 | }); 347 | }; 348 | 349 | // [INTERNAL] _toObject() 350 | iOSImage.prototype._toObject = function(format, quality) { 351 | var img = this._nativeObject; 352 | 353 | var imageData = false; 354 | var mime; 355 | switch (format) { 356 | case 1: 357 | imageData = UIImagePNGRepresentation(img); 358 | mime = 'image/png'; 359 | break; 360 | 361 | case 2: 362 | imageData = UIImageJPEGRepresentation(img, quality / 100.0); 363 | mime = 'image/jpeg'; 364 | break; 365 | } 366 | 367 | if (false === imageData) { 368 | throw "Format '" + format + "' is NOT supported!"; 369 | } 370 | 371 | if (TypeUtils.isNullOrUndefined(imageData)) { 372 | throw "Output image could not be created by iOS!"; 373 | } 374 | 375 | var bitmapData = {}; 376 | 377 | var base64 = imageData.base64EncodedStringWithOptions(null); 378 | 379 | // base64 380 | Object.defineProperty(bitmapData, 'base64', { 381 | get: function() { return base64; } 382 | }); 383 | 384 | // mime 385 | Object.defineProperty(bitmapData, 'mime', { 386 | get: function() { return mime; } 387 | }); 388 | 389 | return bitmapData; 390 | } 391 | 392 | // _writeText() 393 | iOSImage.prototype._writeText = function(txt, leftTop, font) { 394 | var antiAlias; 395 | var fontColor; 396 | var fontSize; 397 | var fontName; 398 | if (null !== font) { 399 | fontColor = font.color; 400 | fontSize = font.size; 401 | fontName = font.name; 402 | } 403 | 404 | fontColor = this.normalizeColor(fontColor); 405 | fontColor = this.__toIOSColor(fontColor); 406 | 407 | if (TypeUtils.isNullOrUndefined(antiAlias)) { 408 | antiAlias = true; 409 | } 410 | 411 | var settings = NSMutableAttributedString.alloc().initWithString(txt); 412 | var settingsRange = NSMakeRange(0, settings.length); 413 | 414 | if (null !== fontColor) { 415 | var iosFontColor = UIColor.alloc() 416 | .initWithRedGreenBlueAlpha(fontColor.r, fontColor.g, fontColor.b, 417 | fontColor.a); 418 | 419 | settings.addAttributeValueRange(NSForegroundColorAttributeName, 420 | iosFontColor, 421 | settingsRange); 422 | } 423 | 424 | if (TypeUtils.isNullOrUndefined(fontSize)) { 425 | fontSize = 10; 426 | } 427 | 428 | var iosFont; 429 | if (!TypeUtils.isNullOrUndefined(fontName)) { 430 | fontName = ('' + fontName).trim(); 431 | if ('' !== fontName) { 432 | iosFont = UIFont.fontWithNameSize(fontName, fontSize); 433 | } 434 | } 435 | 436 | if (TypeUtils.isNullOrUndefined(iosFont)) { 437 | iosFont = UIFont.systemFontOfSize(fontSize); 438 | } 439 | 440 | settings.addAttributeValueRange(NSFontAttributeName, iosFont, 441 | settingsRange); 442 | 443 | this.__onImageContext(function(context, tag, oldImage) { 444 | if (antiAlias) { 445 | CGContextSetAllowsAntialiasing(context, true); 446 | CGContextSetShouldAntialias(context, true); 447 | } 448 | 449 | var rect = CGRectMake(leftTop.x, leftTop.y, 450 | oldImage.size.width, oldImage.size.height); 451 | 452 | settings.drawInRect(CGRectIntegral(rect)); 453 | }); 454 | }; 455 | 456 | // height 457 | Object.defineProperty(iOSImage.prototype, 'height', { 458 | get: function() { return this._nativeObject.size.height; } 459 | }); 460 | 461 | // isDisposed 462 | Object.defineProperty(iOSImage.prototype, 'isDisposed', { 463 | get: function() { return this._isDisposed; } 464 | }); 465 | 466 | // nativeObject 467 | Object.defineProperty(iOSImage.prototype, 'nativeObject', { 468 | get: function() { return this._nativeObject; } 469 | }); 470 | 471 | // width 472 | Object.defineProperty(iOSImage.prototype, 'width', { 473 | get: function() { return this._nativeObject.size.width; } 474 | }); 475 | 476 | // setup common methods and properties 477 | BitmapFactoryCommons.setupBitmapClass(iOSImage); 478 | 479 | 480 | function asBitmapObject(v) { 481 | var bmp = BitmapFactoryCommons.tryGetBitmapObject(iOSImage, v); 482 | if (false !== bmp) { 483 | return bmp; 484 | } 485 | 486 | var opts = defaultOptions; 487 | if (!opts) { 488 | opts = {}; 489 | } 490 | 491 | if (typeof v === "string") { 492 | var data = NSData.alloc() 493 | .initWithBase64Encoding(v); 494 | 495 | var img = UIImage.imageWithData(data); 496 | return new iOSImage(img, opts); 497 | } 498 | else if (v instanceof UIImage) { 499 | return new iOSImage(v, opts); 500 | } 501 | else if (v instanceof ImageSource.ImageSource) { 502 | return new iOSImage(v.ios, opts); 503 | } 504 | 505 | return false; 506 | } 507 | exports.asBitmapObject = asBitmapObject; 508 | iOSImage.asBitmap = asBitmapObject; 509 | 510 | function createBitmap(width, height, opts) { 511 | var img = new interop.Reference(); 512 | 513 | UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height), false, 0.0); 514 | img = UIGraphicsGetImageFromCurrentImageContext(); 515 | UIGraphicsEndImageContext(); 516 | 517 | if (TypeUtils.isNullOrUndefined(img)) { 518 | throw "Could not create UIImage!"; 519 | } 520 | 521 | return new iOSImage(img, opts); 522 | } 523 | exports.createBitmap = createBitmap; 524 | 525 | function makeBitmapMutable(uiImg, opts) { 526 | if (uiImg instanceof ImageSource.ImageSource) { 527 | return new makeBitmapMutable(uiImg.ios, opts); 528 | } 529 | 530 | if (uiImg instanceof iOSImage) { 531 | return new makeBitmapMutable(uiImg.nativeObject, opts); 532 | } 533 | 534 | if (!(uiImg instanceof UIImage)) { 535 | throw "No valid image object!"; 536 | } 537 | 538 | return UIImage.imageWithData(UIImagePNGRepresentation(uiImg)); 539 | } 540 | exports.makeBitmapMutable = makeBitmapMutable; 541 | -------------------------------------------------------------------------------- /plugin/README.md: -------------------------------------------------------------------------------- 1 | [![npm](https://img.shields.io/npm/v/nativescript-bitmap-factory.svg)](https://www.npmjs.com/package/nativescript-bitmap-factory) 2 | [![npm](https://img.shields.io/npm/dt/nativescript-bitmap-factory.svg?label=npm%20downloads)](https://www.npmjs.com/package/nativescript-bitmap-factory) 3 | 4 | # NativeScript Bitmap Factory 5 | 6 | A [NativeScript](https://nativescript.org/) module for creating and manipulating bitmap images. 7 | 8 | [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=U3FY9F6QMDQ4L&lc=DE&item_name=Marcel%20Kloubert&item_number=nativescript%2dbitmap%2dfactory&no_note=1&no_shipping=2¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted) 9 | 10 | ## NativeScript Toolbox 11 | 12 | This module is part of [nativescript-toolbox](https://github.com/mkloubert/nativescript-toolbox). 13 | 14 | ## License 15 | 16 | [MIT license](https://raw.githubusercontent.com/mkloubert/nativescript-bitmap-factory/master/LICENSE) 17 | 18 | ## Platforms 19 | 20 | * Android 21 | * iOS 22 | 23 | ## Installation 24 | 25 | Run 26 | 27 | ```bash 28 | tns plugin add nativescript-bitmap-factory 29 | ``` 30 | 31 | inside your app project to install the module. 32 | 33 | ## Usage 34 | 35 | ```typescript 36 | import BitmapFactory = require("nativescript-bitmap-factory"); 37 | import KnownColors = require("color/known-colors"); 38 | 39 | // create a bitmap with 640x480 40 | var bmp = BitmapFactory.create(640, 480); 41 | 42 | // work with bitmap and 43 | // keep sure to free memory 44 | // after we do not need it anymore 45 | bmp.dispose(() => { 46 | // draw an oval with a size of 300x150 47 | // and start at position x=0, y=75 48 | // and use 49 | // "red" as border color and "black" as background color. 50 | bmp.drawOval("300x150", "0,75", 51 | KnownColors.Red, KnownColors.Black); 52 | 53 | // draw a circle with a radius of 80 54 | // at the center of the bitmap (null => default) 55 | // and use 56 | // "dark green" as border color 57 | bmp.drawCircle(80, null, 58 | KnownColors.DarkGreen); 59 | 60 | // draws an arc with a size of 100x200 61 | // at x=10 and y=20 62 | // beginning at angle 0 with a sweep angle of 90 degrees 63 | // and a black border and a yellow fill color 64 | bmp.drawArc("100x200", "10,20", 65 | 0, 90, 66 | KnownColors.Black, KnownColors.Yellow); 67 | 68 | // set a yellow point at x=160, y=150 69 | bmp.setPoint("160,150", "ff0"); 70 | 71 | // draws a line from (0|150) to (300|75) 72 | // with blue color 73 | bmp.drawLine("0,150", "300,75", '#0000ff'); 74 | 75 | // writes a text in yellow color 76 | // at x=100, y=100 77 | // by using "Roboto" as font 78 | // with a size of 10 79 | bmp.writeText("This is a test!", "100,100", { 80 | color: KnownColors.Yellow, 81 | size: 10, 82 | name: "Roboto" 83 | }); 84 | 85 | // returns the current bitmap as data URL 86 | // which can be used as ImageSource 87 | // in JPEG format with a quality of 75% 88 | var data = bmp.toDataUrl(BitmapFactory.OutputFormat.JPEG, 75); 89 | 90 | // ... and in Base64 format 91 | var base64JPEG = bmp.toBase64(BitmapFactory.OutputFormat.JPEG, 75); 92 | 93 | // ... and as ImageSource 94 | var imgSrc = bmp.toImageSource(); 95 | }); 96 | ``` 97 | 98 | ## Functions 99 | 100 | | Name | Description | 101 | | ---- | --------- | 102 | | asBitmap | Returns a value as wrapped bitmap. | 103 | | create | Creates a new bitmap instance. | 104 | | getDefaultOptions | Returns the default options for creating a new bitmap. | 105 | | makeMutable | A helper function that keeps sure to return a native image object that is able to be used as wrapped bitmap object. | 106 | | setDefaultOptions | Sets the default options for creating a new bitmap. | 107 | 108 | ## Platform specific stuff 109 | 110 | You can access the `nativeObject` property to access the platform specific object. 111 | 112 | For Android this is a [Bitmap](https://developer.android.com/reference/android/graphics/Bitmap.html) object and for iOS this is an [UIImage](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIImage_Class/) object. 113 | 114 | To check the platform you can use the `android` and `ios` properties which have the same values as the corresponding properties from `application` core module. 115 | 116 | ### Android 117 | 118 | You also can access the underlying [Canvas](https://developer.android.com/reference/android/graphics/Canvas.html) object by `__canvas` property. 119 | 120 | ### iOS 121 | 122 | You also can access the underlying [CGImage](https://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CGImage/) object by`__CGImage` property. 123 | 124 | ## Data types 125 | 126 | ### IArgb 127 | 128 | Stores data of an RGB value with alpha value. 129 | 130 | These values can also be submitted as strings (like `#ff0` or `ffffff`) or numbers. 131 | 132 | ```typescript 133 | interface IArgb { 134 | /** 135 | * Gets the alpha value. 136 | */ 137 | a: number; 138 | 139 | /** 140 | * Gets the red value. 141 | */ 142 | r: number; 143 | 144 | /** 145 | * Gets the green value. 146 | */ 147 | g: number; 148 | 149 | /** 150 | * Gets the blue value. 151 | */ 152 | b: number; 153 | } 154 | ``` 155 | 156 | ### IBitmapData 157 | 158 | Used by `toObject()` method. 159 | 160 | ```typescript 161 | interface IBitmapData { 162 | /** 163 | * Gets the data as Base64 string. 164 | */ 165 | base64: string; 166 | 167 | /** 168 | * Gets the mime type. 169 | */ 170 | mime: string; 171 | } 172 | ``` 173 | 174 | ### IFont 175 | 176 | Font settings. 177 | 178 | ```typescript 179 | interface IFont { 180 | /** 181 | * Anti alias or not. 182 | */ 183 | antiAlias?: boolean; 184 | 185 | /** 186 | * Gets the custom forground color. 187 | */ 188 | color?: string | number | IArgb; 189 | 190 | /** 191 | * Gets the name. 192 | */ 193 | name?: string; 194 | 195 | /** 196 | * Gets the size. 197 | */ 198 | size?: number; 199 | } 200 | ``` 201 | 202 | ### IPoint2D 203 | 204 | Coordinates, can also be a string like `0,0` or `150|300`. 205 | 206 | ```typescript 207 | interface IPoint2D { 208 | /** 209 | * Gets the X coordinate. 210 | */ 211 | x: number; 212 | 213 | /** 214 | * Gets the Y coordinate. 215 | */ 216 | y: number; 217 | } 218 | ``` 219 | 220 | ### IPoint2D 221 | 222 | Size, can also be a string like `0,0` or `150x300`. 223 | 224 | ```typescript 225 | interface ISize { 226 | /** 227 | * Gets the height. 228 | */ 229 | height: number; 230 | 231 | /** 232 | * Gets the width. 233 | */ 234 | width: number; 235 | } 236 | ``` 237 | 238 | ### OutputFormat 239 | 240 | Supported output formats. 241 | 242 | ```typescript 243 | enum OutputFormat { 244 | /** 245 | * PNG 246 | */ 247 | PNG = 1, 248 | 249 | /** 250 | * JPEG 251 | */ 252 | JPEG = 2, 253 | } 254 | ``` 255 | 256 | ### Bitmap 257 | 258 | ```typescript 259 | interface IBitmap { 260 | /** 261 | * Get the android specific object provided by 'application' module. 262 | */ 263 | android: AndroidApplication; 264 | 265 | /** 266 | * Clones that bitmap. 267 | */ 268 | clone(): IBitmap; 269 | 270 | /** 271 | * Crops that bitmap and returns its copy. 272 | */ 273 | crop(leftTop?: IPoint2D | string, 274 | size?: ISize | string): IBitmap; 275 | 276 | /** 277 | * Gets or sets the default color. 278 | */ 279 | defaultColor: IPoint2D | string | number; 280 | 281 | /** 282 | * Disposes the bitmap. Similar to the IDisposable pattern of .NET Framework. 283 | */ 284 | dispose(action?: (bmp: IBitmap, tag?: T) => TResult, 285 | tag?: T): TResult; 286 | 287 | /** 288 | * Draws a circle. 289 | */ 290 | drawCircle(radius?: number, 291 | center?: IPoint2D | string, 292 | color?: string | number | IArgb, fillColor?: string | number | IArgb): IBitmap; 293 | 294 | /** 295 | * Draws an arc. 296 | */ 297 | drawArc(size?: ISize | string, 298 | leftTop?: IPoint2D | string, 299 | startAngle?: number, 300 | sweepAngle?: number, 301 | color?: string | number | IArgb, fillColor?: string | number | IArgb): IBitmap; 302 | 303 | /** 304 | * Draws a line. 305 | */ 306 | drawLine(start: IPoint2D | string, end: IPoint2D | string, 307 | color?: string | number | IArgb): IBitmap; 308 | 309 | /** 310 | * Draws an oval circle. 311 | */ 312 | drawOval(size?: ISize | string, 313 | leftTop?: IPoint2D | string, 314 | color?: string | number | IArgb, fillColor?: string | number | IArgb): IBitmap; 315 | 316 | /** 317 | * Draws a rectangle. 318 | */ 319 | drawRect(size?: ISize | string, 320 | leftTop?: IPoint2D | string, 321 | color?: string | number | IArgb, fillColor?: string | number | IArgb): IBitmap; 322 | 323 | /** 324 | * Gets the color of a point. 325 | */ 326 | getPoint(coordinates?: IPoint2D | string): IArgb; 327 | 328 | /** 329 | * Gets the height of the bitmap. 330 | */ 331 | height: number; 332 | 333 | /** 334 | * Get the iOS specific object provided by 'application' module. 335 | */ 336 | ios: iOSApplication; 337 | 338 | /** 339 | * Inserts another image into that bitmap. 340 | */ 341 | insert(other: any, 342 | leftTop?: IPoint2D | string): IBitmap; 343 | 344 | /** 345 | * Gets if the object has been disposed or not. 346 | */ 347 | isDisposed: boolean; 348 | 349 | /** 350 | * Gets the native platform specific object that represents that bitmap. 351 | */ 352 | nativeObject: any; 353 | 354 | /** 355 | * Normalizes a color value. 356 | */ 357 | normalizeColor(value: string | number | IArgb): IArgb; 358 | 359 | /** 360 | * Creates a copy of that bitmap with a new size. 361 | */ 362 | resize(newSize: ISize | string): IBitmap; 363 | 364 | /** 365 | * Resizes that image by defining a new height by keeping ratio. 366 | */ 367 | resizeHeight(newHeight: number): IBitmap; 368 | 369 | /** 370 | * Resizes that image by defining a new (maximum) size by keeping ratio. 371 | */ 372 | resizeMax(maxSize: number): IBitmap; 373 | 374 | /** 375 | * Resizes that image by defining a new width by keeping ratio. 376 | */ 377 | resizeWidth(newWidth: number): IBitmap; 378 | 379 | /** 380 | * Rotates the image. 381 | */ 382 | rotate(degrees?: number): IBitmap; 383 | 384 | /** 385 | * Sets a pixel / point. 386 | */ 387 | setPoint(coordinates?: IPoint2D | string, 388 | color?: string | number | IArgb): IBitmap; 389 | 390 | /** 391 | * Gets the size. 392 | */ 393 | size: ISize; 394 | 395 | /** 396 | * Converts that image to a Base64 string. 397 | */ 398 | toBase64(format?: OutputFormat, quality?: number): string; 399 | 400 | /** 401 | * Converts that image to a data URL. 402 | */ 403 | toDataUrl(format?: OutputFormat, quality?: number): string; 404 | 405 | /** 406 | * Returns that image as ImageSource. 407 | */ 408 | toImageSource(): ImageSource; 409 | 410 | /** 411 | * Converts that image to an object. 412 | */ 413 | toObject(format?: OutputFormat, quality?: number): IBitmapData; 414 | 415 | /** 416 | * Writes a text. 417 | */ 418 | writeText(txt: any, 419 | leftTop?: IPoint2D | string, font?: IFont | string): IBitmap; 420 | 421 | /** 422 | * Gets the width of the bitmap. 423 | */ 424 | width: number; 425 | } 426 | ``` 427 | 428 | ## Contributors 429 | 430 | * [Dimitar Topuzov](https://github.com/dtopuzov) 431 | * [Geoff Bullen](https://github.com/geoffbullen) 432 | * [Jonathan Salomon](https://github.com/abhayastudios) 433 | * [Josh Huckabee](https://github.com/jhuckabee) 434 | -------------------------------------------------------------------------------- /plugin/index.d.ts: -------------------------------------------------------------------------------- 1 | import Application = require("tns-core-modules/application"); 2 | import ImageSource = require('tns-core-modules/image-source'); 3 | /** 4 | * Describes an object that stores ARGB color data. 5 | */ 6 | export interface IArgb { 7 | /** 8 | * Gets the alpha value. 9 | */ 10 | a: number; 11 | /** 12 | * Gets the red value. 13 | */ 14 | r: number; 15 | /** 16 | * Gets the green value. 17 | */ 18 | g: number; 19 | /** 20 | * Gets the blue value. 21 | */ 22 | b: number; 23 | } 24 | /** 25 | * Describes bitmap data. 26 | */ 27 | export interface IBitmapData { 28 | /** 29 | * Gets the data as Base64 string. 30 | */ 31 | base64: string; 32 | /** 33 | * Gets the mime type. 34 | */ 35 | mime: string; 36 | } 37 | /** 38 | * Describes an object that stores a font. 39 | */ 40 | export interface IFont { 41 | /** 42 | * Anti alias or not. 43 | */ 44 | antiAlias?: boolean; 45 | /** 46 | * Gets the custom forground color. 47 | */ 48 | color?: string | number | IArgb; 49 | /** 50 | * Gets the name. 51 | */ 52 | name?: string; 53 | /** 54 | * Gets the size. 55 | */ 56 | size?: number; 57 | } 58 | /** 59 | * Options for 'makeMutable()' functon. 60 | */ 61 | export interface IMakeMutableOptions { 62 | /** 63 | * Dispose current bitmap or not. 64 | * 65 | * Default: (false) 66 | */ 67 | disposeCurrent?: boolean; 68 | /** 69 | * Options for handling temp data / files. 70 | */ 71 | temp?: { 72 | /** 73 | * This is only used if stradegy is 'Custom' and 74 | * is used to define the custom temp directory. 75 | * 76 | * This can be a string or a native object that represents a file 77 | * like java.lang.File on Android. 78 | */ 79 | directory?: any; 80 | /** 81 | * The stradegy. 82 | * 83 | * Default: Memory 84 | */ 85 | stradegy?: TempFileStradegy; 86 | }; 87 | } 88 | /** 89 | * A 2D point. 90 | */ 91 | export interface IPoint2D { 92 | /** 93 | * Gets the X coordinate. 94 | */ 95 | x: number; 96 | /** 97 | * Gets the X coordinate. 98 | */ 99 | y: number; 100 | } 101 | /** 102 | * Describes an object that stores a size. 103 | */ 104 | export interface ISize { 105 | /** 106 | * Gets the height. 107 | */ 108 | height: number; 109 | /** 110 | * Gets the width. 111 | */ 112 | width: number; 113 | } 114 | /** 115 | * List of outout formats. 116 | */ 117 | export declare enum OutputFormat { 118 | /** 119 | * PNG 120 | */ 121 | PNG = 1, 122 | /** 123 | * JPEG 124 | */ 125 | JPEG = 2, 126 | } 127 | /** 128 | * List of temp file stradegies. 129 | */ 130 | export declare enum TempFileStradegy { 131 | /** 132 | * Memory 133 | */ 134 | Memory = 1, 135 | /** 136 | * Cache directory 137 | */ 138 | CacheDir = 2, 139 | /** 140 | * External directory 141 | */ 142 | ExternalCacheDir = 3, 143 | /** 144 | * Custom directory 145 | */ 146 | Custom = 4, 147 | } 148 | /** 149 | * Describes a bitmap. 150 | */ 151 | export interface IBitmap { 152 | /** 153 | * Get the android specific object provided by 'application' module. 154 | */ 155 | android: Application.AndroidApplication; 156 | /** 157 | * Clones that bitmap. 158 | * 159 | * @return {IBitmap} Cloned bitmap. 160 | */ 161 | clone(): IBitmap; 162 | /** 163 | * Crops that bitmap and returns its copy. 164 | * 165 | * @param {IPoint2D} [leftTop] The coordinates of the left/top corner. 166 | * @param {ISize} [size] The size. 167 | * 168 | * @return {IBitmap} The cropped bitmap. 169 | * 170 | * @throws At least one input value is invalid. 171 | */ 172 | crop(leftTop?: IPoint2D | string, size?: ISize | string): IBitmap; 173 | /** 174 | * Gets or sets the default color. 175 | */ 176 | defaultColor: IPoint2D | string | number; 177 | /** 178 | * Disposes the bitmap. Similar to the IDisposable pattern of .NET Framework. 179 | * 180 | * @param {Function} [action] The action to invoke BEFORE bitmap is disposed. 181 | * @param {T} [tag] An optional value for the action. 182 | * 183 | * @return {TResult} The result of the action (if defined). 184 | */ 185 | dispose(action?: (bmp: IBitmap, tag?: T) => TResult, tag?: T): TResult; 186 | /** 187 | * Draws a circle. 188 | * 189 | * @chainable 190 | * 191 | * @param {number} [radius] The radius. 192 | * @param any [center] The center coordinates. 193 | * @param any [color] The line color. 194 | * @param any [fillColor] The fill color. 195 | * 196 | * @throws At least one input value is invalid. 197 | */ 198 | drawCircle(radius?: number, center?: IPoint2D | string, color?: string | number | IArgb, fillColor?: string | number | IArgb): IBitmap; 199 | /** 200 | * Draws an arc. 201 | * 202 | * @chainable 203 | * 204 | * @param {ISize} [size] The size. 205 | * @param {IPoint2D} [leftTop] The coordinates of the left/top corner. 206 | * @param {number} [startAngle] The starting angle (in degrees) where the arc begins. 207 | * @param {number} [sweepAngle] The sweep angle (in degrees) measured clockwise. 208 | * @param any [color] The line color. 209 | * @param any [fillColor] The fill color. 210 | * 211 | * @throws At least one input value is invalid. 212 | */ 213 | drawArc(size?: ISize | string, leftTop?: IPoint2D | string, startAngle?: number, sweepAngle?: number, color?: string | number | IArgb, fillColor?: string | number | IArgb): IBitmap; 214 | /** 215 | * Draws a line. 216 | * 217 | * @chainable 218 | * 219 | * @param {IPoint2D} start The coordinates of the start point. 220 | * @param {IPoint2D} end The coordinates of the end point. 221 | * @param {IArgb} [color] The color to use. Default is black. 222 | * 223 | * @throws At least one input value is invalid. 224 | */ 225 | drawLine(start: IPoint2D | string, end: IPoint2D | string, color?: string | number | IArgb): IBitmap; 226 | /** 227 | * Draws an oval circle. 228 | * 229 | * @chainable 230 | * 231 | * @param {ISize} [size] The size. 232 | * @param {IPoint2D} [leftTop] The coordinates of the left/top corner. 233 | * @param {IArgb} [color] The line color. 234 | * @param {IArgb} [fillColor] The fill color. 235 | * 236 | * @throws At least one input value is invalid. 237 | */ 238 | drawOval(size?: ISize | string, leftTop?: IPoint2D | string, color?: string | number | IArgb, fillColor?: string | number | IArgb): IBitmap; 239 | /** 240 | * Draws a rectangle. 241 | * 242 | * @chainable 243 | * 244 | * @param {ISize} [size] The size. 245 | * @param {IPoint2D} [leftTop] The coordinates of the left/top corner. 246 | * @param {IArgb} [color] The line color. 247 | * @param {IArgb} [fillColor] The fill color. 248 | * 249 | * @throws At least one input value is invalid. 250 | */ 251 | drawRect(size?: ISize | string, leftTop?: IPoint2D | string, color?: string | number | IArgb, fillColor?: string | number | IArgb): IBitmap; 252 | /** 253 | * Gets the color of a point. 254 | * 255 | * @param {IPoint2D} [coordinates] The coordinates of the point. 256 | * 257 | * @return {IArgb} The color. 258 | * 259 | * @throws At least one input value is invalid. 260 | */ 261 | getPoint(coordinates?: IPoint2D | string): IArgb; 262 | /** 263 | * Gets the height of the bitmap. 264 | */ 265 | height: number; 266 | /** 267 | * Get the iOS specific object provided by 'application' module. 268 | */ 269 | ios: Application.iOSApplication; 270 | /** 271 | * Inserts another image into that bitmap. 272 | * 273 | * @chainable 274 | * 275 | * @param {IBitmap} other The other image. 276 | * @param {IPoint2D} [leftTop] The coordinates of the left/top corner. 277 | * 278 | * @throws At least one input value is invalid. 279 | */ 280 | insert(other: any, leftTop?: IPoint2D | string): IBitmap; 281 | /** 282 | * Gets if the object has been disposed or not. 283 | */ 284 | isDisposed: boolean; 285 | /** 286 | * Gets the native platform specific object that represents that bitmap. 287 | */ 288 | nativeObject: any; 289 | /** 290 | * Normalizes a color value. 291 | * 292 | * @param any value The input value. 293 | * 294 | * @return {IArgb} The output value. 295 | * 296 | * @throws At least one input value is invalid. 297 | */ 298 | normalizeColor(value: string | number | IArgb): IArgb; 299 | /** 300 | * Creates a copy of that bitmap with a new size. 301 | * 302 | * @param {ISize} newSize The new size. 303 | * 304 | * @return {IBitmap] The new bitmap. 305 | */ 306 | resize(newSize: ISize | string): IBitmap; 307 | /** 308 | * Resizes that image by defining a new height by keeping ratio. 309 | * 310 | * @param {Number} newHeight The new height. 311 | * 312 | * @return {IBitmap} The resized image. 313 | */ 314 | resizeHeight(newHeight: number): IBitmap; 315 | /** 316 | * Resizes that image by defining a new (maximum) size by keeping ratio. 317 | * 318 | * @param {Number} maxSize The maximum width or height. 319 | * 320 | * @return {IBitmap} The resized image. 321 | */ 322 | resizeMax(maxSize: number): IBitmap; 323 | /** 324 | * Resizes that image by defining a new width by keeping ratio. 325 | * 326 | * @param {Number} newWidth The new width. 327 | * 328 | * @return {IBitmap} The resized image. 329 | */ 330 | resizeWidth(newWidth: number): IBitmap; 331 | /** 332 | * Rotates the image. 333 | * 334 | * @param {number} [degrees] The number of degrees to rotate. Default: 90. 335 | * 336 | * @return {IBitmap} The rotated image. 337 | */ 338 | rotate(degrees?: number): IBitmap; 339 | /** 340 | * Sets a pixel / point. 341 | * 342 | * @chainable 343 | * 344 | * @param {IPoint2D} [coordinates] The coordinate where to draw the point. 345 | * @param {IArgb} [color] The color of the point. 346 | * 347 | * @throws At least one input value is invalid. 348 | */ 349 | setPoint(coordinates?: IPoint2D | string, color?: string | number | IArgb): IBitmap; 350 | /** 351 | * Gets the size. 352 | */ 353 | size: ISize; 354 | /** 355 | * Converts that image to a Base64 string. 356 | * 357 | * @param {OutputFormat} format The output format. Default is: PNG 358 | * @param {Number} quality A value between 0 (0%) and 100 (100%) for the output quality. 359 | * 360 | * @return {String} The bitmap a Base64 string. 361 | * 362 | * @throws At least one input value is invalid. 363 | */ 364 | toBase64(format?: OutputFormat, quality?: number): string; 365 | /** 366 | * Converts that image to a data URL. 367 | * 368 | * @param {OutputFormat} format The output format. Default is: PNG 369 | * @param {Number} quality A value between 0 (0%) and 100 (100%) for the output quality. 370 | * 371 | * @return {String} The bitmap as data url. 372 | * 373 | * @throws At least one input value is invalid. 374 | */ 375 | toDataUrl(format?: OutputFormat, quality?: number): string; 376 | /** 377 | * Returns that image as ImageSource. 378 | * 379 | * @return {ImageSource} The bitmap as ImageSource. 380 | */ 381 | toImageSource(): ImageSource.ImageSource; 382 | /** 383 | * Converts that image to an object. 384 | * 385 | * @param {OutputFormat} format The output format. Default is: PNG 386 | * @param {Number} quality A value between 0 (0%) and 100 (100%) for the output quality. 387 | * 388 | * @return {IBitmapData} The bitmap as object. 389 | * 390 | * @throws At least one input value is invalid. 391 | */ 392 | toObject(format?: OutputFormat, quality?: number): IBitmapData; 393 | /** 394 | * Writes a text. 395 | * 396 | * @chainable 397 | * 398 | * @param {any} txt The text /value to write. 399 | * @param {IPoint2D} [leftTop] The left/top corner. 400 | * @param {IFont} [font] The custom font to use. 401 | * 402 | * @throws At least one input value is invalid. 403 | */ 404 | writeText(txt: any, leftTop?: IPoint2D | string, font?: IFont | string): IBitmap; 405 | /** 406 | * Gets the width of the bitmap. 407 | */ 408 | width: number; 409 | } 410 | /** 411 | * Additional options for creating a bitmap. 412 | */ 413 | export interface ICreateBitmapOptions { 414 | /** 415 | * iOS specific options. 416 | */ 417 | ios?: { 418 | /** 419 | * Let iOS auto release the underlying CGImage (true) or let 420 | * the object call CGImageRelease() manually (false). 421 | * 422 | * Default: (true) 423 | */ 424 | autoRelease?: boolean; 425 | }; 426 | } 427 | /** 428 | * Returns a value as bitmap object. 429 | * 430 | * @param any v The input value. 431 | * @param {Boolean} [throwException] Throw exception if 'v' is invalid or return (false). 432 | * 433 | * @throws Input value is invalid. 434 | * 435 | * @return {IBitmap} The output value or (false) if input value is invalid. 436 | */ 437 | export declare function asBitmap(v: any, throwException?: boolean): IBitmap; 438 | /** 439 | * Creates a new bitmap. 440 | * 441 | * @param {Number} width The width of the new image. 442 | * @param {Number} [height] The optional height of the new image. If not defined, the width is taken as value. 443 | * @param {ICreateBitmapOptions} [opts] Additional options for creating the bitmap. 444 | * 445 | * @return {IBitmap} The new bitmap. 446 | */ 447 | export declare function create(width: number, height?: number, opts?: ICreateBitmapOptions): IBitmap; 448 | /** 449 | * Returns the default options for creating a new bitmap. 450 | * 451 | * @return {ICreateBitmapOptions} The options. 452 | */ 453 | export declare function getDefaultOptions(): ICreateBitmapOptions; 454 | /** 455 | * Makes a (native) image / bitmap mutable. 456 | * 457 | * @param {any} v The (native) object. 458 | * @param {IMakeMutableOptions} [opts] The custom options. 459 | * 460 | * @return {any} The mutable object. 461 | * 462 | * @throws Native object is invalid. 463 | */ 464 | export declare function makeMutable(v: any, opts?: IMakeMutableOptions): any; 465 | /** 466 | * Sets the default options for creating a new bitmap. 467 | * 468 | * @param {ICreateBitmapOptions} The new options. 469 | */ 470 | export declare function setDefaultOptions(opts: ICreateBitmapOptions): void; -------------------------------------------------------------------------------- /plugin/index.js: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) Marcel Joachim Kloubert 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to 7 | // deal in the Software without restriction, including without limitation the 8 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9 | // sell copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | // DEALINGS IN THE SOFTWARE. 22 | "use strict"; 23 | var BitmapFactory = require("./BitmapFactory"); 24 | var TypeUtils = require("utils/types"); 25 | /** 26 | * List of outout formats. 27 | */ 28 | (function (OutputFormat) { 29 | /** 30 | * PNG 31 | */ 32 | OutputFormat[OutputFormat["PNG"] = 1] = "PNG"; 33 | /** 34 | * JPEG 35 | */ 36 | OutputFormat[OutputFormat["JPEG"] = 2] = "JPEG"; 37 | })(exports.OutputFormat || (exports.OutputFormat = {})); 38 | var OutputFormat = exports.OutputFormat; 39 | /** 40 | * List of temp file stradegies. 41 | */ 42 | (function (TempFileStradegy) { 43 | /** 44 | * Memory 45 | */ 46 | TempFileStradegy[TempFileStradegy["Memory"] = 1] = "Memory"; 47 | /** 48 | * Cache directory 49 | */ 50 | TempFileStradegy[TempFileStradegy["CacheDir"] = 2] = "CacheDir"; 51 | /** 52 | * External directory 53 | */ 54 | TempFileStradegy[TempFileStradegy["ExternalCacheDir"] = 3] = "ExternalCacheDir"; 55 | /** 56 | * Custom directory 57 | */ 58 | TempFileStradegy[TempFileStradegy["Custom"] = 4] = "Custom"; 59 | })(exports.TempFileStradegy || (exports.TempFileStradegy = {})); 60 | var TempFileStradegy = exports.TempFileStradegy; 61 | /** 62 | * Returns a value as bitmap object. 63 | * 64 | * @param any v The input value. 65 | * @param {Boolean} [throwException] Throw exception if 'v' is invalid or return (false). 66 | * 67 | * @throws Input value is invalid. 68 | * 69 | * @return {IBitmap} The output value or (false) if input value is invalid. 70 | */ 71 | function asBitmap(v, throwException) { 72 | if (throwException === void 0) { throwException = true; } 73 | var result = BitmapFactory.asBitmapObject(v); 74 | if (throwException && (false === result)) { 75 | throw "No valid value for a bitmap!"; 76 | } 77 | return result; 78 | } 79 | exports.asBitmap = asBitmap; 80 | /** 81 | * Creates a new bitmap. 82 | * 83 | * @param {Number} width The width of the new image. 84 | * @param {Number} [height] The optional height of the new image. If not defined, the width is taken as value. 85 | * @param {ICreateBitmapOptions} [opts] Additional options for creating the bitmap. 86 | * 87 | * @return {IBitmap} The new bitmap. 88 | */ 89 | function create(width, height, opts) { 90 | if (TypeUtils.isNullOrUndefined(height)) { 91 | height = width; 92 | } 93 | if (arguments.length < 3) { 94 | opts = getDefaultOptions(); 95 | } 96 | if (TypeUtils.isNullOrUndefined(opts)) { 97 | opts = {}; 98 | } 99 | return BitmapFactory.createBitmap(width, height, opts); 100 | } 101 | exports.create = create; 102 | /** 103 | * Returns the default options for creating a new bitmap. 104 | * 105 | * @return {ICreateBitmapOptions} The options. 106 | */ 107 | function getDefaultOptions() { 108 | var opts = BitmapFactory.getDefaultOpts(); 109 | if (!opts) { 110 | opts = {}; 111 | } 112 | return opts; 113 | } 114 | exports.getDefaultOptions = getDefaultOptions; 115 | /** 116 | * Makes a (native) image / bitmap mutable. 117 | * 118 | * @param {any} v The (native) object. 119 | * @param {IMakeMutableOptions} [opts] The custom options. 120 | * 121 | * @return {any} The mutable object. 122 | * 123 | * @throws Native object is invalid. 124 | */ 125 | function makeMutable(v, opts) { 126 | if (TypeUtils.isNullOrUndefined(v)) { 127 | return v; 128 | } 129 | if (!opts) { 130 | opts = {}; 131 | } 132 | return BitmapFactory.makeBitmapMutable(v, opts); 133 | } 134 | exports.makeMutable = makeMutable; 135 | /** 136 | * Sets the default options for creating a new bitmap. 137 | * 138 | * @param {ICreateBitmapOptions} The new options. 139 | */ 140 | function setDefaultOptions(opts) { 141 | if (!opts) { 142 | opts = {}; 143 | } 144 | BitmapFactory.setDefaultOpts(opts); 145 | } 146 | exports.setDefaultOptions = setDefaultOptions; 147 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /plugin/index.ts: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) Marcel Joachim Kloubert 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to 7 | // deal in the Software without restriction, including without limitation the 8 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9 | // sell copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | // DEALINGS IN THE SOFTWARE. 22 | 23 | import Application = require("application"); 24 | var BitmapFactory = require("./BitmapFactory"); 25 | import ImageSource = require('image-source'); 26 | import TypeUtils = require("utils/types"); 27 | 28 | 29 | /** 30 | * Describes an object that stores ARGB color data. 31 | */ 32 | export interface IArgb { 33 | /** 34 | * Gets the alpha value. 35 | */ 36 | a: number; 37 | 38 | /** 39 | * Gets the red value. 40 | */ 41 | r: number; 42 | 43 | /** 44 | * Gets the green value. 45 | */ 46 | g: number; 47 | 48 | /** 49 | * Gets the blue value. 50 | */ 51 | b: number; 52 | } 53 | 54 | /** 55 | * Describes bitmap data. 56 | */ 57 | export interface IBitmapData { 58 | /** 59 | * Gets the data as Base64 string. 60 | */ 61 | base64: string; 62 | 63 | /** 64 | * Gets the mime type. 65 | */ 66 | mime: string; 67 | } 68 | 69 | /** 70 | * Describes an object that stores a font. 71 | */ 72 | export interface IFont { 73 | /** 74 | * Anti alias or not. 75 | */ 76 | antiAlias?: boolean; 77 | 78 | /** 79 | * Gets the custom forground color. 80 | */ 81 | color?: string | number | IArgb; 82 | 83 | /** 84 | * Gets the name. 85 | */ 86 | name?: string; 87 | 88 | /** 89 | * Gets the size. 90 | */ 91 | size?: number; 92 | } 93 | 94 | /** 95 | * Options for 'makeMutable()' functon. 96 | */ 97 | export interface IMakeMutableOptions { 98 | /** 99 | * Dispose current bitmap or not. 100 | * 101 | * Default: (false) 102 | */ 103 | disposeCurrent?: boolean; 104 | 105 | /** 106 | * Options for handling temp data / files. 107 | */ 108 | temp?: { 109 | /** 110 | * This is only used if stradegy is 'Custom' and 111 | * is used to define the custom temp directory. 112 | * 113 | * This can be a string or a native object that represents a file 114 | * like java.lang.File on Android. 115 | */ 116 | directory?: any; 117 | 118 | /** 119 | * The stradegy. 120 | * 121 | * Default: Memory 122 | */ 123 | stradegy?: TempFileStradegy; 124 | } 125 | } 126 | 127 | /** 128 | * A 2D point. 129 | */ 130 | export interface IPoint2D { 131 | /** 132 | * Gets the X coordinate. 133 | */ 134 | x: number; 135 | 136 | /** 137 | * Gets the X coordinate. 138 | */ 139 | y: number; 140 | } 141 | 142 | /** 143 | * Describes an object that stores a size. 144 | */ 145 | export interface ISize { 146 | /** 147 | * Gets the height. 148 | */ 149 | height: number; 150 | 151 | /** 152 | * Gets the width. 153 | */ 154 | width: number; 155 | } 156 | 157 | /** 158 | * List of outout formats. 159 | */ 160 | export enum OutputFormat { 161 | /** 162 | * PNG 163 | */ 164 | PNG = 1, 165 | 166 | /** 167 | * JPEG 168 | */ 169 | JPEG = 2, 170 | } 171 | 172 | /** 173 | * List of temp file stradegies. 174 | */ 175 | export enum TempFileStradegy { 176 | /** 177 | * Memory 178 | */ 179 | Memory = 1, 180 | 181 | /** 182 | * Cache directory 183 | */ 184 | CacheDir = 2, 185 | 186 | /** 187 | * External directory 188 | */ 189 | ExternalCacheDir = 3, 190 | 191 | /** 192 | * Custom directory 193 | */ 194 | Custom = 4, 195 | } 196 | 197 | /** 198 | * Describes a bitmap. 199 | */ 200 | export interface IBitmap { 201 | /** 202 | * Get the android specific object provided by 'application' module. 203 | */ 204 | android: Application.AndroidApplication; 205 | 206 | /** 207 | * Clones that bitmap. 208 | * 209 | * @return {IBitmap} Cloned bitmap. 210 | */ 211 | clone(): IBitmap; 212 | 213 | /** 214 | * Crops that bitmap and returns its copy. 215 | * 216 | * @param {IPoint2D} [leftTop] The coordinates of the left/top corner. 217 | * @param {ISize} [size] The size. 218 | * 219 | * @return {IBitmap} The cropped bitmap. 220 | * 221 | * @throws At least one input value is invalid. 222 | */ 223 | crop(leftTop?: IPoint2D | string, 224 | size?: ISize | string): IBitmap; 225 | 226 | /** 227 | * Gets or sets the default color. 228 | */ 229 | defaultColor: IPoint2D | string | number; 230 | 231 | /** 232 | * Disposes the bitmap. Similar to the IDisposable pattern of .NET Framework. 233 | * 234 | * @param {Function} [action] The action to invoke BEFORE bitmap is disposed. 235 | * @param {T} [tag] An optional value for the action. 236 | * 237 | * @return {TResult} The result of the action (if defined). 238 | */ 239 | dispose(action?: (bmp: IBitmap, tag?: T) => TResult, 240 | tag?: T): TResult; 241 | 242 | /** 243 | * Draws a circle. 244 | * 245 | * @chainable 246 | * 247 | * @param {number} [radius] The radius. 248 | * @param any [center] The center coordinates. 249 | * @param any [color] The line color. 250 | * @param any [fillColor] The fill color. 251 | * 252 | * @throws At least one input value is invalid. 253 | */ 254 | drawCircle(radius?: number, 255 | center?: IPoint2D | string, 256 | color?: string | number | IArgb, fillColor?: string | number | IArgb): IBitmap; 257 | 258 | /** 259 | * Draws an arc. 260 | * 261 | * @chainable 262 | * 263 | * @param {ISize} [size] The size. 264 | * @param {IPoint2D} [leftTop] The coordinates of the left/top corner. 265 | * @param {number} [startAngle] The starting angle (in degrees) where the arc begins. 266 | * @param {number} [sweepAngle] The sweep angle (in degrees) measured clockwise. 267 | * @param any [color] The line color. 268 | * @param any [fillColor] The fill color. 269 | * 270 | * @throws At least one input value is invalid. 271 | */ 272 | drawArc(size?: ISize | string, 273 | leftTop?: IPoint2D | string, 274 | startAngle?: number, 275 | sweepAngle?: number, 276 | color?: string | number | IArgb, fillColor?: string | number | IArgb): IBitmap; 277 | 278 | /** 279 | * Draws a line. 280 | * 281 | * @chainable 282 | * 283 | * @param {IPoint2D} start The coordinates of the start point. 284 | * @param {IPoint2D} end The coordinates of the end point. 285 | * @param {IArgb} [color] The color to use. Default is black. 286 | * 287 | * @throws At least one input value is invalid. 288 | */ 289 | drawLine(start: IPoint2D | string, end: IPoint2D | string, 290 | color?: string | number | IArgb): IBitmap; 291 | 292 | /** 293 | * Draws an oval circle. 294 | * 295 | * @chainable 296 | * 297 | * @param {ISize} [size] The size. 298 | * @param {IPoint2D} [leftTop] The coordinates of the left/top corner. 299 | * @param {IArgb} [color] The line color. 300 | * @param {IArgb} [fillColor] The fill color. 301 | * 302 | * @throws At least one input value is invalid. 303 | */ 304 | drawOval(size?: ISize | string, 305 | leftTop?: IPoint2D | string, 306 | color?: string | number | IArgb, fillColor?: string | number | IArgb): IBitmap; 307 | 308 | /** 309 | * Draws a rectangle. 310 | * 311 | * @chainable 312 | * 313 | * @param {ISize} [size] The size. 314 | * @param {IPoint2D} [leftTop] The coordinates of the left/top corner. 315 | * @param {IArgb} [color] The line color. 316 | * @param {IArgb} [fillColor] The fill color. 317 | * 318 | * @throws At least one input value is invalid. 319 | */ 320 | drawRect(size?: ISize | string, 321 | leftTop?: IPoint2D | string, 322 | color?: string | number | IArgb, fillColor?: string | number | IArgb): IBitmap; 323 | 324 | /** 325 | * Gets the color of a point. 326 | * 327 | * @param {IPoint2D} [coordinates] The coordinates of the point. 328 | * 329 | * @return {IArgb} The color. 330 | * 331 | * @throws At least one input value is invalid. 332 | */ 333 | getPoint(coordinates?: IPoint2D | string): IArgb; 334 | 335 | /** 336 | * Gets the height of the bitmap. 337 | */ 338 | height: number; 339 | 340 | /** 341 | * Get the iOS specific object provided by 'application' module. 342 | */ 343 | ios: Application.iOSApplication; 344 | 345 | /** 346 | * Inserts another image into that bitmap. 347 | * 348 | * @chainable 349 | * 350 | * @param {IBitmap} other The other image. 351 | * @param {IPoint2D} [leftTop] The coordinates of the left/top corner. 352 | * 353 | * @throws At least one input value is invalid. 354 | */ 355 | insert(other: any, 356 | leftTop?: IPoint2D | string): IBitmap; 357 | 358 | /** 359 | * Gets if the object has been disposed or not. 360 | */ 361 | isDisposed: boolean; 362 | 363 | /** 364 | * Gets the native platform specific object that represents that bitmap. 365 | */ 366 | nativeObject: any; 367 | 368 | /** 369 | * Normalizes a color value. 370 | * 371 | * @param any value The input value. 372 | * 373 | * @return {IArgb} The output value. 374 | * 375 | * @throws At least one input value is invalid. 376 | */ 377 | normalizeColor(value: string | number | IArgb): IArgb; 378 | 379 | /** 380 | * Creates a copy of that bitmap with a new size. 381 | * 382 | * @param {ISize} newSize The new size. 383 | * 384 | * @return {IBitmap] The new bitmap. 385 | */ 386 | resize(newSize: ISize | string): IBitmap; 387 | 388 | /** 389 | * Resizes that image by defining a new height by keeping ratio. 390 | * 391 | * @param {Number} newHeight The new height. 392 | * 393 | * @return {IBitmap} The resized image. 394 | */ 395 | resizeHeight(newHeight: number): IBitmap; 396 | 397 | /** 398 | * Resizes that image by defining a new (maximum) size by keeping ratio. 399 | * 400 | * @param {Number} maxSize The maximum width or height. 401 | * 402 | * @return {IBitmap} The resized image. 403 | */ 404 | resizeMax(maxSize: number): IBitmap; 405 | 406 | /** 407 | * Resizes that image by defining a new width by keeping ratio. 408 | * 409 | * @param {Number} newWidth The new width. 410 | * 411 | * @return {IBitmap} The resized image. 412 | */ 413 | resizeWidth(newWidth: number): IBitmap; 414 | 415 | /** 416 | * Rotates the image. 417 | * 418 | * @param {number} [degrees] The number of degrees to rotate. Default: 90. 419 | * 420 | * @return {IBitmap} The rotated image. 421 | */ 422 | rotate(degrees?: number): IBitmap; 423 | 424 | /** 425 | * Sets a pixel / point. 426 | * 427 | * @chainable 428 | * 429 | * @param {IPoint2D} [coordinates] The coordinate where to draw the point. 430 | * @param {IArgb} [color] The color of the point. 431 | * 432 | * @throws At least one input value is invalid. 433 | */ 434 | setPoint(coordinates?: IPoint2D | string, 435 | color?: string | number | IArgb): IBitmap; 436 | 437 | /** 438 | * Gets the size. 439 | */ 440 | size: ISize; 441 | 442 | /** 443 | * Converts that image to a Base64 string. 444 | * 445 | * @param {OutputFormat} format The output format. Default is: PNG 446 | * @param {Number} quality A value between 0 (0%) and 100 (100%) for the output quality. 447 | * 448 | * @return {String} The bitmap a Base64 string. 449 | * 450 | * @throws At least one input value is invalid. 451 | */ 452 | toBase64(format?: OutputFormat, quality?: number): string; 453 | 454 | /** 455 | * Converts that image to a data URL. 456 | * 457 | * @param {OutputFormat} format The output format. Default is: PNG 458 | * @param {Number} quality A value between 0 (0%) and 100 (100%) for the output quality. 459 | * 460 | * @return {String} The bitmap as data url. 461 | * 462 | * @throws At least one input value is invalid. 463 | */ 464 | toDataUrl(format?: OutputFormat, quality?: number): string; 465 | 466 | /** 467 | * Returns that image as ImageSource. 468 | * 469 | * @return {ImageSource} The bitmap as ImageSource. 470 | */ 471 | toImageSource(): ImageSource.ImageSource; 472 | 473 | /** 474 | * Converts that image to an object. 475 | * 476 | * @param {OutputFormat} format The output format. Default is: PNG 477 | * @param {Number} quality A value between 0 (0%) and 100 (100%) for the output quality. 478 | * 479 | * @return {IBitmapData} The bitmap as object. 480 | * 481 | * @throws At least one input value is invalid. 482 | */ 483 | toObject(format?: OutputFormat, quality?: number): IBitmapData; 484 | 485 | /** 486 | * Writes a text. 487 | * 488 | * @chainable 489 | * 490 | * @param {any} txt The text /value to write. 491 | * @param {IPoint2D} [leftTop] The left/top corner. 492 | * @param {IFont} [font] The custom font to use. 493 | * 494 | * @throws At least one input value is invalid. 495 | */ 496 | writeText(txt: any, 497 | leftTop?: IPoint2D | string, font?: IFont | string): IBitmap; 498 | 499 | /** 500 | * Gets the width of the bitmap. 501 | */ 502 | width: number; 503 | } 504 | 505 | /** 506 | * Additional options for creating a bitmap. 507 | */ 508 | export interface ICreateBitmapOptions { 509 | /** 510 | * iOS specific options. 511 | */ 512 | ios?: { 513 | /** 514 | * Let iOS auto release the underlying CGImage (true) or let 515 | * the object call CGImageRelease() manually (false). 516 | * 517 | * Default: (true) 518 | */ 519 | autoRelease?: boolean; 520 | }, 521 | } 522 | 523 | /** 524 | * Returns a value as bitmap object. 525 | * 526 | * @param any v The input value. 527 | * @param {Boolean} [throwException] Throw exception if 'v' is invalid or return (false). 528 | * 529 | * @throws Input value is invalid. 530 | * 531 | * @return {IBitmap} The output value or (false) if input value is invalid. 532 | */ 533 | export function asBitmap(v: any, throwException: boolean = true): IBitmap { 534 | var result = BitmapFactory.asBitmapObject(v); 535 | if (throwException && (false === result)) { 536 | throw "No valid value for a bitmap!"; 537 | } 538 | 539 | return result; 540 | } 541 | 542 | /** 543 | * Creates a new bitmap. 544 | * 545 | * @param {Number} width The width of the new image. 546 | * @param {Number} [height] The optional height of the new image. If not defined, the width is taken as value. 547 | * @param {ICreateBitmapOptions} [opts] Additional options for creating the bitmap. 548 | * 549 | * @return {IBitmap} The new bitmap. 550 | */ 551 | export function create(width: number, height?: number, opts?: ICreateBitmapOptions): IBitmap { 552 | if (TypeUtils.isNullOrUndefined(height)) { 553 | height = width; 554 | } 555 | 556 | if (arguments.length < 3) { 557 | opts = getDefaultOptions(); 558 | } 559 | 560 | if (TypeUtils.isNullOrUndefined(opts)) { 561 | opts = {}; 562 | } 563 | 564 | return BitmapFactory.createBitmap(width, height, opts); 565 | } 566 | 567 | /** 568 | * Returns the default options for creating a new bitmap. 569 | * 570 | * @return {ICreateBitmapOptions} The options. 571 | */ 572 | export function getDefaultOptions(): ICreateBitmapOptions { 573 | let opts = BitmapFactory.getDefaultOpts(); 574 | if (!opts) { 575 | opts = {}; 576 | } 577 | 578 | return opts; 579 | } 580 | 581 | /** 582 | * Makes a (native) image / bitmap mutable. 583 | * 584 | * @param {any} v The (native) object. 585 | * @param {IMakeMutableOptions} [opts] The custom options. 586 | * 587 | * @return {any} The mutable object. 588 | * 589 | * @throws Native object is invalid. 590 | */ 591 | export function makeMutable(v: any, opts?: IMakeMutableOptions): any { 592 | if (TypeUtils.isNullOrUndefined(v)) { 593 | return v; 594 | } 595 | 596 | if (!opts) { 597 | opts = {}; 598 | } 599 | 600 | return BitmapFactory.makeBitmapMutable(v, opts); 601 | } 602 | 603 | /** 604 | * Sets the default options for creating a new bitmap. 605 | * 606 | * @param {ICreateBitmapOptions} The new options. 607 | */ 608 | export function setDefaultOptions(opts: ICreateBitmapOptions) { 609 | if (!opts) { 610 | opts = {}; 611 | } 612 | 613 | BitmapFactory.setDefaultOpts(opts); 614 | } 615 | -------------------------------------------------------------------------------- /plugin/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nativescript-bitmap-factory", 3 | "version": "1.8.1", 4 | "lockfileVersion": 1 5 | } 6 | -------------------------------------------------------------------------------- /plugin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nativescript-bitmap-factory", 3 | "description": "A NativeScript module for creating and manipulating bitmap images.", 4 | "version": "1.8.1", 5 | "nativescript": { 6 | "platforms": { 7 | "ios": "1.0.0", 8 | "android": "1.1.0" 9 | } 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/mkloubert/nativescript-bitmap-factory" 14 | }, 15 | "keywords": [ 16 | "NativeScript", 17 | "Bitmaps", 18 | "Factory", 19 | "Factories", 20 | "Images", 21 | "Circles", 22 | "Lines", 23 | "Args", 24 | "Rectangles", 25 | "Ovals", 26 | "Points", 27 | "Text", 28 | "Strings", 29 | "PNG", 30 | "JPEG", 31 | "JPG" 32 | ], 33 | "author": { 34 | "name": "Marcel Joachim Kloubert", 35 | "email": "marcel.kloubert@gmx.net" 36 | }, 37 | "license": { 38 | "type": "MIT", 39 | "url": "https://github.com/mkloubert/nativescript-bitmap-factory/blob/master/LICENSE" 40 | }, 41 | "bugs": { 42 | "url": "https://github.com/mkloubert/nativescript-bitmap-factory/issues" 43 | }, 44 | "homepage": "https://github.com/mkloubert/nativescript-bitmap-factory", 45 | "readmeFilename": "README.md" 46 | } 47 | -------------------------------------------------------------------------------- /plugin/references.d.ts: -------------------------------------------------------------------------------- 1 | /// Enable smart suggestions and completions in Visual Studio Code JavaScript projects. 2 | -------------------------------------------------------------------------------- /plugin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es5", 5 | "sourceMap": true, 6 | "experimentalDecorators": true, 7 | "emitDecoratorMetadata": true, 8 | "noEmitHelpers": true, 9 | "noEmitOnError": true 10 | } 11 | } --------------------------------------------------------------------------------