UNPKG

17.4 kBJavaScriptView Raw
1import { Font } from '../ui/styling/font';
2import { Trace } from '../trace';
3// Types.
4import { path as fsPath, knownFolders } from '../file-system';
5import { isFileOrResourcePath, RESOURCE_PREFIX, SYSTEM_PREFIX } from '../utils';
6import { getScaledDimensions } from './image-source-common';
7export { isFileOrResourcePath };
8let http;
9function ensureHttp() {
10 if (!http) {
11 http = require('../http');
12 }
13}
14export class ImageSource {
15 get height() {
16 if (this.ios) {
17 return this.ios.size.height;
18 }
19 return NaN;
20 }
21 get width() {
22 if (this.ios) {
23 return this.ios.size.width;
24 }
25 return NaN;
26 }
27 get rotationAngle() {
28 return NaN;
29 }
30 set rotationAngle(_value) {
31 // compatibility with Android
32 }
33 constructor(nativeSource) {
34 if (nativeSource) {
35 this.setNativeSource(nativeSource);
36 }
37 }
38 static fromAsset(asset) {
39 return new Promise((resolve, reject) => {
40 asset.getImageAsync((image, err) => {
41 if (image) {
42 resolve(new ImageSource(image));
43 }
44 else {
45 reject(err);
46 }
47 });
48 });
49 }
50 static fromUrl(url) {
51 ensureHttp();
52 return http.getImage(url);
53 }
54 static iosSystemScaleFor(scale) {
55 switch (scale) {
56 case 'small':
57 return 1 /* UIImageSymbolScale.Small */;
58 case 'medium':
59 return 2 /* UIImageSymbolScale.Medium */;
60 case 'large':
61 return 3 /* UIImageSymbolScale.Large */;
62 default:
63 return -1 /* UIImageSymbolScale.Default */;
64 }
65 }
66 static fromSystemImageSync(name, scale) {
67 if (scale) {
68 const image = UIImage.systemImageNamedWithConfiguration(name, UIImageSymbolConfiguration.configurationWithScale(ImageSource.iosSystemScaleFor(scale)));
69 return image ? new ImageSource(image) : null;
70 }
71 else {
72 const image = UIImage.systemImageNamed(name);
73 return image ? new ImageSource(image) : null;
74 }
75 }
76 static fromSystemImage(name, scale) {
77 return new Promise((resolve, reject) => {
78 try {
79 let image;
80 if (scale) {
81 image = UIImage.systemImageNamedWithConfiguration(name, UIImageSymbolConfiguration.configurationWithScale(ImageSource.iosSystemScaleFor(scale)));
82 }
83 else {
84 image = UIImage.systemImageNamed(name);
85 }
86 if (image) {
87 resolve(new ImageSource(image));
88 }
89 else {
90 reject(new Error(`Failed to load system icon with name: ${name}`));
91 }
92 }
93 catch (ex) {
94 reject(ex);
95 }
96 });
97 }
98 static fromResourceSync(name) {
99 const nativeSource = UIImage.tns_safeImageNamed(name) || UIImage.tns_safeImageNamed(`${name}.jpg`);
100 return nativeSource ? new ImageSource(nativeSource) : null;
101 }
102 static fromResource(name) {
103 return new Promise((resolve, reject) => {
104 try {
105 UIImage.tns_safeDecodeImageNamedCompletion(name, (image) => {
106 if (image) {
107 resolve(new ImageSource(image));
108 }
109 else {
110 UIImage.tns_safeDecodeImageNamedCompletion(`${name}.jpg`, (img) => {
111 if (img) {
112 resolve(new ImageSource(img));
113 }
114 });
115 }
116 });
117 }
118 catch (ex) {
119 reject(ex);
120 }
121 });
122 }
123 static fromFileSync(path) {
124 const uiImage = UIImage.imageWithContentsOfFile(getFileName(path));
125 return uiImage ? new ImageSource(uiImage) : null;
126 }
127 static fromFile(path) {
128 return new Promise((resolve, reject) => {
129 try {
130 UIImage.tns_decodeImageWidthContentsOfFileCompletion(getFileName(path), (uiImage) => {
131 if (uiImage) {
132 resolve(new ImageSource(uiImage));
133 }
134 });
135 }
136 catch (ex) {
137 reject(ex);
138 }
139 });
140 }
141 static fromFileOrResourceSync(path) {
142 if (!isFileOrResourcePath(path)) {
143 if (Trace.isEnabled()) {
144 Trace.write('Path "' + path + '" is not a valid file or resource.', Trace.categories.Binding, Trace.messageType.error);
145 }
146 return null;
147 }
148 if (path.indexOf(RESOURCE_PREFIX) === 0) {
149 return ImageSource.fromResourceSync(path.slice(RESOURCE_PREFIX.length));
150 }
151 if (path.indexOf(SYSTEM_PREFIX) === 0) {
152 return ImageSource.fromSystemImageSync(path.slice(SYSTEM_PREFIX.length));
153 }
154 return ImageSource.fromFileSync(path);
155 }
156 static fromDataSync(data) {
157 const uiImage = UIImage.imageWithData(data);
158 return uiImage ? new ImageSource(uiImage) : null;
159 }
160 static fromData(data) {
161 return new Promise((resolve, reject) => {
162 try {
163 UIImage.tns_decodeImageWithDataCompletion(data, (uiImage) => {
164 if (uiImage) {
165 resolve(new ImageSource(uiImage));
166 }
167 });
168 }
169 catch (ex) {
170 reject(ex);
171 }
172 });
173 }
174 static fromBase64Sync(source) {
175 let uiImage;
176 if (typeof source === 'string') {
177 const data = NSData.alloc().initWithBase64EncodedStringOptions(source, 1 /* NSDataBase64DecodingOptions.IgnoreUnknownCharacters */);
178 uiImage = UIImage.imageWithData(data);
179 }
180 return uiImage ? new ImageSource(uiImage) : null;
181 }
182 static fromBase64(source) {
183 return new Promise((resolve, reject) => {
184 try {
185 const data = NSData.alloc().initWithBase64EncodedStringOptions(source, 1 /* NSDataBase64DecodingOptions.IgnoreUnknownCharacters */);
186 const main_queue = dispatch_get_current_queue();
187 const background_queue = dispatch_get_global_queue(21 /* qos_class_t.QOS_CLASS_DEFAULT */, 0);
188 dispatch_async(background_queue, () => {
189 const uiImage = UIImage.imageWithData(data);
190 dispatch_async(main_queue, () => {
191 resolve(new ImageSource(uiImage));
192 });
193 });
194 }
195 catch (ex) {
196 reject(ex);
197 }
198 });
199 }
200 static fromFontIconCodeSync(source, font, color) {
201 font = font || Font.default;
202 // TODO: Consider making 36 font size as default for optimal look on TabView and ActionBar
203 const attributes = {
204 [NSFontAttributeName]: font.getUIFont(UIFont.systemFontOfSize(UIFont.labelFontSize)),
205 };
206 if (color) {
207 attributes[NSForegroundColorAttributeName] = color.ios;
208 }
209 const attributedString = NSAttributedString.alloc().initWithStringAttributes(source, attributes);
210 UIGraphicsBeginImageContextWithOptions(attributedString.size(), false, 0.0);
211 attributedString.drawAtPoint(CGPointMake(0, 0));
212 const iconImage = UIGraphicsGetImageFromCurrentImageContext();
213 UIGraphicsEndImageContext();
214 return iconImage ? new ImageSource(iconImage) : null;
215 }
216 fromAsset(asset) {
217 console.log('fromAsset() is deprecated. Use ImageSource.fromAsset() instead.');
218 return ImageSource.fromAsset(asset).then((imgSource) => {
219 this.setNativeSource(imgSource.ios);
220 return this;
221 });
222 }
223 loadFromResource(name) {
224 console.log('loadFromResource() is deprecated. Use ImageSource.fromResourceSync() instead.');
225 const imgSource = ImageSource.fromResourceSync(name);
226 this.ios = imgSource ? imgSource.ios : null;
227 return !!this.ios;
228 }
229 fromResource(name) {
230 console.log('fromResource() is deprecated. Use ImageSource.fromResource() instead.');
231 return ImageSource.fromResource(name).then((imgSource) => {
232 this.ios = imgSource.ios;
233 return !!this.ios;
234 });
235 }
236 loadFromFile(path) {
237 console.log('loadFromFile() is deprecated. Use ImageSource.fromFileSync() instead.');
238 const imgSource = ImageSource.fromFileSync(path);
239 this.ios = imgSource ? imgSource.ios : null;
240 return !!this.ios;
241 }
242 fromFile(path) {
243 console.log('fromFile() is deprecated. Use ImageSource.fromFile() instead.');
244 return ImageSource.fromFile(path).then((imgSource) => {
245 this.ios = imgSource.ios;
246 return !!this.ios;
247 });
248 }
249 loadFromData(data) {
250 console.log('loadFromData() is deprecated. Use ImageSource.fromDataSync() instead.');
251 const imgSource = ImageSource.fromDataSync(data);
252 this.ios = imgSource ? imgSource.ios : null;
253 return !!this.ios;
254 }
255 fromData(data) {
256 console.log('fromData() is deprecated. Use ImageSource.fromData() instead.');
257 return ImageSource.fromData(data).then((imgSource) => {
258 this.ios = imgSource.ios;
259 return !!this.ios;
260 });
261 }
262 loadFromBase64(source) {
263 console.log('loadFromBase64() is deprecated. Use ImageSource.fromBase64Sync() instead.');
264 const imgSource = ImageSource.fromBase64Sync(source);
265 this.ios = imgSource ? imgSource.ios : null;
266 return !!this.ios;
267 }
268 fromBase64(source) {
269 console.log('fromBase64() is deprecated. Use ImageSource.fromBase64() instead.');
270 return ImageSource.fromBase64(source).then((imgSource) => {
271 this.ios = imgSource.ios;
272 return !!this.ios;
273 });
274 }
275 loadFromFontIconCode(source, font, color) {
276 console.log('loadFromFontIconCode() is deprecated. Use ImageSource.fromFontIconCodeSync() instead.');
277 const imgSource = ImageSource.fromFontIconCodeSync(source, font, color);
278 this.ios = imgSource ? imgSource.ios : null;
279 return !!this.ios;
280 }
281 setNativeSource(source) {
282 if (source && !(source instanceof UIImage)) {
283 if (Trace.isEnabled()) {
284 Trace.write('The method setNativeSource() expects UIImage instance.', Trace.categories.Binding, Trace.messageType.error);
285 }
286 return;
287 }
288 this.ios = source;
289 }
290 saveToFile(path, format, quality) {
291 if (!this.ios) {
292 return false;
293 }
294 if (quality) {
295 quality = (quality - 0) / (100 - 0); // Normalize quality on a scale of 0 to 1
296 }
297 const data = getImageData(this.ios, format, quality);
298 if (data) {
299 return NSFileManager.defaultManager.createFileAtPathContentsAttributes(path, data, null);
300 }
301 return false;
302 }
303 saveToFileAsync(path, format, quality) {
304 return new Promise((resolve, reject) => {
305 if (!this.ios) {
306 reject(false);
307 }
308 let isSuccess = false;
309 try {
310 if (quality) {
311 quality = (quality - 0) / (100 - 0); // Normalize quality on a scale of 0 to 1
312 }
313 const main_queue = dispatch_get_current_queue();
314 const background_queue = dispatch_get_global_queue(21 /* qos_class_t.QOS_CLASS_DEFAULT */, 0);
315 dispatch_async(background_queue, () => {
316 const data = getImageData(this.ios, format, quality);
317 if (data) {
318 isSuccess = NSFileManager.defaultManager.createFileAtPathContentsAttributes(path, data, null);
319 }
320 dispatch_async(main_queue, () => {
321 resolve(isSuccess);
322 });
323 });
324 }
325 catch (ex) {
326 reject(ex);
327 }
328 });
329 }
330 toBase64String(format, quality) {
331 let res = null;
332 if (!this.ios) {
333 return res;
334 }
335 if (quality) {
336 quality = (quality - 0) / (100 - 0); // Normalize quality on a scale of 0 to 1
337 }
338 const data = getImageData(this.ios, format, quality);
339 if (data) {
340 res = data.base64Encoding();
341 }
342 return res;
343 }
344 toBase64StringAsync(format, quality) {
345 return new Promise((resolve, reject) => {
346 if (!this.ios) {
347 reject(null);
348 }
349 let result = null;
350 try {
351 if (quality) {
352 quality = (quality - 0) / (100 - 0); // Normalize quality on a scale of 0 to 1
353 }
354 const main_queue = dispatch_get_current_queue();
355 const background_queue = dispatch_get_global_queue(21 /* qos_class_t.QOS_CLASS_DEFAULT */, 0);
356 dispatch_async(background_queue, () => {
357 const data = getImageData(this.ios, format, quality);
358 if (data) {
359 result = data.base64Encoding();
360 }
361 dispatch_async(main_queue, () => {
362 resolve(result);
363 });
364 });
365 }
366 catch (ex) {
367 reject(ex);
368 }
369 });
370 }
371 resize(maxSize, options) {
372 const size = this.ios.size;
373 const dim = getScaledDimensions(size.width, size.height, maxSize);
374 const newSize = CGSizeMake(dim.width, dim.height);
375 UIGraphicsBeginImageContextWithOptions(newSize, options?.opaque ?? false, this.ios.scale);
376 this.ios.drawInRect(CGRectMake(0, 0, newSize.width, newSize.height));
377 const resizedImage = UIGraphicsGetImageFromCurrentImageContext();
378 UIGraphicsEndImageContext();
379 return new ImageSource(resizedImage);
380 }
381 resizeAsync(maxSize, options) {
382 return new Promise((resolve, reject) => {
383 if (!this.ios) {
384 reject(null);
385 }
386 const main_queue = dispatch_get_current_queue();
387 const background_queue = dispatch_get_global_queue(21 /* qos_class_t.QOS_CLASS_DEFAULT */, 0);
388 dispatch_async(background_queue, () => {
389 const size = this.ios.size;
390 const dim = getScaledDimensions(size.width, size.height, maxSize);
391 const newSize = CGSizeMake(dim.width, dim.height);
392 UIGraphicsBeginImageContextWithOptions(newSize, options?.opaque ?? false, this.ios.scale);
393 this.ios.drawInRect(CGRectMake(0, 0, newSize.width, newSize.height));
394 const resizedImage = UIGraphicsGetImageFromCurrentImageContext();
395 UIGraphicsEndImageContext();
396 dispatch_async(main_queue, () => {
397 resolve(new ImageSource(resizedImage));
398 });
399 });
400 });
401 }
402}
403function getFileName(path) {
404 let fileName = typeof path === 'string' ? path.trim() : '';
405 if (fileName.indexOf('~/') === 0) {
406 fileName = fsPath.join(knownFolders.currentApp().path, fileName.replace('~/', ''));
407 }
408 return fileName;
409}
410function getImageData(instance, format, quality = 0.9) {
411 return NativeScriptUtils.getImageDataFormatQuality(instance, format, quality);
412}
413export function fromAsset(asset) {
414 console.log('fromAsset() is deprecated. Use ImageSource.fromAsset() instead.');
415 return ImageSource.fromAsset(asset);
416}
417export function fromResource(name) {
418 console.log('fromResource() is deprecated. Use ImageSource.fromResourceSync() instead.');
419 return ImageSource.fromResourceSync(name);
420}
421export function fromFile(path) {
422 console.log('fromFile() is deprecated. Use ImageSource.fromFileSync() instead.');
423 return ImageSource.fromFileSync(path);
424}
425export function fromData(data) {
426 console.log('fromData() is deprecated. Use ImageSource.fromDataSync() instead.');
427 return ImageSource.fromDataSync(data);
428}
429export function fromFontIconCode(source, font, color) {
430 console.log('fromFontIconCode() is deprecated. Use ImageSource.fromFontIconCodeSync() instead.');
431 return ImageSource.fromFontIconCodeSync(source, font, color);
432}
433export function fromBase64(source) {
434 console.log('fromBase64() is deprecated. Use ImageSource.fromBase64Sync() instead.');
435 return ImageSource.fromBase64Sync(source);
436}
437export function fromNativeSource(nativeSource) {
438 console.log('fromNativeSource() is deprecated. Use ImageSource constructor instead.');
439 return new ImageSource(nativeSource);
440}
441export function fromUrl(url) {
442 console.log('fromUrl() is deprecated. Use ImageSource.fromUrl() instead.');
443 return ImageSource.fromUrl(url);
444}
445export function fromFileOrResource(path) {
446 console.log('fromFileOrResource() is deprecated. Use ImageSource.fromFileOrResourceSync() instead.');
447 return ImageSource.fromFileOrResourceSync(path);
448}
449//# sourceMappingURL=index.ios.js.map
\No newline at end of file