1
0
mirror of https://github.com/immich-app/immich.git synced 2024-12-22 01:47:08 +02:00

Add support for Apple Pro Raw format (.DNG) (#60)

* Added '.dng' (AppleProRaw) to support file's type
* Added OpenCV python framework for uniform image resizer
* Added version number information
This commit is contained in:
Alex 2022-03-18 20:23:05 -05:00 committed by GitHub
parent 94514cfeea
commit 6e0ac79eae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 146 additions and 48 deletions

View File

@ -13,6 +13,9 @@
## CPU BUILD ## CPU BUILD
FROM python:3.8 as cpu FROM python:3.8 as cpu
RUN apt-get update
RUN apt-get install ffmpeg libsm6 libxext6 -y
WORKDIR /code WORKDIR /code
COPY ./requirements.txt /code/requirements.txt COPY ./requirements.txt /code/requirements.txt

View File

@ -2,15 +2,20 @@ from tensorflow.keras.applications import InceptionV3
from tensorflow.keras.applications.inception_v3 import preprocess_input, decode_predictions from tensorflow.keras.applications.inception_v3 import preprocess_input, decode_predictions
from tensorflow.keras.preprocessing import image from tensorflow.keras.preprocessing import image
import numpy as np import numpy as np
from PIL import Image
import cv2
IMG_SIZE = 299 IMG_SIZE = 299
PREDICTION_MODEL = InceptionV3(weights='imagenet') PREDICTION_MODEL = InceptionV3(weights='imagenet')
def classify_image(image_path: str): def classify_image(image_path: str):
img_path = f'./app/{image_path}' img_path = f'./app/{image_path}'
img = image.load_img(img_path, target_size=(IMG_SIZE, IMG_SIZE)) # img = image.load_img(img_path, target_size=(IMG_SIZE, IMG_SIZE))
x = image.img_to_array(img)
target_image = cv2.imread(img_path, cv2.IMREAD_UNCHANGED)
resized_target_image = cv2.resize(target_image, (IMG_SIZE, IMG_SIZE))
x = image.img_to_array(resized_target_image)
x = np.expand_dims(x, axis=0) x = np.expand_dims(x, axis=0)
x = preprocess_input(x) x = preprocess_input(x)

View File

@ -1,3 +1,4 @@
opencv-python==4.5.5.64
fastapi>=0.68.0,<0.69.0 fastapi>=0.68.0,<0.69.0
pydantic>=1.8.0,<2.0.0 pydantic>=1.8.0,<2.0.0
uvicorn>=0.15.0,<0.16.0 uvicorn>=0.15.0,<0.16.0

View File

@ -1,18 +1,36 @@
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/home/providers/asset.provider.dart'; import 'package:immich_mobile/modules/home/providers/asset.provider.dart';
import 'package:immich_mobile/modules/login/models/authentication_state.model.dart'; import 'package:immich_mobile/modules/login/models/authentication_state.model.dart';
import 'package:immich_mobile/modules/login/providers/authentication.provider.dart'; import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
import 'package:immich_mobile/shared/providers/backup.provider.dart'; import 'package:immich_mobile/shared/providers/backup.provider.dart';
import 'package:immich_mobile/shared/providers/websocket.provider.dart'; import 'package:immich_mobile/shared/providers/websocket.provider.dart';
import 'package:package_info_plus/package_info_plus.dart';
class ProfileDrawer extends ConsumerWidget { class ProfileDrawer extends HookConsumerWidget {
const ProfileDrawer({Key? key}) : super(key: key); const ProfileDrawer({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
AuthenticationState _authState = ref.watch(authenticationProvider); AuthenticationState _authState = ref.watch(authenticationProvider);
final appInfo = useState({});
_getPackageInfo() async {
PackageInfo packageInfo = await PackageInfo.fromPlatform();
appInfo.value = {
"version": packageInfo.version,
"buildNumber": packageInfo.buildNumber,
};
}
useEffect(() {
_getPackageInfo();
return null;
}, []);
return Drawer( return Drawer(
shape: const RoundedRectangleBorder( shape: const RoundedRectangleBorder(
@ -21,50 +39,68 @@ class ProfileDrawer extends ConsumerWidget {
bottomRight: Radius.circular(5), bottomRight: Radius.circular(5),
), ),
), ),
child: ListView( child: Column(
padding: EdgeInsets.zero, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
DrawerHeader( ListView(
decoration: BoxDecoration( shrinkWrap: true,
color: Colors.grey[200], padding: EdgeInsets.zero,
), children: [
child: Column( DrawerHeader(
mainAxisAlignment: MainAxisAlignment.center, decoration: BoxDecoration(
crossAxisAlignment: CrossAxisAlignment.center, color: Colors.grey[200],
children: [
const Image(
image: AssetImage('assets/immich-logo-no-outline.png'),
width: 50,
filterQuality: FilterQuality.high,
), ),
const Padding(padding: EdgeInsets.all(8)), child: Column(
Text( mainAxisAlignment: MainAxisAlignment.center,
_authState.userEmail, crossAxisAlignment: CrossAxisAlignment.center,
style: TextStyle(color: Theme.of(context).primaryColor, fontWeight: FontWeight.bold), children: [
) const Image(
], image: AssetImage('assets/immich-logo-no-outline.png'),
), width: 50,
), filterQuality: FilterQuality.high,
ListTile( ),
tileColor: Colors.grey[100], const Padding(padding: EdgeInsets.all(8)),
leading: const Icon( Text(
Icons.logout_rounded, _authState.userEmail,
color: Colors.black54, style: TextStyle(color: Theme.of(context).primaryColor, fontWeight: FontWeight.bold),
), )
title: const Text( ],
"Sign Out", ),
style: TextStyle(color: Colors.black54, fontSize: 14), ),
), ListTile(
onTap: () async { tileColor: Colors.grey[100],
bool res = await ref.read(authenticationProvider.notifier).logout(); leading: const Icon(
Icons.logout_rounded,
color: Colors.black54,
),
title: const Text(
"Sign Out",
style: TextStyle(color: Colors.black54, fontSize: 14),
),
onTap: () async {
bool res = await ref.read(authenticationProvider.notifier).logout();
if (res) { if (res) {
ref.watch(backupProvider.notifier).cancelBackup(); ref.watch(backupProvider.notifier).cancelBackup();
ref.watch(assetProvider.notifier).clearAllAsset(); ref.watch(assetProvider.notifier).clearAllAsset();
ref.watch(websocketProvider.notifier).disconnect(); ref.watch(websocketProvider.notifier).disconnect();
AutoRouter.of(context).popUntilRoot(); AutoRouter.of(context).popUntilRoot();
} }
}, },
)
],
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Version V${appInfo.value["version"]}+${appInfo.value["buildNumber"]}",
style: TextStyle(
fontSize: 12,
color: Colors.grey[400],
fontWeight: FontWeight.bold,
fontStyle: FontStyle.italic,
),
),
) )
], ],
), ),

View File

@ -32,6 +32,9 @@ class FileHelper {
case 'heif': case 'heif':
return {"type": "image", "subType": "heif"}; return {"type": "image", "subType": "heif"};
case 'dng':
return {"type": "image", "subType": "dng"};
default: default:
return {"type": "unsupport", "subType": "unsupport"}; return {"type": "unsupport", "subType": "unsupport"};
} }

View File

@ -555,6 +555,48 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.2" version: "2.0.2"
package_info_plus:
dependency: "direct main"
description:
name: package_info_plus
url: "https://pub.dartlang.org"
source: hosted
version: "1.4.0"
package_info_plus_linux:
dependency: transitive
description:
name: package_info_plus_linux
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
package_info_plus_macos:
dependency: transitive
description:
name: package_info_plus_macos
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
package_info_plus_platform_interface:
dependency: transitive
description:
name: package_info_plus_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
package_info_plus_web:
dependency: transitive
description:
name: package_info_plus_web
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
package_info_plus_windows:
dependency: transitive
description:
name: package_info_plus_windows
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
path: path:
dependency: transitive dependency: transitive
description: description:

View File

@ -36,6 +36,7 @@ dependencies:
# mapbox_gl: ^0.15.0 # mapbox_gl: ^0.15.0
flutter_map: ^0.14.0 flutter_map: ^0.14.0
flutter_udid: ^2.0.0 flutter_udid: ^2.0.0
package_info_plus: ^1.4.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

View File

@ -12,7 +12,7 @@ export const multerConfig = {
export const multerOption: MulterOptions = { export const multerOption: MulterOptions = {
fileFilter: (req: Request, file: any, cb: any) => { fileFilter: (req: Request, file: any, cb: any) => {
if (file.mimetype.match(/\/(jpg|jpeg|png|gif|mp4|x-msvideo|quicktime|heic|heif)$/)) { if (file.mimetype.match(/\/(jpg|jpeg|png|gif|mp4|x-msvideo|quicktime|heic|heif|dng)$/)) {
cb(null, true); cb(null, true);
} else { } else {
cb(new HttpException(`Unsupported file type ${extname(file.originalname)}`, HttpStatus.BAD_REQUEST), false); cb(new HttpException(`Unsupported file type ${extname(file.originalname)}`, HttpStatus.BAD_REQUEST), false);

View File

@ -43,12 +43,19 @@ export class ImageOptimizeProcessor {
console.error('Error Reading File'); console.error('Error Reading File');
} }
if (savedAsset.mimeType == 'image/heic' || savedAsset.mimeType == 'image/heif') { // Special Assets Type - ios
if (
savedAsset.mimeType == 'image/heic' ||
savedAsset.mimeType == 'image/heif' ||
savedAsset.mimeType == 'image/dng'
) {
let desitnation = ''; let desitnation = '';
if (savedAsset.mimeType == 'image/heic') { if (savedAsset.mimeType == 'image/heic') {
desitnation = resizePath.replace('.HEIC', '.jpeg'); desitnation = resizePath.replace('.HEIC', '.jpeg');
} else { } else if (savedAsset.mimeType == 'image/heif') {
desitnation = resizePath.replace('.HEIF', '.jpeg'); desitnation = resizePath.replace('.HEIF', '.jpeg');
} else if (savedAsset.mimeType == 'image/dng') {
desitnation = resizePath.replace('.DNG', '.jpeg');
} }
sharp(data) sharp(data)