1 | import { Font } from '../ui/styling/font';
|
2 | import { Trace } from '../trace';
|
3 |
|
4 | import { path as fsPath, knownFolders } from '../file-system';
|
5 | import { isFileOrResourcePath, RESOURCE_PREFIX, SYSTEM_PREFIX } from '../utils';
|
6 | import { getScaledDimensions } from './image-source-common';
|
7 | export { isFileOrResourcePath };
|
8 | let http;
|
9 | function ensureHttp() {
|
10 | if (!http) {
|
11 | http = require('../http');
|
12 | }
|
13 | }
|
14 | export 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 |
|
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 ;
|
58 | case 'medium':
|
59 | return 2 ;
|
60 | case 'large':
|
61 | return 3 ;
|
62 | default:
|
63 | return -1 ;
|
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 );
|
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 );
|
186 | const main_queue = dispatch_get_current_queue();
|
187 | const background_queue = dispatch_get_global_queue(21 , 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 |
|
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);
|
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);
|
312 | }
|
313 | const main_queue = dispatch_get_current_queue();
|
314 | const background_queue = dispatch_get_global_queue(21 , 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);
|
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);
|
353 | }
|
354 | const main_queue = dispatch_get_current_queue();
|
355 | const background_queue = dispatch_get_global_queue(21 , 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 , 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 | }
|
403 | function 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 | }
|
410 | function getImageData(instance, format, quality = 0.9) {
|
411 | return NativeScriptUtils.getImageDataFormatQuality(instance, format, quality);
|
412 | }
|
413 | export function fromAsset(asset) {
|
414 | console.log('fromAsset() is deprecated. Use ImageSource.fromAsset() instead.');
|
415 | return ImageSource.fromAsset(asset);
|
416 | }
|
417 | export function fromResource(name) {
|
418 | console.log('fromResource() is deprecated. Use ImageSource.fromResourceSync() instead.');
|
419 | return ImageSource.fromResourceSync(name);
|
420 | }
|
421 | export function fromFile(path) {
|
422 | console.log('fromFile() is deprecated. Use ImageSource.fromFileSync() instead.');
|
423 | return ImageSource.fromFileSync(path);
|
424 | }
|
425 | export function fromData(data) {
|
426 | console.log('fromData() is deprecated. Use ImageSource.fromDataSync() instead.');
|
427 | return ImageSource.fromDataSync(data);
|
428 | }
|
429 | export function fromFontIconCode(source, font, color) {
|
430 | console.log('fromFontIconCode() is deprecated. Use ImageSource.fromFontIconCodeSync() instead.');
|
431 | return ImageSource.fromFontIconCodeSync(source, font, color);
|
432 | }
|
433 | export function fromBase64(source) {
|
434 | console.log('fromBase64() is deprecated. Use ImageSource.fromBase64Sync() instead.');
|
435 | return ImageSource.fromBase64Sync(source);
|
436 | }
|
437 | export function fromNativeSource(nativeSource) {
|
438 | console.log('fromNativeSource() is deprecated. Use ImageSource constructor instead.');
|
439 | return new ImageSource(nativeSource);
|
440 | }
|
441 | export function fromUrl(url) {
|
442 | console.log('fromUrl() is deprecated. Use ImageSource.fromUrl() instead.');
|
443 | return ImageSource.fromUrl(url);
|
444 | }
|
445 | export function fromFileOrResource(path) {
|
446 | console.log('fromFileOrResource() is deprecated. Use ImageSource.fromFileOrResourceSync() instead.');
|
447 | return ImageSource.fromFileOrResourceSync(path);
|
448 | }
|
449 |
|
\ | No newline at end of file |