/** * Updates the sensor by reading the current value into it */ static void update(CAMERA_STATE *camera, struct sensor *sensor) { if (!sensor->enabled) return; struct state *state = (struct state *) sensor; if (!state->loader) state->loader = exif_loader_new(); exif_loader_reset(state->loader); exif_loader_write(state->loader, camera->imagedata.buffer, camera->imagedata.pos); ExifData *data = exif_loader_get_data(state->loader); ExifByteOrder bo = exif_data_get_byte_order(data); int valid = get_shutter_speed(data, bo, &state->shutter_speed); if (valid) valid = get_aperture(data, bo, &state->aperture); if (valid) valid = getDouble(data, bo, EXIF_TAG_ISO_SPEED_RATINGS, &state->iso); exif_data_free(data); if (valid) { // Calculate the light level state->light_level = (2.0 * log(state->aperture) - log(state->shutter_speed) - log(state->iso / 100.0)) / log(2.0); // Update the sensor sensor_log(camera, &state->sensor, (int) (state->light_level * 1000), "Lvl %.1f", state->light_level); } }
static void exif_loader_free (ExifLoader *loader) { ExifMem *mem; if (!loader) return; mem = loader->mem; exif_loader_reset (loader); exif_mem_free (mem, loader); exif_mem_unref (mem); }
unsigned char exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len) { unsigned int i; if (!eld || (len && !buf)) return 0; switch (eld->state) { case EL_EXIF_FOUND: return exif_loader_copy (eld, buf, len); case EL_SKIP_BYTES: if (eld->size > len) { eld->size -= len; return 1; } len -= eld->size; buf += eld->size; eld->size = 0; eld->b_len = 0; switch (eld->data_format) { case EL_DATA_FORMAT_FUJI_RAW: eld->state = EL_READ_SIZE_BYTE_24; break; default: eld->state = EL_READ; break; } break; case EL_READ: default: break; } if (!len) return 1; exif_log (eld->log, EXIF_LOG_CODE_DEBUG, "ExifLoader", "Scanning %i byte(s) of data...", len); /* * First fill the small buffer. Only continue if the buffer * is filled. Note that EXIF data contains at least 12 bytes. */ i = MIN (len, sizeof (eld->b) - eld->b_len); if (i) { memcpy (&eld->b[eld->b_len], buf, i); eld->b_len += i; if (eld->b_len < sizeof (eld->b)) return 1; buf += i; len -= i; } switch (eld->data_format) { case EL_DATA_FORMAT_UNKNOWN: /* Check the small buffer against known formats. */ if (!memcmp (eld->b, "FUJIFILM", 8)) { /* Skip to byte 84. There is another offset there. */ eld->data_format = EL_DATA_FORMAT_FUJI_RAW; eld->size = 84; eld->state = EL_SKIP_BYTES; eld->size = 84; } else if (!memcmp (eld->b + 2, ExifHeader, sizeof (ExifHeader))) { /* Read the size (2 bytes). */ eld->data_format = EL_DATA_FORMAT_EXIF; eld->state = EL_READ_SIZE_BYTE_08; } default: break; } for (i = 0; i < sizeof (eld->b); i++) switch (eld->state) { case EL_EXIF_FOUND: if (!exif_loader_copy (eld, eld->b + i, sizeof (eld->b) - i)) return 0; return exif_loader_copy (eld, buf, len); case EL_SKIP_BYTES: eld->size--; if (!eld->size) eld->state = EL_READ; break; case EL_READ_SIZE_BYTE_24: eld->size |= eld->b[i] << 24; eld->state = EL_READ_SIZE_BYTE_16; break; case EL_READ_SIZE_BYTE_16: eld->size |= eld->b[i] << 16; eld->state = EL_READ_SIZE_BYTE_08; break; case EL_READ_SIZE_BYTE_08: eld->size |= eld->b[i] << 8; eld->state = EL_READ_SIZE_BYTE_00; break; case EL_READ_SIZE_BYTE_00: eld->size |= eld->b[i] << 0; switch (eld->data_format) { case EL_DATA_FORMAT_JPEG: eld->state = EL_SKIP_BYTES; eld->size -= 2; break; case EL_DATA_FORMAT_FUJI_RAW: eld->data_format = EL_DATA_FORMAT_EXIF; eld->state = EL_SKIP_BYTES; eld->size -= 86; break; case EL_DATA_FORMAT_EXIF: eld->state = EL_EXIF_FOUND; break; default: break; } break; default: switch (eld->b[i]) { case JPEG_MARKER_APP1: if (!memcmp (eld->b + i + 3, ExifHeader, MIN((ssize_t)(sizeof(ExifHeader)), MAX(0, ((ssize_t)(sizeof(eld->b))) - ((ssize_t)i) - 3)))) { eld->data_format = EL_DATA_FORMAT_EXIF; } else { eld->data_format = EL_DATA_FORMAT_JPEG; /* Probably JFIF - keep searching for APP1 EXIF*/ } eld->size = 0; eld->state = EL_READ_SIZE_BYTE_08; break; case JPEG_MARKER_DHT: case JPEG_MARKER_DQT: case JPEG_MARKER_APP0: case JPEG_MARKER_APP2: case JPEG_MARKER_APP13: case JPEG_MARKER_COM: eld->data_format = EL_DATA_FORMAT_JPEG; eld->size = 0; eld->state = EL_READ_SIZE_BYTE_08; break; case 0xff: case JPEG_MARKER_SOI: break; default: exif_log (eld->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifLoader", _("The data supplied " "does not seem to contain " "EXIF data.")); exif_loader_reset (eld); return 0; } } /* * If we reach this point, the buffer has not been big enough * to read all data we need. Fill it with new data. */ eld->b_len = 0; return exif_loader_write (eld, buf, len); }