3
0

galaxys2-common: fix EXIF data generated by the camera

* ensure that all IFDs are 12 bytes long; previously when the data field contained less than 4 bytes of data the IFDs were truncated too soon
 * change all data types and number of components according to the EXIF standard
 * get the actual status of the flash from the camera; previosly the camera flash settings (which are not valid EXIF values) were copied in
 * fix calculations of GPS coordinates

With these changes the EXIF generated by the camera are valid and readable. There are still issues with some tags but most data is correct now.

Thanks to dafnis, who identified the problematic fields, and tryptophane, who helped testing.

Patch Set 2: fix whitespaces.

Change-Id: I513ea89f69ff26646e6a4a439b1cd5b835cba8d6
This commit is contained in:
ghepeu 2013-05-05 02:30:20 +02:00
parent 8f1e7b0333
commit bcbeb5ebef

View File

@ -133,8 +133,8 @@ int exynos_exif_attributes_create_gps(struct exynos_camera *exynos_camera,
return 0;
}
gps_latitude = (long) (gps_latitude_float * 10000) / 1;
gps_longitude = (long) (gps_longitude_float * 10000) / 1;
gps_latitude = (long) (gps_latitude_float * 10000000) / 1;
gps_longitude = (long) (gps_longitude_float * 10000000) / 1;
gps_altitude = (long) (gps_altitude_float * 100) / 1;
gps_timestamp = (long) gps_timestamp_int;
@ -159,26 +159,26 @@ int exynos_exif_attributes_create_gps(struct exynos_camera *exynos_camera,
exif_attributes->gps_altitude_ref = 1;
gps_latitude_abs = fabs(gps_latitude / 10000.0);
gps_longitude_abs = fabs(gps_longitude / 10000.0);
gps_altitude_abs = fabs(gps_altitude / 100.0);
gps_latitude_abs = fabs(gps_latitude);
gps_longitude_abs = fabs(gps_longitude);
gps_altitude_abs = fabs(gps_altitude);
exif_attributes->gps_latitude[0].num = (uint32_t) gps_latitude_abs;
exif_attributes->gps_latitude[0].den = 1;
exif_attributes->gps_latitude[0].den = 10000000;
exif_attributes->gps_latitude[1].num = 0;
exif_attributes->gps_latitude[1].den = 1;
exif_attributes->gps_latitude[2].num = 0;
exif_attributes->gps_latitude[2].den = 1;
exif_attributes->gps_longitude[0].num = (uint32_t) gps_longitude_abs;
exif_attributes->gps_longitude[0].den = 1;
exif_attributes->gps_longitude[0].den = 10000000;
exif_attributes->gps_longitude[1].num = 0;
exif_attributes->gps_longitude[1].den = 1;
exif_attributes->gps_longitude[2].num = 0;
exif_attributes->gps_longitude[2].den = 1;
exif_attributes->gps_altitude.num = (uint32_t) gps_altitude_abs;
exif_attributes->gps_altitude.den = 1;
exif_attributes->gps_altitude.den = 100;
gmtime_r(&gps_timestamp, &time_info);
@ -207,6 +207,7 @@ int exynos_exif_attributes_create_params(struct exynos_camera *exynos_camera,
int exposure_time;
int iso_speed;
int exposure;
int flash_results;
int rc;
@ -274,6 +275,13 @@ int exynos_exif_attributes_create_params(struct exynos_camera *exynos_camera,
exif_attributes->iso_speed_rating = iso_speed;
rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_EXIF_FLASH,
&flash_results);
if (rc < 0)
ALOGE("%s: g ctrl failed!", __func__);
exif_attributes->flash = flash_results;
rc = exynos_v4l2_g_ctrl(exynos_camera, 0, V4L2_CID_CAMERA_EXIF_BV,
(int *) &bv);
if (rc < 0) {
@ -330,11 +338,6 @@ bv_ioctl:
break;
}
if (exynos_camera->flash_mode == FLASH_MODE_BASE)
exif_attributes->flash = EXIF_DEF_FLASH;
else
exif_attributes->flash = exynos_camera->flash_mode;
if (exynos_camera->whitebalance == WHITE_BALANCE_AUTO ||
exynos_camera->whitebalance == WHITE_BALANCE_BASE)
exif_attributes->white_balance = EXIF_WB_AUTO;
@ -394,7 +397,7 @@ int exynos_exif_write_data(void *exif_data, unsigned short tag,
*offset += count * length;
} else {
memcpy(pointer, data, count * length);
pointer += count * length;
pointer += 4;
}
size = (int) pointer - (int) exif_data;
@ -412,7 +415,7 @@ int exynos_exif_create(struct exynos_camera *exynos_camera,
unsigned char exif_marker[] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 };
unsigned char tiff_marker[] = { 0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00 };
unsigned char user_comment_code[] = { 0x00, 0x00, 0x00, 0x49, 0x49, 0x43, 0x53, 0x41 };
unsigned char user_comment_code[] = { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 };
unsigned char exif_ascii_prefix[] = { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 };
camera_memory_t *exif_data_memory;
@ -553,7 +556,7 @@ int exynos_exif_create(struct exynos_camera *exynos_camera,
pointer += count;
count = exynos_exif_write_data(pointer, EXIF_TAG_EXIF_VERSION,
EXIF_TYPE_UNDEFINED, 1, NULL, NULL, &exif_attributes->exif_version, sizeof(exif_attributes->exif_version));
EXIF_TYPE_UNDEFINED, 4, NULL, NULL, &exif_attributes->exif_version, sizeof(char));
pointer += count;
count = exynos_exif_write_data(pointer, EXIF_TAG_DATE_TIME_ORG,
@ -617,15 +620,15 @@ int exynos_exif_create(struct exynos_camera *exynos_camera,
pointer += count;
count = exynos_exif_write_data(pointer, EXIF_TAG_EXPOSURE_MODE,
EXIF_TYPE_LONG, 1, NULL, NULL, &exif_attributes->exposure_mode, sizeof(exif_attributes->exposure_mode));
EXIF_TYPE_SHORT, 1, NULL, NULL, &exif_attributes->exposure_mode, sizeof(exif_attributes->exposure_mode));
pointer += count;
count = exynos_exif_write_data(pointer, EXIF_TAG_WHITE_BALANCE,
EXIF_TYPE_LONG, 1, NULL, NULL, &exif_attributes->white_balance, sizeof(exif_attributes->white_balance));
EXIF_TYPE_SHORT, 1, NULL, NULL, &exif_attributes->white_balance, sizeof(exif_attributes->white_balance));
pointer += count;
count = exynos_exif_write_data(pointer, EXIF_TAG_SCENCE_CAPTURE_TYPE,
EXIF_TYPE_LONG, 1, NULL, NULL, &exif_attributes->scene_capture_type, sizeof(exif_attributes->scene_capture_type));
EXIF_TYPE_SHORT, 1, NULL, NULL, &exif_attributes->scene_capture_type, sizeof(exif_attributes->scene_capture_type));
pointer += count;
value = 0;
@ -651,11 +654,11 @@ int exynos_exif_create(struct exynos_camera *exynos_camera,
offset += NUM_SIZE + value * IFD_SIZE + OFFSET_SIZE;
count = exynos_exif_write_data(pointer, EXIF_TAG_GPS_VERSION_ID,
EXIF_TYPE_LONG, 4, NULL, NULL, &exif_attributes->gps_version_id, 1);
EXIF_TYPE_BYTE, 4, NULL, NULL, &exif_attributes->gps_version_id, sizeof(char));
pointer += count;
count = exynos_exif_write_data(pointer, EXIF_TAG_GPS_LATITUDE_REF,
EXIF_TYPE_ASCII, 2, NULL, NULL, &exif_attributes->gps_latitude_ref, 1);
EXIF_TYPE_ASCII, 2, NULL, NULL, &exif_attributes->gps_latitude_ref, sizeof(char));
pointer += count;
count = exynos_exif_write_data(pointer, EXIF_TAG_GPS_LATITUDE,
@ -663,14 +666,15 @@ int exynos_exif_create(struct exynos_camera *exynos_camera,
pointer += count;
count = exynos_exif_write_data(pointer, EXIF_TAG_GPS_LONGITUDE_REF,
EXIF_TYPE_ASCII, 2, NULL, NULL, &exif_attributes->gps_longitude_ref, 1);
EXIF_TYPE_ASCII, 2, NULL, NULL, &exif_attributes->gps_longitude_ref, sizeof(char));
pointer += count;
count = exynos_exif_write_data(pointer, EXIF_TAG_GPS_LONGITUDE,
EXIF_TYPE_RATIONAL, 3, &offset, exif_ifd_start, &exif_attributes->gps_longitude, sizeof(exif_attributes->gps_longitude[0]));
pointer += count;
count = exynos_exif_write_data(pointer, EXIF_TAG_GPS_ALTITUDE_REF,
EXIF_TYPE_BYTE, 1, NULL, NULL, &exif_attributes->gps_altitude_ref, 1);
EXIF_TYPE_BYTE, 1, NULL, NULL, &exif_attributes->gps_altitude_ref, sizeof(char));
pointer += count;
count = exynos_exif_write_data(pointer, EXIF_TAG_GPS_ALTITUDE,
@ -690,7 +694,7 @@ int exynos_exif_create(struct exynos_camera *exynos_camera,
memcpy((void *) ((int) data + (int) sizeof(exif_ascii_prefix)), exif_attributes->gps_processing_method, value);
count = exynos_exif_write_data(pointer, EXIF_TAG_GPS_PROCESSING_METHOD,
EXIF_TYPE_UNDEFINED, value + sizeof(exif_ascii_prefix), &offset, exif_ifd_start, data, 1);
EXIF_TYPE_UNDEFINED, value + sizeof(exif_ascii_prefix), &offset, exif_ifd_start, data, sizeof(char));
pointer += count;
free(data);
@ -729,7 +733,7 @@ int exynos_exif_create(struct exynos_camera *exynos_camera,
pointer += count;
count = exynos_exif_write_data(pointer, EXIF_TAG_COMPRESSION_SCHEME,
EXIF_TYPE_LONG, 1, NULL, NULL, &exif_attributes->compression_scheme, sizeof(exif_attributes->compression_scheme));
EXIF_TYPE_SHORT, 1, NULL, NULL, &exif_attributes->compression_scheme, sizeof(exif_attributes->compression_scheme));
pointer += count;
count = exynos_exif_write_data(pointer, EXIF_TAG_ORIENTATION,