mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
Merge branch 'master'
This commit is contained in:
65
nativescript-core/image-asset/image-asset-common.ts
Normal file
65
nativescript-core/image-asset/image-asset-common.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { ImageAsset as ImageAssetDefinition, ImageAssetOptions } from ".";
|
||||
import { Observable } from "../data/observable";
|
||||
import { screen as platformScreen } from "../platform";
|
||||
|
||||
export class ImageAssetBase extends Observable implements ImageAssetDefinition {
|
||||
private _options: ImageAssetOptions;
|
||||
private _nativeImage: any;
|
||||
|
||||
ios: PHAsset;
|
||||
android: string;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._options = { keepAspectRatio: true, autoScaleFactor: true };
|
||||
}
|
||||
|
||||
get options(): ImageAssetOptions {
|
||||
return this._options;
|
||||
}
|
||||
|
||||
set options(value: ImageAssetOptions) {
|
||||
this._options = value;
|
||||
}
|
||||
|
||||
get nativeImage(): any {
|
||||
return this._nativeImage;
|
||||
}
|
||||
|
||||
set nativeImage(value: any) {
|
||||
this._nativeImage = value;
|
||||
}
|
||||
|
||||
public getImageAsync(callback: (image: any, error: Error) => void) {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
export function getAspectSafeDimensions(sourceWidth, sourceHeight, reqWidth, reqHeight) {
|
||||
let widthCoef = sourceWidth / reqWidth;
|
||||
let heightCoef = sourceHeight / reqHeight;
|
||||
let aspectCoef = Math.min(widthCoef, heightCoef);
|
||||
|
||||
return {
|
||||
width: Math.floor(sourceWidth / aspectCoef),
|
||||
height: Math.floor(sourceHeight / aspectCoef)
|
||||
};
|
||||
}
|
||||
|
||||
export function getRequestedImageSize(src: { width: number, height: number }, options: ImageAssetOptions): { width: number, height: number } {
|
||||
const screen = platformScreen.mainScreen;
|
||||
|
||||
let reqWidth = options.width || Math.min(src.width, screen.widthPixels);
|
||||
let reqHeight = options.height || Math.min(src.height, screen.heightPixels);
|
||||
|
||||
if (options && options.keepAspectRatio) {
|
||||
let safeAspectSize = getAspectSafeDimensions(src.width, src.height, reqWidth, reqHeight);
|
||||
reqWidth = safeAspectSize.width;
|
||||
reqHeight = safeAspectSize.height;
|
||||
}
|
||||
|
||||
return {
|
||||
width: reqWidth,
|
||||
height: reqHeight
|
||||
};
|
||||
}
|
||||
90
nativescript-core/image-asset/image-asset.android.ts
Normal file
90
nativescript-core/image-asset/image-asset.android.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
import { ImageAssetBase, getRequestedImageSize } from "./image-asset-common";
|
||||
import { path as fsPath, knownFolders } from "../file-system";
|
||||
|
||||
export * from "./image-asset-common";
|
||||
|
||||
export class ImageAsset extends ImageAssetBase {
|
||||
private _android: string; //file name of the image
|
||||
|
||||
constructor(asset: string) {
|
||||
super();
|
||||
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 {
|
||||
return this._android;
|
||||
}
|
||||
|
||||
set android(value: string) {
|
||||
this._android = value;
|
||||
}
|
||||
|
||||
public getImageAsync(callback: (image, error) => void) {
|
||||
let bitmapOptions = new android.graphics.BitmapFactory.Options();
|
||||
bitmapOptions.inJustDecodeBounds = true;
|
||||
// read only the file size
|
||||
let bitmap = android.graphics.BitmapFactory.decodeFile(this.android, bitmapOptions);
|
||||
let sourceSize = {
|
||||
width: bitmapOptions.outWidth,
|
||||
height: bitmapOptions.outHeight
|
||||
};
|
||||
let requestedSize = getRequestedImageSize(sourceSize, this.options);
|
||||
|
||||
let sampleSize = org.nativescript.widgets.image.Fetcher.calculateInSampleSize(bitmapOptions.outWidth, bitmapOptions.outHeight, requestedSize.width, requestedSize.height);
|
||||
|
||||
let finalBitmapOptions = new android.graphics.BitmapFactory.Options();
|
||||
finalBitmapOptions.inSampleSize = sampleSize;
|
||||
try {
|
||||
let error = null;
|
||||
// read as minimum bitmap as possible (slightly bigger than the requested size)
|
||||
bitmap = android.graphics.BitmapFactory.decodeFile(this.android, finalBitmapOptions);
|
||||
|
||||
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) {
|
||||
callback(null, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function calculateAngleFromFile(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;
|
||||
}
|
||||
21
nativescript-core/image-asset/image-asset.d.ts
vendored
Normal file
21
nativescript-core/image-asset/image-asset.d.ts
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @module "image-asset"
|
||||
*/ /** */
|
||||
|
||||
import { Observable } from "../data/observable";
|
||||
|
||||
export class ImageAsset extends Observable {
|
||||
constructor(asset: any);
|
||||
getImageAsync(callback: (image: any, error: any) => void); //UIImage for iOS and android.graphics.Bitmap for Android
|
||||
ios: any; //PHAsset
|
||||
nativeImage: any; //UIImage for iOS and android.graphics.Bitmap for Android
|
||||
android: any;
|
||||
options: ImageAssetOptions;
|
||||
}
|
||||
|
||||
export interface ImageAssetOptions {
|
||||
width?: number;
|
||||
height?: number;
|
||||
keepAspectRatio?: boolean;
|
||||
autoScaleFactor?: boolean;
|
||||
}
|
||||
79
nativescript-core/image-asset/image-asset.ios.ts
Normal file
79
nativescript-core/image-asset/image-asset.ios.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { ImageAssetBase, getRequestedImageSize } from "./image-asset-common";
|
||||
import { path as fsPath, knownFolders } from "../file-system";
|
||||
|
||||
export * from "./image-asset-common";
|
||||
|
||||
export class ImageAsset extends ImageAssetBase {
|
||||
private _ios: PHAsset;
|
||||
|
||||
constructor(asset: string | PHAsset | UIImage) {
|
||||
super();
|
||||
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;
|
||||
}
|
||||
else {
|
||||
this.ios = asset;
|
||||
}
|
||||
}
|
||||
|
||||
get ios(): PHAsset {
|
||||
return this._ios;
|
||||
}
|
||||
|
||||
set ios(value: PHAsset) {
|
||||
this._ios = value;
|
||||
}
|
||||
|
||||
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 srcHeight = this.nativeImage ? this.nativeImage.size.height : this.ios.pixelHeight;
|
||||
let requestedSize = getRequestedImageSize({ width: srcWidth, height: srcHeight }, this.options);
|
||||
|
||||
if (this.nativeImage) {
|
||||
let newSize = CGSizeMake(requestedSize.width, requestedSize.height);
|
||||
let resizedImage = this.scaleImage(this.nativeImage, newSize);
|
||||
callback(resizedImage, null);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let imageRequestOptions = PHImageRequestOptions.alloc().init();
|
||||
imageRequestOptions.deliveryMode = PHImageRequestOptionsDeliveryMode.HighQualityFormat;
|
||||
imageRequestOptions.networkAccessAllowed = true;
|
||||
|
||||
PHImageManager.defaultManager().requestImageForAssetTargetSizeContentModeOptionsResultHandler(this.ios, requestedSize, PHImageContentMode.AspectFit, imageRequestOptions,
|
||||
(image, imageResultInfo) => {
|
||||
if (image) {
|
||||
let resultImage = this.scaleImage(image, requestedSize);
|
||||
callback(resultImage, null);
|
||||
}
|
||||
else {
|
||||
callback(null, imageResultInfo.valueForKey(PHImageErrorKey));
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private scaleImage(image: UIImage, requestedSize: { width: number, height: number }): UIImage {
|
||||
// scaleFactor = 0 takes the scale factor of the devices's main screen.
|
||||
const scaleFactor = this.options && this.options.autoScaleFactor === false ? 1.0 : 0.0;
|
||||
|
||||
UIGraphicsBeginImageContextWithOptions(requestedSize, false, scaleFactor);
|
||||
image.drawInRect(CGRectMake(0, 0, requestedSize.width, requestedSize.height));
|
||||
let resultImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
return resultImage;
|
||||
}
|
||||
}
|
||||
6
nativescript-core/image-asset/package.json
Normal file
6
nativescript-core/image-asset/package.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "image-asset",
|
||||
"main": "image-asset",
|
||||
"types": "image-asset.d.ts",
|
||||
"nativescript": {}
|
||||
}
|
||||
Reference in New Issue
Block a user