Files
RecipesCam/3_FIX_RECIPE.md
T

9.6 KiB

Kế Hoạch Sửa Lỗi Bộ Lọc Màu & Đồng Bộ Định Vị CamRecipe ProTài liệu này tập trung giải quyết triệt để các lỗi hiển thị hình ảnh trên kính ngắm (Viewfinder) di động thực tế dựa theo các tệp tin hình ảnh báo lỗi đính kèm từ người dùng.1. Khắc Phục Lỗi Nhiệt Độ Màu (White Balance Kelvin) Bị NgượcVấn đề kỹ thuật (Ảnh 3 & Ảnh 4)Hiện trạng thực tế:Như trong Screenshot_2026-07-17-10-25-59-810_com.locphamtran.recipescamera.jpg, khi kéo thanh trượt WB lên kịch khung 10000K, kính ngắm camera lại bị ám xanh dương lạnh ngắt.Ngược lại, trong Screenshot_2026-07-17-10-25-55-474_com.locphamtran.recipescamera.jpg, khi hạ WB xuống kịch khung 2500K, kính ngắm lại bị ám vàng/cam ấm rực rỡ.Nguyên nhân: Logic ánh xạ giữa giá trị Kelvin và ma trận bù trừ màu sắc (Color compensation matrix) bị nghịch đảo chéo góc. Trong nhiếp ảnh, khi cài đặt WB lên mức cao (ví dụ 10000\text{K}), máy ảnh hiểu nguồn sáng môi trường đang rất lạnh nên phải bù trừ bằng sắc tông ấm (Amber/Orange). Khi cài đặt WB thấp (2500\text{K}), máy ảnh hiểu nguồn sáng rất ấm (Tungsten) nên phải bù trừ bằng dải tông lạnh (Blue) để đưa sắc trắng về trung tính.Giải pháp khắc phụcChúng ta sẽ viết lại thuật toán quy đổi Kelvin sang RGB bổ sung hệ số bù trừ ảnh nghịch đảo chính xác như sau:$\text{Temp} = \frac{\text{Kelvin}}{100}$Hệ số RGB bù trừ màu sắc thực tế sẽ được ánh xạ chính xác trên GPU:Nếu \text{Kelvin} < 5500\text{K} (compensate for warm light): Giảm mạnh hệ số R, tăng hệ số B để tạo tông màu xanh lạnh.Nếu \text{Kelvin} \ge 5500\text{K} (compensate for cold light): Tăng mạnh hệ số R, giảm hệ số B để tạo tông màu vàng ấm.// Sửa đổi hàm ánh xạ Kelvin trong file src/utils/kelvinToRGB.ts export function kelvinToRGBCompensation(kelvin: number) { const k = Math.min(10000, Math.max(2500, kelvin)); let r = 1.0, g = 1.0, b = 1.0;

if (k < 5500) { // 2500K -> 5500K: Cần ám xanh dương để bù trừ ánh sáng ấm const factor = (5500 - k) / 3000; // dải 0 -> 1 r = 1.0 - factor * 0.45; g = 1.0 - factor * 0.15; b = 1.0 + factor * 0.50; // Tăng cường sắc xanh dương } else { // 5500K -> 10000K: Cần ám vàng/đỏ để bù trừ ánh sáng lạnh const factor = (k - 5500) / 4500; // dải 0 -> 1 r = 1.0 + factor * 0.55; // Tăng cường sắc đỏ ấm g = 1.0 + factor * 0.20; b = 1.0 - factor * 0.40; }

return { r, g, b }; } 2. Khắc Phục Lỗi Rò Rỉ Màu Trên Chế Độ Monochrome (ACROS MONO)Vấn đề kỹ thuật (Ảnh 1)Hiện trạng thực tế: Như hiển thị trong Screenshot_2026-07-17-10-23-53-813_com.locphamtran.recipescamera.jpg, khi nhấn chọn bộ lọc đơn sắc ACROS MONO, dải đèn LED RGB trên bàn phím máy tính vẫn rực rỡ sắc đỏ, xanh, hồng tím thay vì hiển thị dải xám đen mộc mạc.Nguyên nhân: Logic áp màu phim bỏ qua bộ lọc trắng đen của Skia do điều kiện rẽ nhánh ma trận màu bị lỗi hoặc hệ số ma trận màu trắng đen chưa triệt tiêu hoàn toàn dải bão hòa màu sắc (Saturation) trên luồng camera thời gian thực.Giải pháp khắc phụcÉp các hệ số ma trận màu sắc của ACROS MONO về đúng tiêu chuẩn độ chói quốc tế ITU-R BT.709 nhằm triệt tiêu hoàn toàn thông tin màu sắc:$Y = 0.2126 \cdot R + 0.7152 \cdot G + 0.0722 \cdot B$// Khóa chặt ma trận lọc màu trắng đen tuyệt đối của Skia const acrosMatrix = [ 0.2126, 0.7152, 0.0722, 0, 0, // Kênh Đỏ chỉ lấy thông tin độ chói xám 0.2126, 0.7152, 0.0722, 0, 0, // Kênh Xanh lá tương tự 0.2126, 0.7152, 0.0722, 0, 0, // Kênh Xanh dương tương tự 0, 0, 0, 1, 0 // Giữ nguyên kênh Alpha ];

