Skip to content

Commit

Permalink
feat: add Data#ifds
Browse files Browse the repository at this point in the history
  • Loading branch information
tonytonyjan committed Sep 12, 2017
1 parent 1c8e4e8 commit 648841f
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 7 deletions.
22 changes: 15 additions & 7 deletions ext/exif/data.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ extern VALUE rb_mExif, rb_eNotReadble, rb_eIFDNotFound;
extern const char* exif_entry_to_ivar(ExifEntry* entry);

VALUE rb_cData;

static const char* attrs[] = {"aperture_value", "artist", "battery_level", "bits_per_sample", "brightness_value", "cfa_pattern", "cfa_repeat_pattern_dim", "color_space", "components_configuration", "compressed_bits_per_pixel", "compression", "contrast", "copyright", "custom_rendered", "date_time", "date_time_digitized", "date_time_original", "device_setting_description", "digital_zoom_ratio", "document_name", "exif_ifd_pointer", "exif_version", "exposure_bias_value", "exposure_index", "exposure_mode", "exposure_program", "exposure_time", "file_source", "fill_order", "flash", "flash_energy", "flash_pix_version", "fnumber", "focal_length", "focal_length_in_35mm_film", "focal_plane_resolution_unit", "focal_plane_x_resolution", "focal_plane_y_resolution", "gain_control", "gamma", "gps_altitude", "gps_altitude_ref", "gps_area_information", "gps_date_stamp", "gps_dest_bearing", "gps_dest_bearing_ref", "gps_dest_distance", "gps_dest_distance_ref", "gps_dest_latitude", "gps_dest_latitude_ref", "gps_dest_longitude", "gps_dest_longitude_ref", "gps_differential", "gps_dop", "gps_img_direction", "gps_img_direction_ref", "gps_info_ifd_pointer", "gps_latitude", "gps_latitude_ref", "gps_longitude", "gps_longitude_ref", "gps_map_datum", "gps_measure_mode", "gps_processing_method", "gps_satellites", "gps_speed", "gps_speed_ref", "gps_status", "gps_time_stamp", "gps_track", "gps_track_ref", "gps_version_id", "image_description", "image_length", "image_resources", "image_unique_id", "image_width", "inter_color_profile", "interoperability_ifd_pointer", "interoperability_index", "interoperability_version", "iptc_naa", "iso_speed_ratings", "jpeg_interchange_format", "jpeg_interchange_format_length", "jpeg_proc", "light_source", "make", "maker_note", "max_aperture_value", "metering_mode", "model", "new_cfa_pattern", "new_subfile_type", "oecf", "orientation", "padding", "photometric_interpretation", "pixel_x_dimension", "pixel_y_dimension", "planar_configuration", "primary_chromaticities", "print_image_matching", "reference_black_white", "related_image_file_format", "related_image_length", "related_image_width", "related_sound_file", "resolution_unit", "rows_per_strip", "samples_per_pixel", "saturation", "scene_capture_type", "scene_type", "sensing_method", "sharpness", "shutter_speed_value", "software", "spatial_frequency_response", "spectral_sensitivity", "strip_byte_counts", "strip_offsets", "sub_ifds", "sub_sec_time", "sub_sec_time_digitized", "sub_sec_time_original", "subject_area", "subject_distance", "subject_distance_range", "subject_location", "tiff_ep_standard_id", "time_zone_offset", "transfer_function", "transfer_range", "user_comment", "white_balance", "white_point", "x_resolution", "xml_packet", "xp_author", "xp_comment", "xp_keywords", "xp_subject", "xp_title", "y_resolution", "ycbcr_coefficients", "ycbcr_positioning", "ycbcr_sub_sampling"};
static const char* ifd_name_mapping[] = {"ifd0", "ifd1", "exif", "gps", "interoperability"};
static const char* attr_readers[] = {"ifds", "aperture_value", "artist", "battery_level", "bits_per_sample", "brightness_value", "cfa_pattern", "cfa_repeat_pattern_dim", "color_space", "components_configuration", "compressed_bits_per_pixel", "compression", "contrast", "copyright", "custom_rendered", "date_time", "date_time_digitized", "date_time_original", "device_setting_description", "digital_zoom_ratio", "document_name", "exif_ifd_pointer", "exif_version", "exposure_bias_value", "exposure_index", "exposure_mode", "exposure_program", "exposure_time", "file_source", "fill_order", "flash", "flash_energy", "flash_pix_version", "fnumber", "focal_length", "focal_length_in_35mm_film", "focal_plane_resolution_unit", "focal_plane_x_resolution", "focal_plane_y_resolution", "gain_control", "gamma", "gps_altitude", "gps_altitude_ref", "gps_area_information", "gps_date_stamp", "gps_dest_bearing", "gps_dest_bearing_ref", "gps_dest_distance", "gps_dest_distance_ref", "gps_dest_latitude", "gps_dest_latitude_ref", "gps_dest_longitude", "gps_dest_longitude_ref", "gps_differential", "gps_dop", "gps_img_direction", "gps_img_direction_ref", "gps_info_ifd_pointer", "gps_latitude", "gps_latitude_ref", "gps_longitude", "gps_longitude_ref", "gps_map_datum", "gps_measure_mode", "gps_processing_method", "gps_satellites", "gps_speed", "gps_speed_ref", "gps_status", "gps_time_stamp", "gps_track", "gps_track_ref", "gps_version_id", "image_description", "image_length", "image_resources", "image_unique_id", "image_width", "inter_color_profile", "interoperability_ifd_pointer", "interoperability_index", "interoperability_version", "iptc_naa", "iso_speed_ratings", "jpeg_interchange_format", "jpeg_interchange_format_length", "jpeg_proc", "light_source", "make", "maker_note", "max_aperture_value", "metering_mode", "model", "new_cfa_pattern", "new_subfile_type", "oecf", "orientation", "padding", "photometric_interpretation", "pixel_x_dimension", "pixel_y_dimension", "planar_configuration", "primary_chromaticities", "print_image_matching", "reference_black_white", "related_image_file_format", "related_image_length", "related_image_width", "related_sound_file", "resolution_unit", "rows_per_strip", "samples_per_pixel", "saturation", "scene_capture_type", "scene_type", "sensing_method", "sharpness", "shutter_speed_value", "software", "spatial_frequency_response", "spectral_sensitivity", "strip_byte_counts", "strip_offsets", "sub_ifds", "sub_sec_time", "sub_sec_time_digitized", "sub_sec_time_original", "subject_area", "subject_distance", "subject_distance_range", "subject_location", "tiff_ep_standard_id", "time_zone_offset", "transfer_function", "transfer_range", "user_comment", "white_balance", "white_point", "x_resolution", "xml_packet", "xp_author", "xp_comment", "xp_keywords", "xp_subject", "xp_title", "y_resolution", "ycbcr_coefficients", "ycbcr_positioning", "ycbcr_sub_sampling"};

