fix: sửa export/gps/UI theo FIX_PLAN + chụp ảnh camera thật (takePhoto)

- export: encodeToBase64 thay SkData.toString, dùng expo-media-library/legacy
- GPS ảnh gốc: resolver EXIF -> MediaLibrary -> device (ACCESS_MEDIA_LOCATION), tag nguồn watermark
- contrast vào color matrix (có hiệu lực mono), ẩn highlight/shadow, denoise/clarity ghi chú export-only
- init session tuần tự, tách setState lồng nhau, share file bằng expo-sharing, DONE lưu gallery
- Phase 4A: chụp camera thật qua vision-camera takePhoto rồi export filter
This commit is contained in:
2026-09-07 06:54:13 +07:00
parent 0d276861e0
commit 96f412e269
13 changed files with 892 additions and 421 deletions
+28 -25
View File
@@ -27,6 +27,7 @@ export function kelvinToRGB(kelvin: number): { r: number; g: number; b: number }
export function getSkiaColorMatrix(
baseFilter: 'classic-neg' | 'provia' | 'velvia' | 'monochrome' | 'none',
exposure: number, // -10 to +10
contrast: number, // -10 to +10
saturation: number, // -10 to +10
temperature: number, // 2500 to 10000
tint: number, // -10 to +10
@@ -110,34 +111,36 @@ export function getSkiaColorMatrix(
}
// 5. White Balance (Kelvin Temperature and Tint) — skip for monochrome to prevent color leakage
if (baseFilter === 'monochrome') {
return matrix;
}
const rgbTemp = kelvinToRGB(temperature);
// Tint adjustment: -10 is Green (+G), +10 is Magenta (+R, +B)
const tintR = tint > 0 ? (tint / 10) * 0.08 : 0;
const tintG = tint < 0 ? (-tint / 10) * 0.08 : 0;
const tintB = tint > 0 ? (tint / 10) * 0.08 : 0;
if (baseFilter !== 'monochrome') {
const rgbTemp = kelvinToRGB(temperature);
// Tint adjustment: -10 is Green (+G), +10 is Magenta (+R, +B)
const tintR = tint > 0 ? (tint / 10) * 0.08 : 0;
const tintG = tint < 0 ? (-tint / 10) * 0.08 : 0;
const tintB = tint > 0 ? (tint / 10) * 0.08 : 0;
const wbMat = [
rgbTemp.r + tintR, 0, 0, 0, 0,
0, rgbTemp.g + tintG, 0, 0, 0,
0, 0, rgbTemp.b + tintB, 0, 0,
0, 0, 0, 1, 0,
];
matrix = multiplyMatrices(wbMat, matrix);
// 6. Exposure adjustment (Simple offset in fifth column and slight scaling)
if (exposure !== 0) {
const scale = 1 + (exposure / 10) * 0.2; // scaling multiplier
const offset = (exposure / 10) * 0.15; // translation offset
const expMat = [
scale, 0, 0, 0, offset,
0, scale, 0, 0, offset,
0, 0, scale, 0, offset,
const wbMat = [
rgbTemp.r + tintR, 0, 0, 0, 0,
0, rgbTemp.g + tintG, 0, 0, 0,
0, 0, rgbTemp.b + tintB, 0, 0,
0, 0, 0, 1, 0,
];
matrix = multiplyMatrices(expMat, matrix);
matrix = multiplyMatrices(wbMat, matrix);
}
// 6. Exposure & Contrast — applied to ALL base filters (monochrome included) so
// both keep affecting mono shots. Contrast scales around mid-grey 0.5.
if (exposure !== 0 || contrast !== 0) {
const expScale = 1 + (exposure / 10) * 0.2; // -10 → 0.8x, +10 → 1.2x
const expOffset = (exposure / 10) * 0.15;
const conScale = 1 + (contrast / 10) * 0.25; // -10 → 0.75x, +10 → 1.25x
const conOffset = 0.5 * (1 - conScale);
const adjMat = [
expScale * conScale, 0, 0, 0, expOffset + conOffset * expScale,
0, expScale * conScale, 0, 0, expOffset + conOffset * expScale,
0, 0, expScale * conScale, 0, expOffset + conOffset * expScale,
0, 0, 0, 1, 0,
];
matrix = multiplyMatrices(adjMat, matrix);
}
return matrix;