feat: add gallery service and ML depth estimation placeholder
Media library access via new expo-media-library Query API, image resize for wallpaper export, and MiDaS depth map service stub for V1.5.
This commit is contained in:
50
src/services/media/gallery.service.ts
Normal file
50
src/services/media/gallery.service.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import * as MediaLibrary from "expo-media-library";
|
||||
import * as ImageManipulator from "expo-image-manipulator";
|
||||
import { Dimensions } from "react-native";
|
||||
|
||||
const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get("screen");
|
||||
|
||||
export async function requestGalleryPermission(): Promise<boolean> {
|
||||
const { status } = await MediaLibrary.requestPermissionsAsync();
|
||||
return status === "granted";
|
||||
}
|
||||
|
||||
export async function getRecentPhotos(
|
||||
count: number = 50,
|
||||
offset: number = 0
|
||||
): Promise<{ assets: MediaLibrary.Asset[]; hasMore: boolean }> {
|
||||
const query = new MediaLibrary.Query()
|
||||
.eq(MediaLibrary.AssetField.MEDIA_TYPE, MediaLibrary.MediaType.IMAGE)
|
||||
.orderBy({
|
||||
key: MediaLibrary.AssetField.CREATION_TIME,
|
||||
ascending: false,
|
||||
})
|
||||
.limit(count)
|
||||
.offset(offset);
|
||||
|
||||
const assets = await query.exe();
|
||||
|
||||
return {
|
||||
assets,
|
||||
hasMore: assets.length === count,
|
||||
};
|
||||
}
|
||||
|
||||
export async function prepareImageForWallpaper(
|
||||
uri: string
|
||||
): Promise<string> {
|
||||
const result = await ImageManipulator.manipulateAsync(
|
||||
uri,
|
||||
[
|
||||
{
|
||||
resize: {
|
||||
width: SCREEN_WIDTH * 2,
|
||||
height: SCREEN_HEIGHT * 2,
|
||||
},
|
||||
},
|
||||
],
|
||||
{ compress: 0.95, format: ImageManipulator.SaveFormat.JPEG }
|
||||
);
|
||||
|
||||
return result.uri;
|
||||
}
|
||||
46
src/services/ml/depth.service.ts
Normal file
46
src/services/ml/depth.service.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { Platform } from "react-native";
|
||||
|
||||
// Depth estimation service — V1.5 feature
|
||||
// Uses MiDaS v2.1 small (TFLite) for on-device depth map generation
|
||||
// Model size: ~17MB, inference: ~50-80ms on mid-range devices
|
||||
|
||||
export interface DepthMapResult {
|
||||
uri: string; // Path to grayscale depth map PNG
|
||||
width: number;
|
||||
height: number;
|
||||
inferenceTimeMs: number;
|
||||
}
|
||||
|
||||
export async function isDepthEstimationAvailable(): Promise<boolean> {
|
||||
// Will check for TFLite model availability
|
||||
// For now, return false — not yet implemented
|
||||
return false;
|
||||
}
|
||||
|
||||
export async function generateDepthMap(
|
||||
imageUri: string
|
||||
): Promise<DepthMapResult> {
|
||||
// TODO V1.5: Implement with react-native-fast-tflite or ONNX Runtime
|
||||
//
|
||||
// Pipeline:
|
||||
// 1. Load image, resize to MiDaS input size (256x256 or 384x384)
|
||||
// 2. Normalize to [0,1] float tensor
|
||||
// 3. Run MiDaS inference
|
||||
// 4. Resize output to original image dimensions
|
||||
// 5. Normalize depth values to [0,255] grayscale
|
||||
// 6. Save as PNG, return URI
|
||||
//
|
||||
// The depth map will be cached in MMKV keyed by image URI hash
|
||||
// to avoid recomputation.
|
||||
|
||||
throw new Error(
|
||||
"Depth estimation not yet available. Coming in V1.5 with MiDaS on-device inference."
|
||||
);
|
||||
}
|
||||
|
||||
export async function downloadDepthModel(): Promise<void> {
|
||||
// TODO: Download MiDaS TFLite model from Cloudflare R2
|
||||
// Model is not bundled in the app to keep binary size down
|
||||
// Download on first use of depth-parallax animation
|
||||
throw new Error("Model download not yet implemented.");
|
||||
}
|
||||
Reference in New Issue
Block a user