static VALUE new(VALUE self, VALUE input);
static VALUE dump(VALUE self);
Expand All @@ -24,9 +24,8 @@ void init_data(){
int length;

rb_cData = rb_define_class_under(rb_mExif, "Data", rb_cObject);
length = sizeof(attrs) / sizeof(char*);

for(int i = 0; i < length; ++i) rb_define_attr(rb_cData, attrs[i], 1, 0);
length = sizeof(attr_readers) / sizeof(char*);
for(int i = 0; i < length; ++i) rb_define_attr(rb_cData, attr_readers[i], 1, 0);
rb_define_singleton_method(rb_cData, "new", new, 1);
rb_define_method(rb_cData, "dump", dump, 0);
}
Expand All @@ -52,7 +51,9 @@ VALUE new(VALUE self, VALUE input){
exif_loader_unref (loader);
if(!ed) rb_raise(rb_eNotReadble, "File not readable or no EXIF data in file.");


VALUE rb_data = Data_Wrap_Struct(self, NULL, exif_data_free, ed);
rb_iv_set(rb_data, "@ifds", rb_hash_new());
exif_data_foreach_content(ed, each_content, &rb_data);
return rb_data;
}
Expand All @@ -70,7 +71,7 @@ static void each_content(ExifContent *ec, void *self_ptr){

ifd = exif_content_get_ifd(ec);
if(ifd == EXIF_IFD_COUNT) rb_raise(rb_eIFDNotFound, "Con't get IFD.");

rb_hash_aset(rb_iv_get(*(VALUE*)self_ptr, "@ifds"), ID2SYM(rb_intern(ifd_name_mapping[ifd])), rb_hash_new());
exif_content_foreach_entry(ec, each_entry, self_ptr);
}

