mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-15 19:26:42 +08:00
Improve ImageAsset scaling (#5110)
* Do not depend on current device screen while calculating Image Asset size. * Scale the image asset to the exact requested size. * Process image assets natively, pass keepAspectRatio based on the stretch property and Asset options. * Fixed the splashscreen resource name as it cannot be read when containing a dot. * Updated the Image Asset scale and rotate logic based on the Native one. * Make the ImageAsset size more important than the Image decode size as its more specific. * Fixed tslint errors. * Added filePath support in the ImageAsset constructor for iOS in order to unify it with the Android implementation, support for relative files and file not found support errors. * Added unit tests for ImageAssets. * Added a sample app for UI testing of image-view with ImageAsset src. * chore: apply PR comments
This commit is contained in:

committed by
Alexander Djenkov

parent
27622d83ba
commit
a94ec9946f
BIN
apps/app/splashscreen.png
Normal file
BIN
apps/app/splashscreen.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
@ -0,0 +1,8 @@
|
|||||||
|
import * as vmModule from "./view-model";
|
||||||
|
|
||||||
|
var viewModel = vmModule.imageViewModel;
|
||||||
|
|
||||||
|
export function pageLoaded(args) {
|
||||||
|
let page = args.object;
|
||||||
|
page.bindingContext = viewModel;
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
<Page loaded="pageLoaded">
|
||||||
|
<GridLayout rows="*, *">
|
||||||
|
<Image row="0" src="{{ cameraImageAsset }}" stretch="aspectFill" margin="10"/>
|
||||||
|
<Image row="1" src="{{ cameraImageSrc }}" stretch="aspectFill" margin="10"></Image>
|
||||||
|
</GridLayout>
|
||||||
|
</Page>
|
44
apps/app/ui-tests-app/image-view/image-asset/view-model.ts
Normal file
44
apps/app/ui-tests-app/image-view/image-asset/view-model.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import * as dialogs from "tns-core-modules/ui/dialogs";
|
||||||
|
import * as observable from "tns-core-modules/data/observable";
|
||||||
|
import * as imageAssetModule from "tns-core-modules/image-asset";
|
||||||
|
import { ImageSource } from 'tns-core-modules/image-source';
|
||||||
|
|
||||||
|
let _cameraImageAsset = null;
|
||||||
|
let _cameraImageSrc = null;
|
||||||
|
|
||||||
|
export class ImageViewModel extends observable.Observable {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
let asset = new imageAssetModule.ImageAsset('~/splashscreen.png');
|
||||||
|
asset.options = {
|
||||||
|
width: 300,
|
||||||
|
height: 300,
|
||||||
|
keepAspectRatio: true
|
||||||
|
};
|
||||||
|
let source = new ImageSource();
|
||||||
|
source.fromAsset(asset).then((source) => {
|
||||||
|
this.set("cameraImageAsset", asset);
|
||||||
|
this.set("cameraImageSrc", source);
|
||||||
|
}, (error) => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get cameraImageAsset(): string {
|
||||||
|
return _cameraImageAsset;
|
||||||
|
}
|
||||||
|
|
||||||
|
set cameraImageAsset(value: string) {
|
||||||
|
_cameraImageAsset = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
get cameraImageSrc(): string {
|
||||||
|
return _cameraImageSrc;
|
||||||
|
}
|
||||||
|
|
||||||
|
set cameraImageSrc(value: string) {
|
||||||
|
_cameraImageSrc = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export var imageViewModel = new ImageViewModel();
|
@ -16,6 +16,7 @@ export function loadExamples() {
|
|||||||
examples.set("mode-matrix", "image-view/mode-matrix");
|
examples.set("mode-matrix", "image-view/mode-matrix");
|
||||||
examples.set("stretch-modes", "image-view/stretch-modes");
|
examples.set("stretch-modes", "image-view/stretch-modes");
|
||||||
examples.set("missing-image", "image-view/missing-image");
|
examples.set("missing-image", "image-view/missing-image");
|
||||||
|
examples.set("image-asset", "image-view/image-asset/image-asset");
|
||||||
|
|
||||||
return examples;
|
return examples;
|
||||||
}
|
}
|
Binary file not shown.
Before Width: | Height: | Size: 26 KiB |
BIN
tests/app/App_Resources/Android/drawable-nodpi/splashscreen.png
Normal file
BIN
tests/app/App_Resources/Android/drawable-nodpi/splashscreen.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
BIN
tests/app/App_Resources/iOS/splashscreen.png
Normal file
BIN
tests/app/App_Resources/iOS/splashscreen.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
@ -1,10 +1,14 @@
|
|||||||
import * as imageSource from "tns-core-modules/image-source";
|
import * as imageSource from "tns-core-modules/image-source";
|
||||||
|
import * as imageAssetModule from "tns-core-modules/image-asset";
|
||||||
import * as fs from "tns-core-modules/file-system";
|
import * as fs from "tns-core-modules/file-system";
|
||||||
import * as app from "tns-core-modules/application";
|
import * as app from "tns-core-modules/application";
|
||||||
import * as TKUnit from "../TKUnit";
|
import * as TKUnit from "../TKUnit";
|
||||||
import * as platform from "tns-core-modules/platform";
|
import * as platform from "tns-core-modules/platform";
|
||||||
|
|
||||||
const imagePath = "~/logo.png";
|
const imagePath = "~/logo.png";
|
||||||
|
const splashscreenPath = "~/splashscreen.png";
|
||||||
|
const splashscreenWidth = 372;
|
||||||
|
const splashscreenHeight = 218;
|
||||||
const smallImagePath = "~/small-image.png";
|
const smallImagePath = "~/small-image.png";
|
||||||
|
|
||||||
export function testFromResource() {
|
export function testFromResource() {
|
||||||
@ -65,6 +69,96 @@ export function testFromFile() {
|
|||||||
TKUnit.assert(!fs.File.exists(path), "test.png not removed");
|
TKUnit.assert(!fs.File.exists(path), "test.png not removed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function testFromAssetFileNotFound(done) {
|
||||||
|
let asset = new imageAssetModule.ImageAsset('invalidFile.png');
|
||||||
|
asset.options = {
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
keepAspectRatio: true
|
||||||
|
};
|
||||||
|
|
||||||
|
let img = imageSource.fromAsset(asset).then((source) => {
|
||||||
|
done('Should not resolve with invalid file name.');
|
||||||
|
}, (error) => {
|
||||||
|
TKUnit.assertNotNull(error);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function testFromAssetSimple(done) {
|
||||||
|
let asset = new imageAssetModule.ImageAsset(splashscreenPath);
|
||||||
|
asset.options = {
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
keepAspectRatio: true
|
||||||
|
};
|
||||||
|
|
||||||
|
let img = imageSource.fromAsset(asset).then((source) => {
|
||||||
|
TKUnit.assertEqual(source.width, splashscreenWidth);
|
||||||
|
TKUnit.assertEqual(source.height, splashscreenHeight);
|
||||||
|
done();
|
||||||
|
}, (error) => {
|
||||||
|
done(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function testFromAssetWithScaling(done) {
|
||||||
|
let asset = new imageAssetModule.ImageAsset(splashscreenPath);
|
||||||
|
let scaleWidth = 10;
|
||||||
|
let scaleHeight = 11;
|
||||||
|
asset.options = {
|
||||||
|
width: scaleWidth,
|
||||||
|
height: scaleHeight,
|
||||||
|
keepAspectRatio: false
|
||||||
|
};
|
||||||
|
|
||||||
|
let img = imageSource.fromAsset(asset).then((source) => {
|
||||||
|
TKUnit.assertEqual(source.width, scaleWidth);
|
||||||
|
TKUnit.assertEqual(source.height, scaleHeight);
|
||||||
|
done();
|
||||||
|
}, (error) => {
|
||||||
|
done(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function testFromAssetWithScalingAndAspectRatio(done) {
|
||||||
|
let asset = new imageAssetModule.ImageAsset(splashscreenPath);
|
||||||
|
let scaleWidth = 10;
|
||||||
|
let scaleHeight = 11;
|
||||||
|
asset.options = {
|
||||||
|
width: scaleWidth,
|
||||||
|
height: scaleHeight,
|
||||||
|
keepAspectRatio: true
|
||||||
|
};
|
||||||
|
|
||||||
|
let img = imageSource.fromAsset(asset).then((source) => {
|
||||||
|
TKUnit.assertEqual(source.width, scaleWidth);
|
||||||
|
TKUnit.assertEqual(source.height, 5);
|
||||||
|
done();
|
||||||
|
}, (error) => {
|
||||||
|
done(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function testFromAssetWithBiggerScaling(done) {
|
||||||
|
let asset = new imageAssetModule.ImageAsset(splashscreenPath);
|
||||||
|
let scaleWidth = 600;
|
||||||
|
let scaleHeight = 600;
|
||||||
|
asset.options = {
|
||||||
|
width: scaleWidth,
|
||||||
|
height: scaleHeight,
|
||||||
|
keepAspectRatio: false
|
||||||
|
};
|
||||||
|
|
||||||
|
let img = imageSource.fromAsset(asset).then((source) => {
|
||||||
|
TKUnit.assertEqual(source.width, scaleWidth);
|
||||||
|
TKUnit.assertEqual(source.height, scaleHeight);
|
||||||
|
done();
|
||||||
|
}, (error) => {
|
||||||
|
done(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function testNativeFields() {
|
export function testNativeFields() {
|
||||||
const img = imageSource.fromFile(imagePath);
|
const img = imageSource.fromFile(imagePath);
|
||||||
if (app.android) {
|
if (app.android) {
|
||||||
|
BIN
tests/app/splashscreen.png
Normal file
BIN
tests/app/splashscreen.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
@ -138,7 +138,8 @@ export const test_SettingImageSrcToDataURI_async = function (done) {
|
|||||||
|
|
||||||
export function test_imageSourceNotResetAfterCreateUI() {
|
export function test_imageSourceNotResetAfterCreateUI() {
|
||||||
let image = new ImageModule.Image();
|
let image = new ImageModule.Image();
|
||||||
let imageSource = ImageSourceModule.fromResource("splashscreen.9");
|
let imageSource = ImageSourceModule.fromResource("splashscreen");
|
||||||
|
TKUnit.assertNotEqual(null, imageSource);
|
||||||
image.imageSource = imageSource;
|
image.imageSource = imageSource;
|
||||||
helper.buildUIAndRunTest(image, () => {
|
helper.buildUIAndRunTest(image, () => {
|
||||||
TKUnit.waitUntilReady(() => image.isLoaded);
|
TKUnit.waitUntilReady(() => image.isLoaded);
|
||||||
|
@ -43,14 +43,10 @@ export function getAspectSafeDimensions(sourceWidth, sourceHeight, reqWidth, req
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getRequestedImageSize(src: { width: number, height: number }, options: definition.ImageAssetOptions): { width: number, height: number } {
|
export function getRequestedImageSize(src: { width: number, height: number }, options: definition.ImageAssetOptions): { width: number, height: number } {
|
||||||
let reqWidth = platform.screen.mainScreen.widthDIPs;
|
var screen = platform.screen.mainScreen;
|
||||||
let reqHeight = platform.screen.mainScreen.heightDIPs;
|
|
||||||
if (options && options.width) {
|
var reqWidth = options.width || Math.min(src.width, screen.widthPixels);
|
||||||
reqWidth = (options.width > 0 && options.width < reqWidth) ? options.width : reqWidth;
|
var reqHeight = options.height || Math.min(src.height, screen.heightPixels);
|
||||||
}
|
|
||||||
if (options && options.height) {
|
|
||||||
reqHeight = (options.height > 0 && options.height < reqHeight) ? options.height : reqHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options && options.keepAspectRatio) {
|
if (options && options.keepAspectRatio) {
|
||||||
let safeAspectSize = getAspectSafeDimensions(src.width, src.height, reqWidth, reqHeight);
|
let safeAspectSize = getAspectSafeDimensions(src.width, src.height, reqWidth, reqHeight);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import * as platform from "../platform";
|
import * as platform from "../platform";
|
||||||
import * as common from "./image-asset-common";
|
import * as common from "./image-asset-common";
|
||||||
|
import { path as fsPath, knownFolders } from "../file-system";
|
||||||
|
|
||||||
global.moduleMerge(common, exports);
|
global.moduleMerge(common, exports);
|
||||||
|
|
||||||
@ -8,7 +9,11 @@ export class ImageAsset extends common.ImageAsset {
|
|||||||
|
|
||||||
constructor(asset: string) {
|
constructor(asset: string) {
|
||||||
super();
|
super();
|
||||||
this.android = asset;
|
let fileName = typeof asset === "string" ? asset.trim() : "";
|
||||||
|
if (fileName.indexOf("~/") === 0) {
|
||||||
|
fileName = fsPath.join(knownFolders.currentApp().path, fileName.replace("~/", ""));
|
||||||
|
}
|
||||||
|
this.android = fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
get android(): string {
|
get android(): string {
|
||||||
@ -22,6 +27,7 @@ export class ImageAsset extends common.ImageAsset {
|
|||||||
public getImageAsync(callback: (image, error) => void) {
|
public getImageAsync(callback: (image, error) => void) {
|
||||||
let bitmapOptions = new android.graphics.BitmapFactory.Options();
|
let bitmapOptions = new android.graphics.BitmapFactory.Options();
|
||||||
bitmapOptions.inJustDecodeBounds = true;
|
bitmapOptions.inJustDecodeBounds = true;
|
||||||
|
// read only the file size
|
||||||
let bitmap = android.graphics.BitmapFactory.decodeFile(this.android, bitmapOptions);
|
let bitmap = android.graphics.BitmapFactory.decodeFile(this.android, bitmapOptions);
|
||||||
let sourceSize = {
|
let sourceSize = {
|
||||||
width: bitmapOptions.outWidth,
|
width: bitmapOptions.outWidth,
|
||||||
@ -29,13 +35,34 @@ export class ImageAsset extends common.ImageAsset {
|
|||||||
};
|
};
|
||||||
let requestedSize = common.getRequestedImageSize(sourceSize, this.options);
|
let requestedSize = common.getRequestedImageSize(sourceSize, this.options);
|
||||||
|
|
||||||
let sampleSize = calculateInSampleSize(bitmapOptions.outWidth, bitmapOptions.outHeight, requestedSize.width, requestedSize.height);
|
let sampleSize = org.nativescript.widgets.image.Fetcher.calculateInSampleSize(bitmapOptions.outWidth, bitmapOptions.outHeight, requestedSize.width, requestedSize.height);
|
||||||
|
|
||||||
let finalBitmapOptions = new android.graphics.BitmapFactory.Options();
|
let finalBitmapOptions = new android.graphics.BitmapFactory.Options();
|
||||||
finalBitmapOptions.inSampleSize = sampleSize;
|
finalBitmapOptions.inSampleSize = sampleSize;
|
||||||
try {
|
try {
|
||||||
|
let error = null;
|
||||||
|
// read as minimum bitmap as possible (slightly bigger than the requested size)
|
||||||
bitmap = android.graphics.BitmapFactory.decodeFile(this.android, finalBitmapOptions);
|
bitmap = android.graphics.BitmapFactory.decodeFile(this.android, finalBitmapOptions);
|
||||||
callback(bitmap, null);
|
|
||||||
|
if (bitmap) {
|
||||||
|
if (requestedSize.width !== bitmap.getWidth() || requestedSize.height !== bitmap.getHeight()) {
|
||||||
|
// scale to exact size
|
||||||
|
bitmap = android.graphics.Bitmap.createScaledBitmap(bitmap, requestedSize.width, requestedSize.height, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const rotationAngle = calculateAngleFromFile(this.android);
|
||||||
|
if (rotationAngle !== 0) {
|
||||||
|
const matrix = new android.graphics.Matrix();
|
||||||
|
matrix.postRotate(rotationAngle);
|
||||||
|
bitmap = android.graphics.Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bitmap) {
|
||||||
|
error = "Asset '" + this.android + "' cannot be found.";
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(bitmap, error);
|
||||||
}
|
}
|
||||||
catch (ex) {
|
catch (ex) {
|
||||||
callback(null, ex);
|
callback(null, ex);
|
||||||
@ -43,6 +70,26 @@ export class ImageAsset extends common.ImageAsset {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var calculateAngleFromFile = function (filename: string) {
|
||||||
|
let rotationAngle = 0;
|
||||||
|
const ei = new android.media.ExifInterface(filename);
|
||||||
|
const orientation = ei.getAttributeInt(android.media.ExifInterface.TAG_ORIENTATION, android.media.ExifInterface.ORIENTATION_NORMAL);
|
||||||
|
|
||||||
|
switch (orientation) {
|
||||||
|
case android.media.ExifInterface.ORIENTATION_ROTATE_90:
|
||||||
|
rotationAngle = 90;
|
||||||
|
break;
|
||||||
|
case android.media.ExifInterface.ORIENTATION_ROTATE_180:
|
||||||
|
rotationAngle = 180;
|
||||||
|
break;
|
||||||
|
case android.media.ExifInterface.ORIENTATION_ROTATE_270:
|
||||||
|
rotationAngle = 270;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rotationAngle;
|
||||||
|
}
|
||||||
|
|
||||||
var calculateInSampleSize = function (imageWidth, imageHeight, reqWidth, reqHeight) {
|
var calculateInSampleSize = function (imageWidth, imageHeight, reqWidth, reqHeight) {
|
||||||
let sampleSize = 1;
|
let sampleSize = 1;
|
||||||
let displayWidth = platform.screen.mainScreen.widthDIPs;
|
let displayWidth = platform.screen.mainScreen.widthDIPs;
|
||||||
@ -56,5 +103,16 @@ var calculateInSampleSize = function (imageWidth, imageHeight, reqWidth, reqHeig
|
|||||||
sampleSize *= 2;
|
sampleSize *= 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var totalPixels = (imageWidth / sampleSize) * (imageHeight / sampleSize);
|
||||||
|
|
||||||
|
// Anything more than 2x the requested pixels we'll sample down further
|
||||||
|
var totalReqPixelsCap = reqWidth * reqHeight * 2;
|
||||||
|
|
||||||
|
while (totalPixels > totalReqPixelsCap) {
|
||||||
|
sampleSize *= 2;
|
||||||
|
totalPixels = (imageWidth / sampleSize) * (imageHeight / sampleSize);
|
||||||
|
}
|
||||||
|
|
||||||
return sampleSize;
|
return sampleSize;
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,21 @@
|
|||||||
import * as common from "./image-asset-common";
|
import * as common from "./image-asset-common";
|
||||||
|
import { path as fsPath, knownFolders } from "../file-system";
|
||||||
|
|
||||||
global.moduleMerge(common, exports);
|
global.moduleMerge(common, exports);
|
||||||
|
|
||||||
export class ImageAsset extends common.ImageAsset {
|
export class ImageAsset extends common.ImageAsset {
|
||||||
private _ios: PHAsset;
|
private _ios: PHAsset;
|
||||||
|
|
||||||
constructor(asset: PHAsset | UIImage) {
|
constructor(asset: string | PHAsset | UIImage) {
|
||||||
super();
|
super();
|
||||||
if (asset instanceof UIImage) {
|
if (typeof asset === "string") {
|
||||||
|
if (asset.indexOf("~/") === 0) {
|
||||||
|
asset = fsPath.join(knownFolders.currentApp().path, asset.replace("~/", ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.nativeImage = UIImage.imageWithContentsOfFile(asset);
|
||||||
|
}
|
||||||
|
else if (asset instanceof UIImage) {
|
||||||
this.nativeImage = asset
|
this.nativeImage = asset
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -24,6 +32,10 @@ export class ImageAsset extends common.ImageAsset {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getImageAsync(callback: (image, error) => void) {
|
public getImageAsync(callback: (image, error) => void) {
|
||||||
|
if (!this.ios && !this.nativeImage) {
|
||||||
|
callback(null, "Asset cannot be found.");
|
||||||
|
}
|
||||||
|
|
||||||
let srcWidth = this.nativeImage ? this.nativeImage.size.width : this.ios.pixelWidth;
|
let srcWidth = this.nativeImage ? this.nativeImage.size.width : this.ios.pixelWidth;
|
||||||
let srcHeight = this.nativeImage ? this.nativeImage.size.height : this.ios.pixelHeight;
|
let srcHeight = this.nativeImage ? this.nativeImage.size.height : this.ios.pixelHeight;
|
||||||
let requestedSize = common.getRequestedImageSize({ width: srcWidth, height: srcHeight }, this.options);
|
let requestedSize = common.getRequestedImageSize({ width: srcWidth, height: srcHeight }, this.options);
|
||||||
|
@ -44,7 +44,6 @@ export class ImageSource implements ImageSourceDefinition {
|
|||||||
return new Promise<ImageSource>((resolve, reject) => {
|
return new Promise<ImageSource>((resolve, reject) => {
|
||||||
asset.getImageAsync((image, err) => {
|
asset.getImageAsync((image, err) => {
|
||||||
if (image) {
|
if (image) {
|
||||||
this.setRotationAngleFromFile(asset.android);
|
|
||||||
this.setNativeSource(image);
|
this.setNativeSource(image);
|
||||||
resolve(this);
|
resolve(this);
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
} from "./image-common";
|
} from "./image-common";
|
||||||
import { knownFolders } from "../../file-system";
|
import { knownFolders } from "../../file-system";
|
||||||
|
|
||||||
|
import * as platform from "../../platform";
|
||||||
export * from "./image-common";
|
export * from "./image-common";
|
||||||
|
|
||||||
const FILE_PREFIX = "file:///";
|
const FILE_PREFIX = "file:///";
|
||||||
@ -82,12 +83,27 @@ export class Image extends ImageBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!value) {
|
if (!value) {
|
||||||
imageView.setUri(null, 0, 0, false, true);
|
imageView.setUri(null, 0, 0, false, false, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const async = this.loadMode === ASYNC;
|
let screen = platform.screen.mainScreen;
|
||||||
|
|
||||||
|
let decodeWidth = Math.min(this.decodeWidth, screen.widthPixels);
|
||||||
|
let decodeHeight = Math.min(this.decodeHeight, screen.heightPixels);
|
||||||
|
let keepAspectRatio = this._calculateKeepAspectRatio();
|
||||||
|
if (value instanceof ImageAsset) {
|
||||||
|
if (value.options) {
|
||||||
|
decodeWidth = value.options.width || decodeWidth;
|
||||||
|
decodeHeight = value.options.height || decodeHeight;
|
||||||
|
keepAspectRatio = !!value.options.keepAspectRatio;
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle assets as file paths natively
|
||||||
|
value = value.android;
|
||||||
|
}
|
||||||
|
|
||||||
|
const async = this.loadMode === ASYNC;
|
||||||
if (typeof value === "string" || value instanceof String) {
|
if (typeof value === "string" || value instanceof String) {
|
||||||
value = value.trim();
|
value = value.trim();
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
@ -97,24 +113,28 @@ export class Image extends ImageBase {
|
|||||||
super._createImageSourceFromSrc(value);
|
super._createImageSourceFromSrc(value);
|
||||||
} else if (isFileOrResourcePath(value)) {
|
} else if (isFileOrResourcePath(value)) {
|
||||||
if (value.indexOf(RESOURCE_PREFIX) === 0) {
|
if (value.indexOf(RESOURCE_PREFIX) === 0) {
|
||||||
imageView.setUri(value, this.decodeWidth, this.decodeHeight, this.useCache, async);
|
imageView.setUri(value, decodeWidth, decodeHeight, keepAspectRatio, this.useCache, async);
|
||||||
} else {
|
} else {
|
||||||
let fileName = value;
|
let fileName = value;
|
||||||
if (fileName.indexOf("~/") === 0) {
|
if (fileName.indexOf("~/") === 0) {
|
||||||
fileName = knownFolders.currentApp().path + "/" + fileName.replace("~/", "");
|
fileName = knownFolders.currentApp().path + "/" + fileName.replace("~/", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
imageView.setUri(FILE_PREFIX + fileName, this.decodeWidth, this.decodeHeight, this.useCache, async);
|
imageView.setUri(FILE_PREFIX + fileName, decodeWidth, decodeHeight, keepAspectRatio, this.useCache, async);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// For backwards compatibility http always use async loading.
|
// For backwards compatibility http always use async loading.
|
||||||
imageView.setUri(value, this.decodeWidth, this.decodeHeight, this.useCache, true);
|
imageView.setUri(value, decodeWidth, decodeHeight, keepAspectRatio, this.useCache, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
super._createImageSourceFromSrc(value);
|
super._createImageSourceFromSrc(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _calculateKeepAspectRatio(): boolean {
|
||||||
|
return this.stretch === "fill" ? false : true;
|
||||||
|
}
|
||||||
|
|
||||||
[stretchProperty.getDefault](): "aspectFit" {
|
[stretchProperty.getDefault](): "aspectFit" {
|
||||||
return "aspectFit";
|
return "aspectFit";
|
||||||
}
|
}
|
||||||
|
@ -347,7 +347,7 @@
|
|||||||
getRotationAngle(): number;
|
getRotationAngle(): number;
|
||||||
setRotationAngle(angle: number): void;
|
setRotationAngle(angle: number): void;
|
||||||
|
|
||||||
setUri(uri: string, decodeWidth: number, decodeHeight: number, useCache: boolean, async: boolean): void;
|
setUri(uri: string, decodeWidth: number, decodeHeight: number, keepAspectRatio: boolean, useCache: boolean, async: boolean): void;
|
||||||
setImageLoadedListener(listener: image.Worker.OnImageLoadedListener): void;
|
setImageLoadedListener(listener: image.Worker.OnImageLoadedListener): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -409,6 +409,8 @@
|
|||||||
export class Fetcher extends Worker {
|
export class Fetcher extends Worker {
|
||||||
private constructor();
|
private constructor();
|
||||||
public static getInstance(context: android.content.Context): Fetcher;
|
public static getInstance(context: android.content.Context): Fetcher;
|
||||||
|
public static calculateInSampleSize(imageWidth: number, imageHeight: number,
|
||||||
|
reqWidth: number, reqHeight: number): number;
|
||||||
public addImageCache(cache: Cache): void;
|
public addImageCache(cache: Cache): void;
|
||||||
public initCache(): void;
|
public initCache(): void;
|
||||||
public clearCache(): void;
|
public clearCache(): void;
|
||||||
|
Reference in New Issue
Block a user