Skip to content

Commit

Permalink
Merge pull request #135 from NativeScript/hristova/make-dimensions-ma…
Browse files Browse the repository at this point in the history
…tch-orientation-when-keepAspectRatio-true

fix: make dimensions match orientation when keepAspectRatio is true
  • Loading branch information
DimitarTodorov authored Nov 8, 2018
2 parents 9493d57 + 2dbbcaf commit 3f711c9
Show file tree
Hide file tree
Showing 9 changed files with 121 additions and 52 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ __Example 2__ shows how to take a picture using the NativeScript camera module.
* __width__: The desired width of the picture (in device independent pixels).
* __height__: The desired height of the picture (in device independent pixels).
* __keepAspectRatio__: A boolean parameter that indicates if the aspect ratio should be kept.
* __saveToGallery__: A boolean parameter that indicates if the taken photo will be saved in "Photos" for Android and in "Camera Roll" in iOS
* __saveToGallery__: A boolean parameter that indicates if the original taken photo will be saved in "Photos" for Android and in "Camera Roll" in iOS
* __cameraFacing__: Start with either the "front" or "rear" (default) camera of the device. The current implementation doesn't work on all Android devices, in which case it falls back to the default behavior.

What does `device independent pixels` mean? The NativeScript layout mechanism uses device-independent pixels when measuring UI controls. This allows you to declare one layout and this layout will look similar to all devices (no matter the device's display resolution). In order to get a proper image quality for high resolution devices (like iPhone retina and Android Full HD), camera will return an image with bigger dimensions. For example, if we request an image that is 100x100, on iPhone 6 the actual image will be 200x200 (since its display density factor is 2 -> 100*2x100*2).
Expand Down
11 changes: 5 additions & 6 deletions demo-angular/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
# Example for using nativescript-camera plugin
## This example demonstrates how to use plugin with nativescript-angular and webpack

Steps to start example.
If you want to test it out on an emulator or a device you can follow the instructions below:

1. npm install
2. Due to a bug with the used version of @angular, a single line from file
node_modules/@angular/compiler/index.js (line 38: export * from './src/template_parser/template_ast';) should be deleted, since its duplicated.
3. tns platform add android - to add platform before starting webpack process
4. npm run start-android
`git clone https://github.com/NativeScript/nativescript-camera.git`
`cd nativescript-camera/demo` or `cd nativescript-camera/demo-angular`
`npm run build.plugin && npm install`
`tns run android` or `tns run ios` depending on the platform you want to test
26 changes: 20 additions & 6 deletions demo-angular/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
<GridLayout rows="auto, *, auto">
<StackLayout orientation="horizontal" row="0" padding="10">
<Label text="saveToGallery"></Label>
<Switch [(ngModel)]="saveToGallery"></Switch>
<GridLayout rows="auto, *, auto, auto">
<StackLayout row="0" orientation="vertical" padding="10">
<StackLayout orientation="horizontal" padding="10">
<Label text="saveToGallery"></Label>
<Switch [(ngModel)]="saveToGallery"></Switch>
</StackLayout>
<StackLayout orientation="horizontal" padding="10">
<Label text="keepAspectRatio"></Label>
<Switch [(ngModel)]="keepAspectRatio"></Switch>
</StackLayout>
<StackLayout orientation="horizontal" padding="10">
<Label text="width"></Label>
<TextField hint="Enter width" keyboardType="number" [(ngModel)]="width" class="input"></TextField>
<Label text="height"></Label>
<TextField hint="Enter height" keyboardType="number" [(ngModel)]="height" class="input"></TextField>
</StackLayout>
</StackLayout>
<Image row="1" [src]="cameraImage" stretch="fill" margin="10"></Image>
<Button text="Take Picture" (tap)='onTakePictureTap($event)' row="2" padding="10"></Button>

<Image row="1" [src]="cameraImage" stretch="aspectFit" margin="10"></Image>
<TextView row="2" [(ngModel)]="labelText" editable="false"></TextView>>
<Button row="3" text="Take Picture" (tap)='onTakePictureTap($event)' padding="10"></Button>
</GridLayout>
33 changes: 20 additions & 13 deletions demo-angular/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,38 @@ import { ImageAsset } from 'tns-core-modules/image-asset';
templateUrl: './app.component.html'
})
export class AppComponent {
public saveToGallery: boolean = true;
public saveToGallery: boolean = false;
public keepAspectRatio: boolean = true;
public width: number = 320;
public height: number = 240;
public cameraImage: ImageAsset;
public actualWidth: number;
public actualHeight: number;
public scale: number = 1;
public labelText: string;

onTakePictureTap(args) {
requestPermissions().then(
() => {
takePicture({ width: 300, height: 300, keepAspectRatio: true, saveToGallery: this.saveToGallery })
takePicture({ width: this.width, height: this.height, keepAspectRatio: this.keepAspectRatio, saveToGallery: this.saveToGallery })
.then((imageAsset: any) => {
this.cameraImage = imageAsset;
let that = this;
imageAsset.getImageAsync(function (nativeImage) {
let scale = 1;
let height = 0;
let width = 0;
if (imageAsset.android) {
// get the current density of the screen (dpi) and divide it by the default one to get the scale
scale = nativeImage.getDensity() / android.util.DisplayMetrics.DENSITY_DEFAULT;
height = imageAsset.options.height;
width = imageAsset.options.width;
that.scale = nativeImage.getDensity() / android.util.DisplayMetrics.DENSITY_DEFAULT;
that.actualWidth = nativeImage.getWidth();
that.actualHeight = nativeImage.getHeight();
} else {
scale = nativeImage.scale;
width = nativeImage.size.width * scale;
height = nativeImage.size.height * scale;
that.scale = nativeImage.scale;
that.actualWidth = nativeImage.size.width * that.scale;
that.actualHeight = nativeImage.size.height * that.scale;
}
console.log(`Displayed Size: ${width}x${height} with scale ${scale}`);
console.log(`Image Size: ${width / scale}x${height / scale}`);
that.labelText = `Displayed Size: ${that.actualWidth}x${that.actualHeight} with scale ${that.scale}\n` +
`Image Size: ${Math.round(that.actualWidth / that.scale)}x${Math.round(that.actualHeight / that.scale)}`;

console.log(`${that.labelText}`);
});
}, (error) => {
console.log("Error: " + error);
Expand Down
8 changes: 8 additions & 0 deletions demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Example for using nativescript-camera plugin

If you want to test it out on an emulator or a device you can follow the instructions below:

`git clone https://github.com/NativeScript/nativescript-camera.git`
`cd nativescript-camera/demo` or `cd nativescript-camera/demo-angular`
`npm run build.plugin && npm install`
`tns run android` or `tns run ios` depending on the platform you want to test
33 changes: 23 additions & 10 deletions demo/app/main-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,46 @@ export function navigatingTo(args: EventData) {
let page = <Page>args.object;
let picturePath = null;

page.bindingContext = fromObject({ cameraImage: picturePath, saveToGallery: true });
page.bindingContext = fromObject({
cameraImage: picturePath,
saveToGallery: false,
keepAspectRatio: true,
width: 320,
height: 240
});
}

export function onTakePictureTap(args: EventData) {
let page = <Page>(<View>args.object).page;
let saveToGallery = page.bindingContext.get("saveToGallery");
let keepAspectRatio = page.bindingContext.get("keepAspectRatio");
let width = page.bindingContext.get("width");
let height = page.bindingContext.get("height");
requestPermissions().then(
() => {
takePicture({ width: 300, height: 300, keepAspectRatio: true, saveToGallery: saveToGallery }).
takePicture({ width: width, height: height, keepAspectRatio: keepAspectRatio, saveToGallery: saveToGallery }).
then((imageAsset) => {
page.bindingContext.set("cameraImage", imageAsset);
imageAsset.getImageAsync(function (nativeImage) {
let scale = 1;
let height = 0;
let width = 0;
let actualWidth = 0;
let actualHeight = 0;
if (imageAsset.android) {
// get the current density of the screen (dpi) and divide it by the default one to get the scale
scale = nativeImage.getDensity() / android.util.DisplayMetrics.DENSITY_DEFAULT;
height = imageAsset.options.height;
width = imageAsset.options.width;
actualWidth = nativeImage.getWidth();
actualHeight = nativeImage.getHeight();
} else {
scale = nativeImage.scale;
width = nativeImage.size.width * scale;
height = nativeImage.size.height * scale;
actualWidth = nativeImage.size.width * scale;
actualHeight = nativeImage.size.height * scale;
}
console.log(`Displayed Size: ${width}x${height} with scale ${scale}`);
console.log(`Image Size: ${width / scale}x${height / scale}`);
let labelText = `Displayed Size: ${actualWidth}x${actualHeight} with scale ${scale}\n` +
`Image Size: ${Math.round(actualWidth / scale)}x${Math.round(actualHeight / scale)}`;
page.bindingContext.set("labelText", labelText);

console.log(`${labelText}`);

});
},
(err) => {
Expand Down
25 changes: 19 additions & 6 deletions demo/app/main-page.xml
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo">
<GridLayout rows="auto, *, auto">
<StackLayout orientation="horizontal" row="0" padding="10">
<Label text="saveToGallery" />
<Switch checked="{{ saveToGallery }}"/>
<GridLayout rows="auto, *, auto, auto">
<StackLayout row="0" orientation="vertical" padding="10">
<StackLayout orientation="horizontal" row="0" padding="10">
<Label text="saveToGallery" />
<Switch checked="{{ saveToGallery }}"/>
</StackLayout>
<StackLayout orientation="horizontal" row="0" padding="10">
<Label text="keepAspectRatio" />
<Switch checked="{{ keepAspectRatio }}"/>
</StackLayout>
<StackLayout orientation="horizontal" padding="10">
<Label text="width"></Label>
<TextField hint="Enter width" keyboardType="number" text="{{ width }}" class="input"></TextField>
<Label text="height"></Label>
<TextField hint="Enter height" keyboardType="number" text="{{ height }}" class="input"></TextField>
</StackLayout>
</StackLayout>
<Image row="1" src="{{ cameraImage }}" id="image" stretch="fill" margin="10"/>
<Button text="Take Picture" tap="onTakePictureTap" row="2" padding="10"/>
<Image row="1" src="{{ cameraImage }}" id="image" stretch="aspectFit" margin="10"/>
<TextView row="2" text="{{ labelText }}" editable="false"></TextView>>
<Button row="3" text="Take Picture" tap="onTakePictureTap" padding="10"/>
</GridLayout>
</Page>
15 changes: 13 additions & 2 deletions src/camera.android.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,7 @@ export let takePicture = function (options?): Promise<any> {
tempPictureUri = (<any>android.support.v4.content).FileProvider.getUriForFile(
applicationModule.android.currentContext,
applicationModule.android.nativeApp.getPackageName() + ".provider", nativeFile);
}
else {
} else {
tempPictureUri = android.net.Uri.fromFile(nativeFile);
}

Expand Down Expand Up @@ -125,6 +124,18 @@ export let takePicture = function (options?): Promise<any> {
rotateBitmap(picturePath, 270);
}

if (shouldKeepAspectRatio) {
let pictureWidth = exif.getAttributeInt(android.media.ExifInterface.TAG_IMAGE_WIDTH, 0);
let pictureHeight = exif.getAttributeInt(android.media.ExifInterface.TAG_IMAGE_LENGTH, 0);
let isPictureLandscape = pictureWidth > pictureHeight;
let areOptionsLandscape = reqWidth > reqHeight;
if (isPictureLandscape !== areOptionsLandscape) {
let oldReqWidth = reqWidth;
reqWidth = reqHeight;
reqHeight = oldReqWidth;
}
}

let asset = new imageAssetModule.ImageAsset(picturePath);
asset.options = {
width: reqWidth,
Expand Down
20 changes: 12 additions & 8 deletions src/camera.ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ class UIImagePickerControllerDelegateImpl extends NSObject implements UIImagePic
let currentDate: Date = new Date();
let source = info.valueForKey(UIImagePickerControllerOriginalImage);
if (source) {
let image = null;
let imageSource: typeof imageSourceModule = require("image-source");
let imageSourceResult = imageSource.fromNativeSource(source);

Expand Down Expand Up @@ -81,10 +80,8 @@ class UIImagePickerControllerDelegateImpl extends NSObject implements UIImagePic
trace.write("An error ocurred while saving image to gallery: " +
err, trace.categories.Error, trace.messageType.error);
}

});
}
else {
} else {
imageAsset = new imageAssetModule.ImageAsset(imageSourceResult.ios);
this.setImageAssetAndCallCallback(imageAsset);
}
Expand All @@ -96,6 +93,15 @@ class UIImagePickerControllerDelegateImpl extends NSObject implements UIImagePic
}

private setImageAssetAndCallCallback(imageAsset: imageAssetModule.ImageAsset) {
if (this._keepAspectRatio) {
let isPictureLandscape = imageAsset.nativeImage.size.width > imageAsset.nativeImage.size.height;
let areOptionsLandscape = this._width > this._height;
if (isPictureLandscape !== areOptionsLandscape) {
let oldWidth = this._width;
this._width = this._height;
this._height = oldWidth;
}
}
imageAsset.options = {
width: this._width,
height: this._height,
Expand Down Expand Up @@ -139,8 +145,7 @@ export let takePicture = function (options): Promise<any> {
} else if (saveToGallery) {
listener = UIImagePickerControllerDelegateImpl.new().initWithCallbackAndOptions(
resolve, reject, { saveToGallery: saveToGallery, keepAspectRatio: keepAspectRatio });
}
else {
} else {
listener = UIImagePickerControllerDelegateImpl.new().initWithCallback(resolve, reject);
}
imagePickerController.delegate = listener;
Expand Down Expand Up @@ -204,8 +209,7 @@ let requestPhotosPermissions = function () {
trace.write("Application can access photo library assets.", trace.categories.Debug);
}
resolve();
}
else {
} else {
reject();
}
});
Expand Down

0 comments on commit 3f711c9

Please sign in to comment.