diff --git a/src/main.c b/src/main.c index 4eae63f..23805ea 100644 --- a/src/main.c +++ b/src/main.c @@ -422,6 +422,7 @@ preview_draw(GtkGLArea *area, GdkGLContext *ctx, gpointer data) glViewport( offset_x, state.preview_height - size_y - offset_y, size_x, size_y); + // This rotates the camera preview based on the phone rotation if (current_preview_buffer) { glUseProgram(blit_program); @@ -469,20 +470,38 @@ preview_draw(GtkGLArea *area, GdkGLContext *ctx, gpointer data) MPZBarCode *code = &zbar_result->codes[i]; GLfloat vertices[] = { - code->bounds_x[0], code->bounds_y[0], - code->bounds_x[1], code->bounds_y[1], - code->bounds_x[3], code->bounds_y[3], - code->bounds_x[2], code->bounds_y[2], + code->bounds_x[0], code->bounds_y[0], // Bottom left + code->bounds_x[1], code->bounds_y[1], // Bottom right + code->bounds_x[3], code->bounds_y[3], // Top left + code->bounds_x[2], code->bounds_y[2], // Top right }; + // Convert the pixel X/Y coordinates to OpenGL coordinates + // (-1 to 1) for (int i = 0; i < 4; ++i) { - vertices[i * 2] = - 2 * vertices[i * 2] / - state.preview_buffer_width - - 1.0; - vertices[i * 2 + 1] = - 1.0 - 2 * vertices[i * 2 + 1] / - state.preview_buffer_height; + // Width/height need to be swapped between portrait + // mode and landscape mode for symbols to render + // correctly + if (state.device_rotation == 0 || + state.device_rotation == 180) { + vertices[i * 2] = + 2 * vertices[i * 2] / + state.preview_buffer_width - + 1.0; + vertices[i * 2 + 1] = + 1.0 - + 2 * vertices[i * 2 + 1] / + state.preview_buffer_height; + } else { + vertices[i * 2] = + 2 * vertices[i * 2] / + state.preview_buffer_height - + 1.0; + vertices[i * 2 + 1] = + 1.0 - + 2 * vertices[i * 2 + 1] / + state.preview_buffer_width; + } } if (gtk_gl_area_get_use_es(area)) { diff --git a/src/process_pipeline.c b/src/process_pipeline.c index cc48a2d..6d031e0 100644 --- a/src/process_pipeline.c +++ b/src/process_pipeline.c @@ -1115,7 +1115,7 @@ process_image(MPPipeline *pipeline, const MPBuffer *buffer) state_proc.mode->format, state_proc.mode->width, state_proc.mode->height, - state_proc.device_rotation, + state_proc.camera_rotation, state_proc.mode->mirrored); mp_zbar_pipeline_process_image(mp_zbar_image_ref(zbar_image)); diff --git a/src/zbar_pipeline.c b/src/zbar_pipeline.c index 80da3d2..849015a 100644 --- a/src/zbar_pipeline.c +++ b/src/zbar_pipeline.c @@ -77,6 +77,19 @@ is_3d_code(zbar_symbol_type_t type) } } +/* + * This function gets given the x/y coordinates of the corners of a QR-code/symbol, + * but zbar is given an image buffer that may be rotated/mirrored. + * So here we adjust the coordinates based on that, so it can be used in src/main.c + * to display the symbol on top of the correctly rotated/mirrored camera preview. + * + * Rotation 0 is the phone in landscape mode (counter-clockwise) + * Rotation 90 is the phone in portrait mode upside down + * Rotation 180 is the phone in landscape mode (clockwise) + * Rotation 270 is the phone in portrait mode + * + * Mirrored is mainly/only(?) used for front cameras + */ static inline void map_coords(int *x, int *y, int width, int height, int rotation, bool mirrored) { @@ -109,6 +122,7 @@ process_symbol(const MPZBarImage *image, int height, const zbar_symbol_t *symbol) { + // When device is in portrait mode, swap width/height if (image->rotation == 90 || image->rotation == 270) { int tmp = width; width = height;