Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/core/image-asset/image-asset-common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export function getRequestedImageSize(src: { width: number; height: number }, op
}

return {
width: reqWidth,
height: reqHeight,
width: Number(reqWidth),
height: Number(reqHeight),
};
}
55 changes: 53 additions & 2 deletions packages/core/image-asset/index.android.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,58 @@ export class ImageAsset extends ImageAssetBase {
this._android = value;
}

public getImageAsync(callback: (image, error) => void) {
/**
* Validates and adjusts image dimensions to prevent bitmap size exceeding Android's 32-bit limit.
* Android has a limitation where bitmap size (width * height) cannot exceed 2^31-1.
* This method ensures the dimensions are within safe bounds while maintaining aspect ratio.
*
* @param {number|string} width - The desired width of the image
* @param {number|string} height - The desired height of the image
* @returns {{ width: number; height: number }} Object containing validated dimensions
*
* @example
* // Returns safe dimensions that won't exceed Android's bitmap size limit
* const safe = validateDimensions("4000", "3000");
*/
private _validateDimensions(width: number | string, height: number | string): { width: number; height: number } {
const parseSize = (size: number | string): number => {
return typeof size === 'string' ? parseInt(size, 10) : size;
};

let w = parseSize(width);
let h = parseSize(height);

// Check for 32-bit limitation (2^31 - 1, leaving some headroom)
const MAX_DIMENSION = Math.floor(Math.sqrt(Math.pow(2, 31) - 1));

// Check if each dimension exceeds MAX_DIMENSION
w = Math.min(w, MAX_DIMENSION);
h = Math.min(h, MAX_DIMENSION);

// Check the total pixel count
if (w * h > Math.pow(2, 31) - 1) {
const scale = Math.sqrt((Math.pow(2, 31) - 1) / (w * h));
w = Math.floor(w * scale);
h = Math.floor(h * scale);
}

return { width: w, height: h };
}

/**
* Asynchronously loads an image with the specified dimensions.
* Handles string/number dimension types and applies size validation for Android bitmap limitations.
*
* @param {Function} callback - Callback function that receives (image, error)
* @param {{ width?: number; height?: number }} [options] - Optional dimensions for the image
*/
public getImageAsync(callback: (image, error) => void, options?: { width?: number; height?: number }) {
if (options?.width || options?.height) {
const validDimensions = this._validateDimensions(options.width || this.options.width || 0, options.height || this.options.height || 0);
options.width = validDimensions.width;
options.height = validDimensions.height;
}

org.nativescript.widgets.Utils.loadImageAsync(
ad.getApplicationContext(),
this.android,
Expand All @@ -39,7 +90,7 @@ export class ImageAsset extends ImageAssetBase {
onError(ex) {
callback(null, ex);
},
})
}),
);
}
}
4 changes: 2 additions & 2 deletions packages/core/image-asset/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ export class ImageAsset extends Observable {
}

export interface ImageAssetOptions {
width?: number;
height?: number;
width?: number | string;
height?: number | string;
keepAspectRatio?: boolean;
autoScaleFactor?: boolean;
}
26 changes: 25 additions & 1 deletion packages/core/image-asset/index.ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,23 @@ export class ImageAsset extends ImageAssetBase {
this._ios = value;
}

public getImageAsync(callback: (image, error) => void) {
/**
* Asynchronously loads an image and optionally resizes it.
* Handles both string and number type dimensions by converting strings to numbers.
*
* @param {Function} callback - Callback function that receives (image, error)
* @param {{ width?: number|string; height?: number|string }} [options] - Optional dimensions for the image
*/
public getImageAsync(callback: (image, error) => void, options?: { width?: number | string; height?: number | string }) {
if (options) {
if (typeof options.width === 'string') {
options.width = parseInt(options.width, 10);
}
if (typeof options.height === 'string') {
options.height = parseInt(options.height, 10);
}
}

if (!this.ios && !this.nativeImage) {
callback(null, 'Asset cannot be found.');
}
Expand Down Expand Up @@ -60,6 +76,14 @@ export class ImageAsset extends ImageAssetBase {
});
}

/**
* Scales the image to the requested size while respecting device scale factor settings.
*
* @param {UIImage} image - The source UIImage to scale
* @param {{ width: number; height: number }} requestedSize - Target dimensions
* @returns {UIImage} Scaled image
* @private
*/
private scaleImage(image: UIImage, requestedSize: { width: number; height: number }): UIImage {
return NativeScriptUtils.scaleImageWidthHeightScaleFactor(image, requestedSize.width, requestedSize.height, this.options?.autoScaleFactor === false ? 1.0 : 0.0);
}
Expand Down