android/camera: Implement image flipping
We use libyuv's Mirror function to handle horizontal flip. Regarding the vertical flip, libyuv doc states that 'just set a negative height'
This commit is contained in:
parent
24fc1150a8
commit
c130c065b4
@ -210,8 +210,13 @@ CaptureSession::CaptureSession(ACameraManager* manager, const std::string& id) {
|
|||||||
#undef CAMERA_CALL
|
#undef CAMERA_CALL
|
||||||
#undef CREATE
|
#undef CREATE
|
||||||
|
|
||||||
Interface::Interface(Factory& factory_, const std::string& id_, const Service::CAM::Flip& flip_)
|
Interface::Interface(Factory& factory_, const std::string& id_, const Service::CAM::Flip& flip)
|
||||||
: factory(factory_), id(id_), flip(flip_) {}
|
: factory(factory_), id(id_) {
|
||||||
|
mirror = base_mirror =
|
||||||
|
flip == Service::CAM::Flip::Horizontal || flip == Service::CAM::Flip::Reverse;
|
||||||
|
invert = base_invert =
|
||||||
|
flip == Service::CAM::Flip::Vertical || flip == Service::CAM::Flip::Reverse;
|
||||||
|
}
|
||||||
|
|
||||||
Interface::~Interface() = default;
|
Interface::~Interface() = default;
|
||||||
|
|
||||||
@ -227,8 +232,11 @@ void Interface::SetResolution(const Service::CAM::Resolution& resolution_) {
|
|||||||
resolution = resolution_;
|
resolution = resolution_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interface::SetFlip(Service::CAM::Flip flip_) {
|
void Interface::SetFlip(Service::CAM::Flip flip) {
|
||||||
flip = flip_;
|
mirror = base_mirror ^
|
||||||
|
(flip == Service::CAM::Flip::Horizontal || flip == Service::CAM::Flip::Reverse);
|
||||||
|
invert =
|
||||||
|
base_invert ^ (flip == Service::CAM::Flip::Vertical || flip == Service::CAM::Flip::Reverse);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interface::SetFormat(Service::CAM::OutputFormat format_) {
|
void Interface::SetFormat(Service::CAM::OutputFormat format_) {
|
||||||
@ -265,19 +273,32 @@ std::vector<u16> Interface::ReceiveFrame() {
|
|||||||
scaled_y.data(), resolution.width, scaled_u.data(), resolution.width / 4,
|
scaled_y.data(), resolution.width, scaled_u.data(), resolution.width / 4,
|
||||||
scaled_v.data(), resolution.width / 4, resolution.width, resolution.height,
|
scaled_v.data(), resolution.width / 4, resolution.width, resolution.height,
|
||||||
libyuv::kFilterBilinear);
|
libyuv::kFilterBilinear);
|
||||||
// TODO: Record and apply flip
|
|
||||||
|
if (mirror) {
|
||||||
|
std::vector<u8> mirrored_y(scaled_y.size());
|
||||||
|
std::vector<u8> mirrored_u(scaled_u.size());
|
||||||
|
std::vector<u8> mirrored_v(scaled_v.size());
|
||||||
|
libyuv::I420Mirror(scaled_y.data(), resolution.width, scaled_u.data(), resolution.width / 4,
|
||||||
|
scaled_v.data(), resolution.width / 4, mirrored_y.data(),
|
||||||
|
resolution.width, mirrored_u.data(), resolution.width / 4,
|
||||||
|
mirrored_v.data(), resolution.width / 4, resolution.width,
|
||||||
|
resolution.height);
|
||||||
|
scaled_y.swap(mirrored_y);
|
||||||
|
scaled_u.swap(mirrored_u);
|
||||||
|
scaled_v.swap(mirrored_v);
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<u16> output(resolution.width * resolution.height);
|
std::vector<u16> output(resolution.width * resolution.height);
|
||||||
if (format == Service::CAM::OutputFormat::RGB565) {
|
if (format == Service::CAM::OutputFormat::RGB565) {
|
||||||
libyuv::I420ToRGB565(scaled_y.data(), resolution.width, scaled_u.data(),
|
libyuv::I420ToRGB565(scaled_y.data(), resolution.width, scaled_u.data(),
|
||||||
resolution.width / 4, scaled_v.data(), resolution.width / 4,
|
resolution.width / 4, scaled_v.data(), resolution.width / 4,
|
||||||
reinterpret_cast<u8*>(output.data()), resolution.width * 2,
|
reinterpret_cast<u8*>(output.data()), resolution.width * 2,
|
||||||
resolution.width, resolution.height);
|
resolution.width, invert ? -resolution.height : resolution.height);
|
||||||
} else {
|
} else {
|
||||||
libyuv::I420ToYUY2(scaled_y.data(), resolution.width, scaled_u.data(), resolution.width / 4,
|
libyuv::I420ToYUY2(scaled_y.data(), resolution.width, scaled_u.data(), resolution.width / 4,
|
||||||
scaled_v.data(), resolution.width / 4,
|
scaled_v.data(), resolution.width / 4,
|
||||||
reinterpret_cast<u8*>(output.data()), resolution.width * 2,
|
reinterpret_cast<u8*>(output.data()), resolution.width * 2,
|
||||||
resolution.width, resolution.height);
|
resolution.width, invert ? -resolution.height : resolution.height);
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,13 @@ private:
|
|||||||
std::string id;
|
std::string id;
|
||||||
|
|
||||||
Service::CAM::Resolution resolution;
|
Service::CAM::Resolution resolution;
|
||||||
Service::CAM::Flip flip;
|
|
||||||
|
// Flipping parameters. mirror = horizontal, invert = vertical.
|
||||||
|
bool base_mirror{};
|
||||||
|
bool base_invert{};
|
||||||
|
bool mirror{};
|
||||||
|
bool invert{};
|
||||||
|
|
||||||
Service::CAM::OutputFormat format;
|
Service::CAM::OutputFormat format;
|
||||||
// std::vector<u16> image; // Data fetched from the frontend
|
// std::vector<u16> image; // Data fetched from the frontend
|
||||||
// bool opened{}; // Whether the camera was successfully opened
|
// bool opened{}; // Whether the camera was successfully opened
|
||||||
|
@ -29,7 +29,12 @@ void CleanupJNI(JNIEnv* env) {
|
|||||||
env->DeleteGlobalRef(s_still_image_camera_helper_class);
|
env->DeleteGlobalRef(s_still_image_camera_helper_class);
|
||||||
}
|
}
|
||||||
|
|
||||||
Interface::Interface(jstring path_, const Service::CAM::Flip& flip_) : path(path_), flip(flip_) {}
|
Interface::Interface(jstring path_, const Service::CAM::Flip& flip) : path(path_) {
|
||||||
|
mirror = base_mirror =
|
||||||
|
flip == Service::CAM::Flip::Horizontal || flip == Service::CAM::Flip::Reverse;
|
||||||
|
invert = base_invert =
|
||||||
|
flip == Service::CAM::Flip::Vertical || flip == Service::CAM::Flip::Reverse;
|
||||||
|
}
|
||||||
|
|
||||||
Interface::~Interface() {
|
Interface::~Interface() {
|
||||||
Factory::last_path = nullptr;
|
Factory::last_path = nullptr;
|
||||||
@ -70,13 +75,20 @@ void Interface::StartCapture() {
|
|||||||
info.width, info.height);
|
info.width, info.height);
|
||||||
BITMAP_CALL(unlockPixels(env, bitmap));
|
BITMAP_CALL(unlockPixels(env, bitmap));
|
||||||
|
|
||||||
|
if (mirror) {
|
||||||
|
std::vector<u8> mirrored(data.size());
|
||||||
|
libyuv::ARGBMirror(data.data(), info.stride, mirrored.data(), info.stride, info.width,
|
||||||
|
info.height);
|
||||||
|
data.swap(mirrored);
|
||||||
|
}
|
||||||
|
|
||||||
image.resize(info.height * info.width);
|
image.resize(info.height * info.width);
|
||||||
if (format == Service::CAM::OutputFormat::RGB565) {
|
if (format == Service::CAM::OutputFormat::RGB565) {
|
||||||
libyuv::ARGBToRGB565(data.data(), info.stride, reinterpret_cast<u8*>(image.data()),
|
libyuv::ARGBToRGB565(data.data(), info.stride, reinterpret_cast<u8*>(image.data()),
|
||||||
info.width * 2, info.width, info.height);
|
info.width * 2, info.width, invert ? -info.height : info.height);
|
||||||
} else {
|
} else {
|
||||||
libyuv::ARGBToYUY2(data.data(), info.stride, reinterpret_cast<u8*>(image.data()),
|
libyuv::ARGBToYUY2(data.data(), info.stride, reinterpret_cast<u8*>(image.data()),
|
||||||
info.width * 2, info.width, info.height);
|
info.width * 2, info.width, invert ? -info.height : info.height);
|
||||||
}
|
}
|
||||||
opened = true;
|
opened = true;
|
||||||
|
|
||||||
@ -87,8 +99,11 @@ void Interface::SetResolution(const Service::CAM::Resolution& resolution_) {
|
|||||||
resolution = resolution_;
|
resolution = resolution_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interface::SetFlip(Service::CAM::Flip flip_) {
|
void Interface::SetFlip(Service::CAM::Flip flip) {
|
||||||
flip = flip_;
|
mirror = base_mirror ^
|
||||||
|
(flip == Service::CAM::Flip::Horizontal || flip == Service::CAM::Flip::Reverse);
|
||||||
|
invert =
|
||||||
|
base_invert ^ (flip == Service::CAM::Flip::Vertical || flip == Service::CAM::Flip::Reverse);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interface::SetFormat(Service::CAM::OutputFormat format_) {
|
void Interface::SetFormat(Service::CAM::OutputFormat format_) {
|
||||||
|
@ -31,7 +31,13 @@ public:
|
|||||||
private:
|
private:
|
||||||
jstring path;
|
jstring path;
|
||||||
Service::CAM::Resolution resolution;
|
Service::CAM::Resolution resolution;
|
||||||
Service::CAM::Flip flip;
|
|
||||||
|
// Flipping parameters. mirror = horizontal, invert = vertical.
|
||||||
|
bool base_mirror{};
|
||||||
|
bool base_invert{};
|
||||||
|
bool mirror{};
|
||||||
|
bool invert{};
|
||||||
|
|
||||||
Service::CAM::OutputFormat format;
|
Service::CAM::OutputFormat format;
|
||||||
std::vector<u16> image; // Data fetched from the frontend
|
std::vector<u16> image; // Data fetched from the frontend
|
||||||
bool opened{}; // Whether the camera was successfully opened
|
bool opened{}; // Whether the camera was successfully opened
|
||||||
|
Loading…
x
Reference in New Issue
Block a user