// Áp dụng bộ lọc ma trận sắc độ xám đơn sắc chuẩn nhiếp ảnh const activeColorFilter = currentRecipe.film_sim === 'acros' ? Skia.ColorFilter.Matrix(acrosMatrix) : Skia.ColorFilter.Matrix(standardColorMatrix); 3. Loại Bỏ Lớp Mờ Sương (Fog Overlay) Trên Viewfinder Khi Thay Đổi WBVấn đề kỹ thuật (Ảnh 2)Hiện trạng thực tế: Như trong Screenshot_2026-07-17-10-25-47-625_com.locphamtran.recipescamera.jpg, khi chỉnh nhiệt độ màu về đúng trị số 6600K, lớp mờ sương (blur) bỗng nhiên biến mất kỳ lạ giúp ảnh sắc nét hẳn lên.Nguyên nhân: Lỗi phân chia dải biến số (division/overflow error) trong hàm shader tự động làm mờ ảnh khi xử lý nhiệt độ màu. Bộ lọc Gaussian Blur (feGaussianBlur) bị liên kết sai lệch với biến nhiệt độ màu wb, khiến cho ở các dải nhiệt độ khác ngoài 6600K, bán kính mờ (stdDeviation) bị tính toán sai vượt ngưỡng 0 mặc dù độ sắc nét hoặc độ mịn màng không thay đổi.Giải pháp khắc phụcCô lập hoàn toàn giá trị mờ sương khỏi bộ điều phối WB. Chỉ kích hoạt hiệu ứng mờ sương khi và chỉ khi người dùng chủ động tinh chỉnh dải thanh trượt Clarity < 0 hoặc Denoise < 0:// Tách biệt hoàn toàn tính toán bán kính mờ sương khỏi White Balance const getBlurSigma = (clarity: number, grainStrength: number) => { 'worklet'; let blurSigma = 0;

// Chỉ áp dụng hiệu ứng Bloom/Mist mềm mại khi Clarity ở mức âm if (clarity < 0) { blurSigma = Math.abs(clarity) * 0.45; // Khống chế bán kính mờ mịn màng }

// Chỉ áp dụng khử nhiễu (Denoise) làm mượt hạt khi Grain ở mức âm if (grainStrength < 0) { const denoiseSigma = Math.abs(grainStrength) * 0.35; blurSigma = Math.max(blurSigma, denoiseSigma); }

return blurSigma; // Trả về 0 nếu các thông số này không ở mức âm }; 4. Đồng Bộ Hóa Recipes Thời Gian Thực Trên Native Camera PreviewVấn đề kỹ thuậtHiện trạng thực tế: Các thông số phơi sáng trong tab EXPOSURE hay dải lọc màu trong tab WB & CHROME thay đổi trên thanh trượt nhưng kính ngắm camera trực tiếp vẫn trơ trơ không thay đổi màu sắc.Nguyên nhân: Biến trạng thái tùy chỉnh của React Native (adjustments) khi thay đổi không kích hoạt việc vẽ lại (re-render) trên luồng xử lý frame của camera (Vision Camera Frame Processor hoặc Skia Canvas), do thiếu các biến liên kết phụ thuộc (dependency array) hoặc chưa đưa giá trị thông số màu về dạng Shared Values của thư viện react-native-reanimated.Giải pháp khắc phụcSử dụng hook useSharedValue để truyền giá trị tức thời của thanh sliders sang luồng xử lý đồ họa GPU của Skia nhằm cập nhật kính ngắm ở tốc độ 60 FPS:import { useSharedValue, useDerivedValue } from 'react-native-reanimated';

export function ViewfinderCamera() { // Đồng bộ hóa các dải thông số màu dưới dạng Shared Values của GPU const exposureVal = useSharedValue(0.7); const kelvinVal = useSharedValue(5800); const colorChromeVal = useSharedValue('strong');

// Đăng ký lắng nghe sự thay đổi của sliders để cập nhật tức thì ma trận màu Skia const skiaColorFilter = useDerivedValue(() => { const matrix = calculateDynamicMatrix(exposureVal.value, kelvinVal.value, colorChromeVal.value); return Skia.ColorFilter.Matrix(matrix); }, [exposureVal, kelvinVal, colorChromeVal]);

return ( <Canvas style={{ flex: 1 }}> ); } 5. Khắc Phục Lỗi Đọc GPS Định Vị Gốc Của Ảnh Thư ViệnVấn đề kỹ thuậtHiện trạng thực tế: Khi tải ảnh lên từ thư viện, Geotag watermark ở góc dưới bên trái vẫn hiển thị tọa độ GPS của vị trí điện thoại hiện tại, bỏ qua lịch sử vị trí chụp gốc lưu trong EXIF của tệp tin.Nguyên nhân: API chọn ảnh (expo-image-picker) theo mặc định chỉ trả về một đường dẫn URI tạm thời bị lược bỏ hoàn toàn các siêu dữ liệu EXIF nhạy cảm vì lý do bảo mật quyền riêng tư của hệ điều hành.Giải pháp khắc phụcSử dụng gói truy vấn tài sản chuyên sâu expo-media-library để yêu cầu hệ thống cung cấp siêu dữ liệu chi tiết của bức ảnh gốc thông qua mã định danh tài sản (assetId):import * as MediaLibrary from 'expo-media-library';

export const getOriginalPhotoLocation = async (assetId: string) => { try { // Yêu cầu quyền truy cập thư viện đầy đủ từ hệ điều hành const { status } = await MediaLibrary.requestPermissionsAsync(); if (status === 'granted') { // Truy vấn thông tin chi tiết của ảnh gốc bao gồm tọa độ GPS chụp lịch sử const assetInfo = await MediaLibrary.getAssetInfoAsync(assetId); if (assetInfo.location) { return { latitude: assetInfo.location.latitude, longitude: assetInfo.location.longitude, source: 'EXIF_ORIGINAL' }; } } } catch (error) { console.warn("Không thể trích xuất định vị EXIF gốc từ ảnh thư viện:", error); } return null; // Trả về null để chuyển sang định vị hiện tại làm dự phòng (fallback) };