Camera3: Handle different aspect ratios for thumbnail and main image
If thumbnail and main image aspect ratios are different, crop
the crop the thumbnail before downscale to prevent distortion/streching.
Also ensure thumbnail FOV is not outside the main image FOV in case
main image is cropped.
Bug: 14322819
Change-Id: I9b56fb8e94f92018aa7e8d8c2e50a7f855a4a426
diff --git a/camera/QCamera2/stack/mm-jpeg-interface/inc/mm_jpeg.h b/camera/QCamera2/stack/mm-jpeg-interface/inc/mm_jpeg.h
index 629049d..55ac502 100644
--- a/camera/QCamera2/stack/mm-jpeg-interface/inc/mm_jpeg.h
+++ b/camera/QCamera2/stack/mm-jpeg-interface/inc/mm_jpeg.h
@@ -43,6 +43,7 @@
#define MM_JPEG_CIRQ_SIZE 30
#define MM_JPEG_MAX_SESSION 10
#define MAX_EXIF_TABLE_ENTRIES 50
+#define ASPECT_TOLERANCE 0.001
typedef struct {
struct cam_list list;
diff --git a/camera/QCamera2/stack/mm-jpeg-interface/src/mm_jpeg.c b/camera/QCamera2/stack/mm-jpeg-interface/src/mm_jpeg.c
index bb72cfa..5b82bdb 100644
--- a/camera/QCamera2/stack/mm-jpeg-interface/src/mm_jpeg.c
+++ b/camera/QCamera2/stack/mm-jpeg-interface/src/mm_jpeg.c
@@ -35,6 +35,7 @@
#include <sys/prctl.h>
#include <fcntl.h>
#include <poll.h>
+#include <math.h>
#include "mm_jpeg_dbg.h"
#include "mm_jpeg_interface.h"
@@ -105,6 +106,23 @@
#define GET_SESSION_IDX(x) (((x) >> 8) & 0xff)
#define GET_JOB_IDX(x) (((x) >> 16) & 0xff)
+/** GCD:
+ * @x: input number
+ * @y: input number
+ * @gcd: gcd of x and y
+ *
+ * Find the GCD of 2 numbers
+ **/
+#define GCD( x, y, gcd) ({ \
+ int tmp; \
+ while (*y != 0) { \
+ tmp = *x % *y; \
+ *x = *y; \
+ *y = tmp; \
+ } \
+ *gcd = *x; \
+})
+
OMX_ERRORTYPE mm_jpeg_ebd(OMX_HANDLETYPE hComponent,
OMX_PTR pAppData,
OMX_BUFFERHEADERTYPE* pBuffer);
@@ -778,6 +796,50 @@
return ret;
}
+/** mm_jpeg_get_thumbnail_crop
+ *
+ * Arguments:
+ * @p_thumb_dim: thumbnail dimension
+ * @p_main_dim: main image dimension
+ * @crop_width : flag indicating if width needs to be cropped
+ *
+ * Return:
+ * OMX error values
+ *
+ * Description:
+ * If the main image and thumbnail ascpect ratios are differnt,
+ * re-calculate the thumbnail crop info to prevent distortion
+ *
+ */
+OMX_ERRORTYPE mm_jpeg_get_thumbnail_crop(mm_jpeg_dim_t *p_thumb_dim,
+ mm_jpeg_dim_t *p_main_dim, uint8_t crop_width) {
+ OMX_ERRORTYPE ret = OMX_ErrorNone;
+ int divisor;
+ int cropped_width = 0, cropped_height = 0;
+
+ if(crop_width) {
+ //Keep height constant
+ cropped_height = p_thumb_dim->src_dim.height;
+ cropped_width = floor((cropped_height * p_thumb_dim->dst_dim.width) /
+ p_thumb_dim->dst_dim.height);
+ } else {
+ //Keep width constant
+ cropped_width = p_thumb_dim->src_dim.width;
+ cropped_height = floor((cropped_width * p_thumb_dim->dst_dim.height) /
+ p_thumb_dim->dst_dim.width);
+ }
+ p_thumb_dim->crop.left = floor(p_thumb_dim->src_dim.width - cropped_width)/2;
+ p_thumb_dim->crop.top = floor(p_thumb_dim->src_dim.height - cropped_height)/2;
+ p_thumb_dim->crop.width = cropped_width;
+ p_thumb_dim->crop.height = cropped_height;
+
+ CDBG_HIGH("%s %d New thumbnail crop: left %d, top %d, crop width %d, crop height %d",
+ __func__, __LINE__, p_thumb_dim->crop.left, p_thumb_dim->crop.top,
+ p_thumb_dim->crop.width, p_thumb_dim->crop.height);
+
+ return ret;
+}
+
/** mm_jpeg_omx_config_thumbnail:
*
* Arguments:
@@ -853,10 +915,6 @@
thumbnail_info.scaling_enabled = 1;
thumbnail_info.input_width = p_thumb_dim->src_dim.width;
thumbnail_info.input_height = p_thumb_dim->src_dim.height;
- thumbnail_info.crop_info.nWidth = p_thumb_dim->crop.width;
- thumbnail_info.crop_info.nHeight = p_thumb_dim->crop.height;
- thumbnail_info.crop_info.nLeft = p_thumb_dim->crop.left;
- thumbnail_info.crop_info.nTop = p_thumb_dim->crop.top;
thumbnail_info.quality = p_params->thumb_quality;
if ((p_main_dim->src_dim.width < p_thumb_dim->src_dim.width) ||
@@ -878,6 +936,48 @@
}
}
+ //If the main image and thumbnail aspect ratio are different, reset the
+ // thumbnail crop info to avoid distortion
+ double main_aspect_ratio = (double)p_main_dim->dst_dim.width /
+ (double)p_main_dim->dst_dim.height;
+ double thumb_aspect_ratio = (double)p_thumb_dim->dst_dim.width /
+ (double)p_thumb_dim->dst_dim.height;
+ if ((thumb_aspect_ratio - main_aspect_ratio) > ASPECT_TOLERANCE) {
+ mm_jpeg_get_thumbnail_crop(p_thumb_dim, p_main_dim, 0);
+ } else if((main_aspect_ratio - thumb_aspect_ratio) > ASPECT_TOLERANCE){
+ mm_jpeg_get_thumbnail_crop(p_thumb_dim, p_main_dim, 1);
+ }
+
+
+ //Fill thumbnail crop info
+ thumbnail_info.crop_info.nWidth = p_thumb_dim->crop.width;
+ thumbnail_info.crop_info.nHeight = p_thumb_dim->crop.height;
+ thumbnail_info.crop_info.nLeft = p_thumb_dim->crop.left;
+ thumbnail_info.crop_info.nTop = p_thumb_dim->crop.top;
+
+ //If main image cropping/scaling is enabled, thumb FOV should be within
+ //main image FOV
+ if ((p_main_dim->crop.width != p_main_dim->src_dim.width) ||
+ (p_main_dim->crop.height != p_main_dim->src_dim.height)) {
+ if ((p_thumb_dim->crop.left < p_main_dim->crop.left) ||
+ ((p_thumb_dim->crop.left + p_thumb_dim->crop.width) >
+ (p_main_dim->crop.left + p_main_dim->crop.width)) ||
+ (p_thumb_dim->crop.top < p_main_dim->crop.top) ||
+ ((p_thumb_dim->crop.top + p_thumb_dim->crop.height) >
+ (p_main_dim->crop.top + p_main_dim->crop.height))) {
+ //Reset the FOV for the thumbnail
+ CDBG_HIGH("%s:%d] Resetting the thumbnail FOV wrt main image",
+ __func__, __LINE__);
+ thumbnail_info.crop_info.nLeft = p_main_dim->crop.left;
+ thumbnail_info.crop_info.nTop = p_main_dim->crop.height;
+ if ((p_thumb_dim->crop.width > p_main_dim->crop.width) ||
+ (p_thumb_dim->crop.height > p_main_dim->crop.height)) {
+ thumbnail_info.crop_info.nWidth = p_main_dim->crop.width;
+ thumbnail_info.crop_info.nHeight = p_main_dim->crop.height;
+ }
+ }
+ }
+
if ((p_thumb_dim->dst_dim.width > p_thumb_dim->src_dim.width)
|| (p_thumb_dim->dst_dim.height > p_thumb_dim->src_dim.height)) {
CDBG_ERROR("%s:%d] Incorrect thumbnail dim %dx%d resetting to %dx%d",