Expand All @@ -80,7 +81,14 @@ static void each_entry(ExifEntry *entry, void *self_ptr){

ivar_name = exif_entry_to_ivar(entry);
value = exif_entry_to_rb_value(entry);

rb_hash_aset(
rb_hash_aref(
rb_iv_get(*(VALUE*)self_ptr, "@ifds"),
ID2SYM(rb_intern(ifd_name_mapping[exif_entry_get_ifd(entry)]))
),
ID2SYM(rb_intern(ivar_name + 1)),
value
);
rb_iv_set(*(VALUE*)self_ptr, ivar_name, value);
}

Expand Down
82 changes: 82 additions & 0 deletions test/test_exif.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,88 @@

class TestExif < Minitest::Test
module Shared
def test_ifds
assert_equal({
image_width: 4000,
image_length: 2670,
bits_per_sample: [8, 8, 8],
photometric_interpretation: 2,
make: 'NIKON CORPORATION',
model: 'NIKON D600',
orientation: 1,
samples_per_pixel: 3,
x_resolution: Rational(300, 1),
y_resolution: Rational(300, 1),
resolution_unit: 2,
software: 'Adobe Photoshop CS6 (Macintosh)',
date_time: '2013:12:08 21:14:11'
}, data.ifds[:ifd0])

assert_equal({
compression: 6,
x_resolution: Rational(72, 1),
y_resolution: Rational(72, 1),
resolution_unit: 2
}, data.ifds[:ifd1])

assert_equal({
exposure_time: Rational(1, 125),
fnumber: Rational(8, 1),
exposure_program: 3,
iso_speed_ratings: 250,
exif_version: '0230',
date_time_original: '2013:09:10 16:31:21',
date_time_digitized: '2013:09:10 16:31:21',
shutter_speed_value: Rational(870723, 125000),
aperture_value: Rational(6, 1),
exposure_bias_value: Rational(-1, 3),
max_aperture_value: Rational(3, 1),
metering_mode: 2,
light_source: 9,
flash: 16,
focal_length: Rational(70, 1),
sub_sec_time_original: '90',
sub_sec_time_digitized: '90',
color_space: 1,
pixel_x_dimension: 4000,
pixel_y_dimension: 2670,
focal_plane_x_resolution: Rational(54886891, 32768),
focal_plane_y_resolution: Rational(54886891, 32768),
focal_plane_resolution_unit: 3,
sensing_method: 2,
file_source: "\x03",
scene_type: "\x01",
new_cfa_pattern: "\x02\x00\x02\x00\x00\x01\x01\x02",
custom_rendered: 0,
exposure_mode: 0,
white_balance: 1,
digital_zoom_ratio: Rational(1, 1),
focal_length_in_35mm_film: 70,
scene_capture_type: 0,
gain_control: 0,
contrast: 0,
saturation: 0,
sharpness: 0,
subject_distance_range: 0,
flash_pix_version: '0100'
}, data.ifds[:exif])

assert_equal({
gps_version_id: [2, 2, 0, 0],
gps_latitude_ref: 'N',
gps_latitude: [Rational(24, 1), Rational(106817, 10000), Rational(0, 1)],
gps_longitude_ref: 'E',
gps_longitude: [Rational(121, 1), Rational(76869, 2500), Rational(0, 1)],
gps_altitude_ref: 0,
gps_altitude: Rational(332, 1),
gps_time_stamp: [Rational(8, 1), Rational(4, 1), Rational(25, 1)],
gps_map_datum: 'WGS-84',
gps_date_stamp: '2013:09:10'
}, data.ifds[:gps])

assert_equal({}, data.ifds[:interoperability])
end

def test_undefined
assert_equal '0230', data.exif_version
assert_equal "\x03", data.file_source
Expand Down

0 comments on commit 648841f

Please sign in to comment.