ucw.cz
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
List overview
Download
Gfxprim
February 2015
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
gfxprim@ucw.cz
1 participants
4 discussions
Start a n
N
ew thread
[repo.or.cz] gfxprim.git branch master updated: 1.0.0-rc1-141-g85375ef
by metan
08 Feb '15
08 Feb '15
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project gfxprim.git. The branch, master has been updated via 85375ef6c62a32f40443803cfba409e0b4e56ae5 (commit) via 37c29279ba0395d957597f60325545fba9d4fcf2 (commit) from 254ab1bb2cf59cfef000a55e64837a89e35e4008 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log -----------------------------------------------------------------
http://repo.or.cz/w/gfxprim.git/commit/85375ef6c62a32f40443803cfba409e0b4e5…
commit 85375ef6c62a32f40443803cfba409e0b4e56ae5 Author: Cyril Hrubis <metan(a)ucw.cz> Date: Sun Feb 8 17:50:58 2015 +0100 loaders: Exif: Fix rational loading Arrays are TODO! Signed-off-by: Cyril Hrubis <metan(a)ucw.cz> diff --git a/libs/loaders/GP_Exif.c b/libs/loaders/GP_Exif.c index e11f72e..04b3d85 100644 --- a/libs/loaders/GP_Exif.c +++ b/libs/loaders/GP_Exif.c @@ -186,29 +186,15 @@ add: static int load_rat(GP_IO *io, GP_DataStorage *storage, GP_DataNode *node, const char *id, uint32_t num_comp, uint32_t val) { - (void)io;(void)storage;(void)node;(void)id;(void)num_comp;(void)val; - return GP_DataStorageAddRational(storage, node, id, 0, 0) != NULL; -} - -/* -static int rat_num(void *buf, uint32_t offset, size_t buf_len, int swap) -{ - int ret; + size_t max_comps = GP_MIN(num_comp, 32u); + uint32_t buf[2 * max_comps]; - GET_32(ret, buf, offset, buf_len, swap); - - return ret; -} - -static int rat_den(void *buf, uint32_t offset, size_t buf_len, int swap) -{ - int ret; - - GET_32(ret, buf, offset + 4, buf_len, swap); + if (get_buf(io, val + 6, (void*)buf, num_comp * 8)) + return 1; - return ret; + //TODO: Data Storage needs array + return GP_DataStorageAddRational(storage, node, id, buf[0], buf[1]) != NULL; } -*/ static int load_tag(GP_IO *io, GP_DataStorage *storage, GP_DataNode* node, const struct IFD_tags *taglist, @@ -228,6 +214,7 @@ static int load_tag(GP_IO *io, GP_DataStorage *storage, "expected '%s' in %s block", res->name, IFD_format_name(format), format, IFD_format_name(res->format), taglist->id); + //TODO: Load and convert! } if ((res->num_components != 0) &&
http://repo.or.cz/w/gfxprim.git/commit/37c29279ba0395d957597f60325545fba9d4…
commit 37c29279ba0395d957597f60325545fba9d4fcf2 Author: Cyril Hrubis <metan(a)ucw.cz> Date: Sun Feb 8 17:42:44 2015 +0100 loaders: Exif: Limit number of subrecords Signed-off-by: Cyril Hrubis <metan(a)ucw.cz> diff --git a/libs/loaders/GP_Exif.c b/libs/loaders/GP_Exif.c index 0cfd591..e11f72e 100644 --- a/libs/loaders/GP_Exif.c +++ b/libs/loaders/GP_Exif.c @@ -324,7 +324,7 @@ static int load_IFD(GP_IO *io, GP_DataStorage *storage, GP_DataNode *node, GP_DEBUG(2, "-- IFD Offset 0x%08x Entries %04u --", IFD_offset, IFD_entries_count); - struct IFD_subrecord subrecs[IFD_entries_count]; + struct IFD_subrecord subrecs[4]; unsigned int subrec_cnt = 0; for (i = 0; i < IFD_entries_count; i++) { @@ -346,6 +346,10 @@ static int load_IFD(GP_IO *io, GP_DataStorage *storage, GP_DataNode *node, case IFD_EXIF_OFFSET: case IFD_GPS_OFFSET: case IFD_INTEROPERABILITY_OFFSET: + if (subrec_cnt >= GP_ARRAY_SIZE(subrecs)) { + GP_WARN("Too much subrecords, skipping one"); + continue; + } subrecs[subrec_cnt].tag = tag; subrecs[subrec_cnt].offset = val; subrec_cnt++; ----------------------------------------------------------------------- Summary of changes: libs/loaders/GP_Exif.c | 33 ++++++++++++--------------------- 1 files changed, 12 insertions(+), 21 deletions(-) repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos(a)gmail.com if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive no reply. -- gfxprim.git ("A simple 2D graphics library with emphasis on correctness and well-defined operation.")
1
0
0
0
[repo.or.cz] gfxprim.git branch master updated: 1.0.0-rc1-139-g254ab1b
by metan
08 Feb '15
08 Feb '15
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project gfxprim.git. The branch, master has been updated via 254ab1bb2cf59cfef000a55e64837a89e35e4008 (commit) via 76e4c74a3e527af4fe39c98123d4475a1ddc2a05 (commit) from 143e4e08779b9dcd3aeed69e2de28c64d9c3d4d0 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log -----------------------------------------------------------------
http://repo.or.cz/w/gfxprim.git/commit/254ab1bb2cf59cfef000a55e64837a89e35e…
commit 254ab1bb2cf59cfef000a55e64837a89e35e4008 Author: Cyril Hrubis <metan(a)ucw.cz> Date: Sun Feb 8 17:00:23 2015 +0100 loaders: DataStorage: Print strings enclosed in '' Signed-off-by: Cyril Hrubis <metan(a)ucw.cz> diff --git a/libs/loaders/GP_DataStorage.c b/libs/loaders/GP_DataStorage.c index cb02425..b453bea 100644 --- a/libs/loaders/GP_DataStorage.c +++ b/libs/loaders/GP_DataStorage.c @@ -411,7 +411,7 @@ static void data_print(const GP_DataNode *node, node->value.rat.num, node->value.rat.den); break; case GP_DATA_STRING: - padd_printf(padd, node->id, id_padd, " : %sn", node->value.str); + padd_printf(padd, node->id, id_padd, " : '%s'n", node->value.str); break; case GP_DATA_DICT: padd_printf(padd, node->id ? node->id : "Data Root", 0, " = {n");
http://repo.or.cz/w/gfxprim.git/commit/76e4c74a3e527af4fe39c98123d4475a1ddc…
commit 76e4c74a3e527af4fe39c98123d4475a1ddc2a05 Author: Cyril Hrubis <metan(a)ucw.cz> Date: Sun Feb 8 15:49:27 2015 +0100 loaders: Exif: Fix subIFD handling, add subIFDs * Add interoperability and GPS sub IFD handling * Add a few more tags Signed-off-by: Cyril Hrubis <metan(a)ucw.cz> diff --git a/libs/loaders/GP_Exif.c b/libs/loaders/GP_Exif.c index 99f49f7..0cfd591 100644 --- a/libs/loaders/GP_Exif.c +++ b/libs/loaders/GP_Exif.c @@ -24,9 +24,9 @@ #include <string.h> #include <errno.h> -#include "core/GP_Debug.h" - -#include "loaders/GP_Exif.h" +#include <core/GP_Common.h> +#include <core/GP_Debug.h> +#include <loaders/GP_Exif.h> enum IFD_formats { /* 1 bytes/components */ @@ -71,133 +71,13 @@ static const char *IFD_format_names[] = { "Double Float", }; -enum IFD_tags { - /* Image width and height */ - IFD_IMAGE_WIDTH = 0x0100, - IFD_IMAGE_HEIGHT = 0x0101, - - IFD_BITS_PER_SAMPLE = 0x0102, - - /* TODO: enum of compressions */ - IFD_COMPRESSION = 0x0103, - /* TODO: enum of interpretations */ - IFD_PHOTOMETRIC_INTERPRETATION = 0x0106, - - /* ASCII text no multibyte encoding */ - IFD_IMAGE_DESCRIPTION = 0x010e, - /* Device (camer, scanner, ...) manufacturer */ - IFD_MAKE = 0x010f, - /* Device model */ - IFD_MODEL = 0x0110, - /* Image orientation * - * 1 upper left, 3 lower right, 6 upper right, * - * 8 lower left, other reserved */ - IFD_ORIENTATION = 0x0112, - /* X resolution 72 DPI is default */ - IFD_X_RESOLUTION = 0x011a, - /* Y resolution 72 DPI is default */ - IFD_Y_RESOLUTION = 0x011b, - /* 1 = Chunky, 2 = Planar */ - IFD_PLANAR_CONFIGURATION = 0x011c, - /* 1 = No unit, 2 = Inch (default), 3 = Centimeter */ - IFD_RESOLUTION_UNIT = 0x0128, - /* Software string. */ - IFD_SOFTWARE = 0x0131, - /* YYYY:MM:DD HH:MM:SS in 24 hours format */ - IFD_DATE_TIME = 0x0132, - /* White Point */ - IFD_WHITE_POINT = 0x013e, - /* Primary Chromaticies */ - IFD_PRIMARY_CHROMATICIES = 0x013f, - /* YCbCr Coefficients */ - IFD_Y_CB_CR_COEFFICIENTS = 0x0211, - /* YCbCr Positioning */ - IFD_Y_CB_CR_POSITIONING = 0x0213, - /* Reference Black White */ - IFD_REFERENCE_BLACK_WHITE = 0x0214, - /* Copyright */ - IFD_COPYRIGHT = 0x8298, - /* Exif SubIFD Offset */ - IFD_EXIF_OFFSET = 0x8769, - - /* TAGs from Exif SubIFD */ - IFD_EXPOSURE_TIME = 0x829a, - /* Actual F-Number of lens when image was taken */ - IFD_F_NUMBER = 0x829d, - /* 1 manual, 2 normal, 3 aperture priority, 4 shutter priority, * - * 5 creative (slow), 6 action (high-speed), 7 portrait mode, * - * 8 landscape mode */ - IFD_EXPOSURE_PROGRAM = 0x8822, - /* CCD sensitivity */ - IFD_ISO_SPEED_RATINGS = 0x8827, - /* ASCII 4 byte Exif version */ - IFD_EXIF_VERSION = 0x9000, - /* Original time should not be modified by user program */ - IFD_DATE_TIME_ORIGINAL = 0x9003, - IFD_DATE_TIME_DIGITIZED = 0x9004, - /* Undefined commonly 0x00, 0x01, 0x02, 0x03 */ - IFD_COMPONENT_CONFIGURATION = 0x9101, - /* Average compression ration */ - IFD_COMPRESSED_BITS_PER_PIXEL = 0x9102, - /* Shutter speed as 1 / (2 ^ val) */ - IFD_SHUTTER_SPEED_VALUE = 0x9201, - /* Aperture to convert to F-Number do 1.4142 ^ val */ - IFD_APERTURE_VALUE = 0x9202, - /* Brightness in EV */ - IFD_BRIGHTNESS_VALUE = 0x9203, - /* Exposure bias in EV */ - IFD_EXPOSURE_BIAS_VALUE = 0x9204, - /* Max Aperture in the same format as IFD_APERTURE_VALUE */ - IFD_MAX_APERTURE_VALUE = 0x9205, - /* Distance to focus point in meters */ - IFD_SUBJECT_DISTANCE = 0x9206, - /* Exposure metering method, 1 average, 2 center weighted average, * - * 3 spot, 4 multi-spot, 5 multi-segment */ - IFD_METERING_MODE = 0x9207, - /* White balance 0 auto, 1 daylight, 2 flourescent, 3 tungsten, 10 flash */ - IFD_LIGHT_SOURCE = 0x9208, - /* 0 off, 1 on */ - IFD_FLASH = 0x9209, - /* Focal length in milimeters */ - IFD_FOCAL_LENGTH = 0x920a, - /* Maker note, undefined may be IFD block */ - IFD_MAKER_NOTE = 0x927c, - /* Comment */ - IFD_USER_COMMENT = 0x9286, - - /* Stores FlashPix version, undefined, may be four ASCII numbers */ - IFD_FLASH_PIX_VERSION = 0xa000, - /* Unknown may be 1 */ - IFD_COLOR_SPACE = 0xa001, - /* Exif Image Width and Height */ - IFD_EXIF_IMAGE_WIDTH = 0xa002, - IFD_EXIF_IMAGE_HEIGHT = 0xa003, - /* May store related audio filename */ - IFD_RELATED_SOUND_FILE = 0xa004, - /* */ - IFD_FOCAL_PLANE_X_RESOLUTION = 0xa20e, - IFD_FOCAL_PLANE_Y_RESOLUTION = 0xa20f, - /* 1 = No unit, 2 = Inch (default), 3 = Centimeter */ - IFD_FOCAL_PLANE_RESOLUTION_UNIT = 0xa210, - /* TODO: enum of sensing methods */ - IFD_SENSING_METHOD = 0xa217, - IFD_FILE_SOURCE = 0xa300, - IFD_SCENE_TYPE = 0xa301, - /* 0 = Normal, 1 = Custom */ - IFD_CUSTOM_RENDERER = 0xa401, - /* 0 = Auto, 1 = Manual, 2 = Auto bracket */ - IFD_EXPOSURE_MODE = 0xa402, - /* 0 = Auto, 1 = Manual */ - IFD_WHITE_BALANCE = 0xa403, - /* 0 = Standard, 1 = Landscape, 2 = Portrait, 3 = Night Scene */ - IFD_SCENE_CAPTURE_TYPE = 0xa406, - /* 0 = Normal, 1 = Soft, 2 = Hard */ - IFD_CONTRAST = 0xa408, - /* 0 = Normal, 1 = Low Saturation, 2 = Hight Saturation */ - IFD_SATURATION = 0xa409, - /* 0 = Normal, 1 = Sort, 2 = Hard */ - IFD_SHARPNESS = 0xa40a, -}; +static const char *IFD_format_name(uint16_t format) +{ + if (format == 0 || format > IFD_FORMAT_LAST) + return "Unknown"; + + return IFD_format_names[format - 1]; +} struct IFD_tag { uint16_t tag; @@ -207,120 +87,43 @@ struct IFD_tag { uint32_t num_components; }; -/* These are sorted by tag */ -static const struct IFD_tag IFD_tags[] = { - /* TAGs from IFD0 */ - /* TODO May be LONG */ - {IFD_IMAGE_WIDTH, "Image Width", IFD_UNSIGNED_SHORT, 1}, - {IFD_IMAGE_HEIGHT, "Image Height", IFD_UNSIGNED_SHORT, 1}, - - {IFD_BITS_PER_SAMPLE, "Bits Per Sample", IFD_UNSIGNED_SHORT, 3}, - {IFD_COMPRESSION, "Compression", IFD_UNSIGNED_SHORT, 1}, - {IFD_PHOTOMETRIC_INTERPRETATION, "Photometric Interpretation", IFD_UNSIGNED_SHORT, 1}, - - {IFD_IMAGE_DESCRIPTION, "Image Description", IFD_ASCII_STRING, 0}, - {IFD_MAKE, "Make", IFD_ASCII_STRING, 0}, - {IFD_MODEL, "Model", IFD_ASCII_STRING, 0}, - {IFD_ORIENTATION, "Orientation", IFD_UNSIGNED_SHORT, 1}, - {IFD_X_RESOLUTION, "X Resolution", IFD_UNSIGNED_RATIONAL, 1}, - {IFD_Y_RESOLUTION, "Y Resolution", IFD_UNSIGNED_RATIONAL, 1}, - {IFD_PLANAR_CONFIGURATION, "Planar Configuration", IFD_UNSIGNED_SHORT, 1}, - {IFD_RESOLUTION_UNIT, "Resolution Unit", IFD_UNSIGNED_SHORT, 1}, - {IFD_SOFTWARE, "Software", IFD_ASCII_STRING, 0}, - {IFD_DATE_TIME, "Date Time", IFD_ASCII_STRING, 20}, - {IFD_WHITE_POINT, "White Point", IFD_UNSIGNED_RATIONAL, 2}, - {IFD_PRIMARY_CHROMATICIES, "Primary Chromaticies", IFD_UNSIGNED_RATIONAL, 6}, - {IFD_Y_CB_CR_COEFFICIENTS, "YCbCr Conefficients", IFD_UNSIGNED_RATIONAL, 3}, - {IFD_Y_CB_CR_POSITIONING, "YCbCr Positioning", IFD_UNSIGNED_SHORT, 1}, - {IFD_REFERENCE_BLACK_WHITE, "Reference Black White", IFD_UNSIGNED_RATIONAL, 6}, - {IFD_COPYRIGHT, "Copyright", IFD_ASCII_STRING, 0}, - - /* TAGs from Exif SubIFD */ - {IFD_EXPOSURE_TIME, "Exposure Time", IFD_UNSIGNED_RATIONAL, 1}, - {IFD_F_NUMBER, "F-Number", IFD_UNSIGNED_RATIONAL, 1}, - - /* TAG from IFD0 */ - {IFD_EXIF_OFFSET, "Exif Offset", IFD_UNSIGNED_LONG, 1}, - - /* TAGs from Exif SubIFD */ - {IFD_EXPOSURE_PROGRAM, "Exposure Program", IFD_UNSIGNED_SHORT, 1}, - {IFD_ISO_SPEED_RATINGS, "ISO Speed Ratings", IFD_UNSIGNED_SHORT, 1}, - {IFD_EXIF_VERSION, "Exif Version", IFD_UNDEFINED, 4}, - {IFD_DATE_TIME_ORIGINAL, "Date Time Original", IFD_ASCII_STRING, 20}, - {IFD_DATE_TIME_DIGITIZED, "Date Time Digitized", IFD_ASCII_STRING, 20}, - {IFD_COMPONENT_CONFIGURATION, "Component Configuration", IFD_UNDEFINED, 0}, - {IFD_COMPRESSED_BITS_PER_PIXEL, "Compressed Bits Per Pixel", IFD_UNSIGNED_RATIONAL, 1}, - {IFD_SHUTTER_SPEED_VALUE, "Shutter Speed", IFD_SIGNED_RATIONAL, 1}, - {IFD_APERTURE_VALUE, "Aperture", IFD_UNSIGNED_RATIONAL, 1}, - {IFD_BRIGHTNESS_VALUE, "Brightness", IFD_SIGNED_RATIONAL, 1}, - {IFD_EXPOSURE_BIAS_VALUE, "Exposure Bias", IFD_SIGNED_RATIONAL, 1}, - {IFD_MAX_APERTURE_VALUE, "Max Aperture", IFD_UNSIGNED_RATIONAL, 1}, - {IFD_SUBJECT_DISTANCE, "Subject Distance", IFD_SIGNED_RATIONAL, 1}, - {IFD_METERING_MODE, "Metering Mode", IFD_UNSIGNED_SHORT, 1}, - {IFD_LIGHT_SOURCE, "Light Source", IFD_UNSIGNED_SHORT, 1}, - {IFD_FLASH, "Flash", IFD_UNSIGNED_SHORT, 1}, - {IFD_FOCAL_LENGTH, "Focal Length", IFD_UNSIGNED_RATIONAL, 1}, - {IFD_MAKER_NOTE, "Maker Note", IFD_UNDEFINED, 0}, - {IFD_USER_COMMENT, "User Comment", IFD_UNDEFINED, 0}, - {IFD_FLASH_PIX_VERSION, "Flash Pix Version", IFD_UNDEFINED, 4}, - {IFD_COLOR_SPACE, "Color Space", IFD_UNSIGNED_SHORT, 1}, - /* these two may be short in some cases */ - {IFD_EXIF_IMAGE_WIDTH, "Exif Image Width", IFD_UNSIGNED_LONG, 1}, - {IFD_EXIF_IMAGE_HEIGHT, "Exif Image Height", IFD_UNSIGNED_LONG, 1}, - {IFD_RELATED_SOUND_FILE, "Related Soundfile", IFD_ASCII_STRING, 0}, - {IFD_FOCAL_PLANE_X_RESOLUTION, "Focal Plane X Resolution", IFD_UNSIGNED_RATIONAL, 1}, - {IFD_FOCAL_PLANE_Y_RESOLUTION, "Focal Plane Y Resolution", IFD_UNSIGNED_RATIONAL, 1}, - {IFD_FOCAL_PLANE_RESOLUTION_UNIT, "Focal Plane Resolution Unit", IFD_UNSIGNED_SHORT, 1}, - {IFD_SENSING_METHOD, "Sensing Method", IFD_UNSIGNED_SHORT, 1}, - {IFD_FILE_SOURCE, "File Source", IFD_UNDEFINED, 1}, - {IFD_SCENE_TYPE, "Scene Type", IFD_UNDEFINED, 1}, - {IFD_CUSTOM_RENDERER, "Custom Renderer", IFD_UNSIGNED_SHORT, 1}, - {IFD_EXPOSURE_MODE, "Exposure Mode", IFD_UNSIGNED_SHORT, 1}, - {IFD_WHITE_BALANCE, "White Balance", IFD_UNSIGNED_SHORT, 1}, - {IFD_SCENE_CAPTURE_TYPE, "Scene Capture Type", IFD_UNSIGNED_SHORT, 1}, - {IFD_CONTRAST, "Contrast", IFD_UNSIGNED_SHORT, 1}, - {IFD_SATURATION, "Saturation", IFD_UNSIGNED_SHORT, 1}, - {IFD_SHARPNESS, "Sharpness", IFD_UNSIGNED_SHORT, 1}, +struct IFD_tags { + const struct IFD_tag *tags; + unsigned int tag_cnt; + const char *id; }; -static const char *IFD_format_name(uint16_t format) -{ - if (format == 0 || format > IFD_FORMAT_LAST) - return "Unknown"; - - return IFD_format_names[format - 1]; -} - -static const struct IFD_tag *IFD_tag_get(uint16_t tag) +static const struct IFD_tag *IFD_tag_get(const struct IFD_tags *tags, + uint16_t tag) { int left = 0; - int right = sizeof(IFD_tags)/sizeof(struct IFD_tag) - 1; + int right = tags->tag_cnt - 1; while (right - left > 1) { int middle = (right + left)/2; - if (IFD_tags[middle].tag == tag) - return &IFD_tags[middle]; + if (tags->tags[middle].tag == tag) + return &tags->tags[middle]; - if (IFD_tags[middle].tag > tag) + if (tags->tags[middle].tag > tag) right = middle; else left = middle; } - if (IFD_tags[left].tag == tag) - return &IFD_tags[left]; + if (tags->tags[left].tag == tag) + return &tags->tags[left]; - if (IFD_tags[right].tag == tag) - return &IFD_tags[right]; + if (tags->tags[right].tag == tag) + return &tags->tags[right]; return NULL; } -static const char *IFD_tag_name(uint16_t tag) +static const char *IFD_tag_name(const struct IFD_tags *taglist, uint16_t tag) { - const struct IFD_tag *res = IFD_tag_get(tag); + const struct IFD_tag *res = IFD_tag_get(taglist, tag); if (res == NULL) return "Unknown"; @@ -328,6 +131,9 @@ static const char *IFD_tag_name(uint16_t tag) return res->name; } +#include "GP_ExifGPS.h" +#include "GP_Exif.h" + static int get_buf(GP_IO *io, off_t offset, char *buf, size_t len) { off_t off; @@ -380,8 +186,7 @@ add: static int load_rat(GP_IO *io, GP_DataStorage *storage, GP_DataNode *node, const char *id, uint32_t num_comp, uint32_t val) { - uint32_t buf[2]; - + (void)io;(void)storage;(void)node;(void)id;(void)num_comp;(void)val; return GP_DataStorageAddRational(storage, node, id, 0, 0) != NULL; } @@ -406,29 +211,29 @@ static int rat_den(void *buf, uint32_t offset, size_t buf_len, int swap) */ static int load_tag(GP_IO *io, GP_DataStorage *storage, - GP_DataNode* node, int endian, - uint16_t tag, uint16_t format, + GP_DataNode* node, const struct IFD_tags *taglist, + int endian, uint16_t tag, uint16_t format, uint32_t num_comp, uint32_t val) { - const struct IFD_tag *res = IFD_tag_get(tag); + const struct IFD_tag *res = IFD_tag_get(taglist, tag); if (res == NULL) { - GP_TODO("Skipping unknown IFD tag 0x%02x format %s", - tag, IFD_format_name(format)); + GP_TODO("Skipping unknown IFD tag 0x%02x %s cnt %u in %s block", + tag, IFD_format_name(format), num_comp, taglist->id); return 0; } if (res->format != format) { GP_WARN("Unexpected tag '%s' format '%s' (0x%02x) " - "expected '%s'", res->name, + "expected '%s' in %s block", res->name, IFD_format_name(format), format, - IFD_format_name(res->format)); + IFD_format_name(res->format), taglist->id); } if ((res->num_components != 0) && (res->num_components != num_comp)) { - GP_WARN("Unexpected tag '%s' num_components %u expected %u", - res->name, num_comp, res->num_components); + GP_WARN("Unexpected '%s' num_components %u expected %u in %s block", + res->name, num_comp, res->num_components, taglist->id); } switch (format) { @@ -436,7 +241,9 @@ static int load_tag(GP_IO *io, GP_DataStorage *storage, if (load_string(io, storage, node, res->name, num_comp, &val)) return 1; break; - //case IFD_UNSIGNED_LONG: + case IFD_SIGNED_LONG: + case IFD_UNSIGNED_LONG: + case IFD_SIGNED_SHORT: case IFD_UNSIGNED_SHORT: if (num_comp == 1) GP_DataStorageAddInt(storage, node, res->name, val); @@ -448,23 +255,13 @@ static int load_tag(GP_IO *io, GP_DataStorage *storage, case IFD_SIGNED_RATIONAL: if (load_rat(io, storage, node, res->name, num_comp, val)) return 1; - -/* if (num_comp == 1) { - rec.type = GP_DATA_RATIONAL; - rec.value.rat. - GP_MetaDataCreateRat(self, res->name, - rat_num(buf, val, buf_len, swap), - rat_den(buf, val, buf_len, swap)); - } else { - goto unused; - } -*/ break; case IFD_UNDEFINED: switch (res->tag) { case IFD_EXIF_VERSION: case IFD_FLASH_PIX_VERSION: case IFD_MAKER_NOTE: + case IFD_INTEROP_VERSION: if (load_string(io, storage, node, res->name, num_comp, &val)) return 1; break; @@ -482,11 +279,18 @@ static int load_tag(GP_IO *io, GP_DataStorage *storage, return 0; } +struct IFD_subrecord { + uint16_t tag; + uint32_t offset; +}; + static int load_IFD(GP_IO *io, GP_DataStorage *storage, GP_DataNode *node, - uint32_t IFD_offset, int endian) + const struct IFD_tags *taglist, uint32_t IFD_offset, + int endian) { uint16_t IFD_entries_count; uint16_t i2 = endian == 'I' ? GP_IO_L2 : GP_IO_B2; + unsigned int i; uint16_t IFD_header[] = { GP_IO_IGN | IFD_offset, @@ -494,14 +298,6 @@ static int load_IFD(GP_IO *io, GP_DataStorage *storage, GP_DataNode *node, GP_IO_END, }; - if (GP_IOReadF(io, IFD_header, &IFD_entries_count) != 2) { - GP_DEBUG(1, "Failed to read IFD entries count"); - return 1; - } - - GP_DEBUG(2, "-- IFD Offset 0x%08x Entries 0x%04x --", - IFD_offset, IFD_entries_count); - uint16_t IFD_record_LE[] = { GP_IO_L2, /* Tag */ GP_IO_L2, /* Format */ @@ -518,16 +314,24 @@ static int load_IFD(GP_IO *io, GP_DataStorage *storage, GP_DataNode *node, GP_IO_END, }; - uint16_t *IFD_record = endian == 'I' ? IFD_record_LE : IFD_record_BE; + uint16_t *IFD_rec_head = endian == 'I' ? IFD_record_LE : IFD_record_BE; + + if (GP_IOReadF(io, IFD_header, &IFD_entries_count) != 2) { + GP_DEBUG(1, "Failed to read IFD entries count"); + return 1; + } + + GP_DEBUG(2, "-- IFD Offset 0x%08x Entries %04u --", + IFD_offset, IFD_entries_count); - int i; + struct IFD_subrecord subrecs[IFD_entries_count]; + unsigned int subrec_cnt = 0; for (i = 0; i < IFD_entries_count; i++) { uint16_t tag, format; uint32_t num_comp, val; - off_t cur_off; - if (GP_IOReadF(io, IFD_record, &tag, &format, &num_comp, &val) != 4) { + if (GP_IOReadF(io, IFD_rec_head, &tag, &format, &num_comp, &val) != 4) { GP_DEBUG(1, "Failed to read IFD record"); return 1; } @@ -536,28 +340,55 @@ static int load_IFD(GP_IO *io, GP_DataStorage *storage, GP_DataNode *node, tag, format, num_comp, val); GP_DEBUG(3, "IFD Entry tag '%s' format '%s'", - IFD_tag_name(tag), IFD_format_name(format)); + IFD_tag_name(taglist, tag), IFD_format_name(format)); + + switch (tag) { + case IFD_EXIF_OFFSET: + case IFD_GPS_OFFSET: + case IFD_INTEROPERABILITY_OFFSET: + subrecs[subrec_cnt].tag = tag; + subrecs[subrec_cnt].offset = val; + subrec_cnt++; + break; + default: + load_tag(io, storage, node, taglist, endian, tag, format, num_comp, val); + break; + } + } + for (i = 0; i < subrec_cnt; i++) { + off_t cur_off = GP_IOTell(io); + const struct IFD_tags *tags; + GP_DataNode *new_node; - if (tag == IFD_EXIF_OFFSET) { - cur_off = GP_IOTell(io); + GP_DEBUG(3, "-- Loading sub IFD %s --", + IFD_tag_name(taglist, subrecs[i].tag)); - /* Offset is counted from the II or MM in the Exif header */ - if (val + 6 < cur_off) - GP_DEBUG(1, "Negative offset!"); - else - load_IFD(io, storage, node, val + 6 - cur_off, endian); - } else { - load_tag(io, storage, node, endian, tag, format, num_comp, val); + switch (subrecs[i].tag) { + case IFD_EXIF_OFFSET: + tags = taglist; + new_node = node; + break; + case IFD_GPS_OFFSET: + tags = &IFD_GPS_tags; + new_node = GP_DataStorageAddDict(storage, node, "GPS"); + break; + case IFD_INTEROPERABILITY_OFFSET: + tags = taglist; + new_node = GP_DataStorageAddDict(storage, node, "Interoperability"); + break; + default: + GP_BUG("Invalid tag"); + return 1; } - } -/* - GET_32(IFD_offset, buf, IFD_offset, buf_len, swap); + /* Offset is counted from the II or MM in the Exif header */ + if (subrecs[i].offset + 6 < cur_off) + GP_DEBUG(1, "Negative offset!"); + + load_IFD(io, storage, new_node, tags, subrecs[i].offset + 6 - cur_off, endian); + } - if (IFD_offset != 0x00000000) - load_IFD(self, buf, buf_len, IFD_offset, swap); -*/ return 0; } @@ -605,5 +436,5 @@ int GP_ReadExif(GP_IO *io, GP_DataStorage *storage) GP_DataNode *exif_root = GP_DataStorageAddDict(storage, NULL, "Exif"); /* The offset starts from the II or MM */ - return load_IFD(io, storage, exif_root, IFD_offset - 8, b1); + return load_IFD(io, storage, exif_root, &IFD_EXIF_tags, IFD_offset - 8, b1); } diff --git a/libs/loaders/GP_Exif.c b/libs/loaders/GP_Exif.h similarity index 53% copy from libs/loaders/GP_Exif.c copy to libs/loaders/GP_Exif.h index 99f49f7..2e09413 100644 --- a/libs/loaders/GP_Exif.c +++ b/libs/loaders/GP_Exif.h @@ -20,64 +20,15 @@ * * *****************************************************************************/ -#include <stdlib.h> -#include <string.h> -#include <errno.h> +enum IFD_EXIF_tags { + /* Stored in interop IFD */ + IFD_INTEROP_VERSION = 0x2, -#include "core/GP_Debug.h" - -#include "loaders/GP_Exif.h" - -enum IFD_formats { - /* 1 bytes/components */ - IFD_UNSIGNED_BYTE = 0x01, - /* 1 bytes/components */ - IFD_ASCII_STRING = 0x02, - /* 2 bytes/components */ - IFD_UNSIGNED_SHORT = 0x03, - /* 4 bytes/components */ - IFD_UNSIGNED_LONG = 0x04, - /* 8 bytes/components */ - IFD_UNSIGNED_RATIONAL = 0x05, - /* 1 bytes/components */ - IFD_SIGNED_BYTE = 0x06, - /* 1 bytes/components */ - IFD_UNDEFINED = 0x07, - /* 2 bytes/components */ - IFD_SIGNED_SHORT = 0x08, - /* 4 bytes/components */ - IFD_SIGNED_LONG = 0x09, - /* 8 bytes/components */ - IFD_SIGNED_RATIONAL = 0x0a, - /* 4 bytes/components */ - IFD_SINGLE_FLOAT = 0x0b, - /* 8 bytes/components */ - IFD_SINGLE_DOUBLE = 0x0c, - IFD_FORMAT_LAST = IFD_SINGLE_DOUBLE, -}; - -static const char *IFD_format_names[] = { - "Unsigned Byte", - "ASCII String", - "Unsigned Short", - "Unsigned Long", - "Unsigned Rational", - "Signed Byte", - "Undefined", - "Signed Short", - "Signed Long", - "Signed Rational", - "Single Float", - "Double Float", -}; - -enum IFD_tags { /* Image width and height */ IFD_IMAGE_WIDTH = 0x0100, IFD_IMAGE_HEIGHT = 0x0101, IFD_BITS_PER_SAMPLE = 0x0102, - /* TODO: enum of compressions */ IFD_COMPRESSION = 0x0103, /* TODO: enum of interpretations */ @@ -105,6 +56,8 @@ enum IFD_tags { IFD_SOFTWARE = 0x0131, /* YYYY:MM:DD HH:MM:SS in 24 hours format */ IFD_DATE_TIME = 0x0132, + /* Artist */ + IFD_ARTIST = 0x013b, /* White Point */ IFD_WHITE_POINT = 0x013e, /* Primary Chromaticies */ @@ -115,19 +68,22 @@ enum IFD_tags { IFD_Y_CB_CR_POSITIONING = 0x0213, /* Reference Black White */ IFD_REFERENCE_BLACK_WHITE = 0x0214, + /* Stored in interop IFD */ + IFD_RELATED_IMAGE_WIDTH = 0x1001, + IFD_RELATED_IMAGE_HEIGHT = 0x1002, /* Copyright */ IFD_COPYRIGHT = 0x8298, - /* Exif SubIFD Offset */ - IFD_EXIF_OFFSET = 0x8769, - - /* TAGs from Exif SubIFD */ IFD_EXPOSURE_TIME = 0x829a, /* Actual F-Number of lens when image was taken */ IFD_F_NUMBER = 0x829d, + /* Exif SubIFD Offset */ + IFD_EXIF_OFFSET = 0x8769, /* 1 manual, 2 normal, 3 aperture priority, 4 shutter priority, * * 5 creative (slow), 6 action (high-speed), 7 portrait mode, * * 8 landscape mode */ IFD_EXPOSURE_PROGRAM = 0x8822, + /* Offset to GPS data */ + IFD_GPS_OFFSET = 0x8825, /* CCD sensitivity */ IFD_ISO_SPEED_RATINGS = 0x8827, /* ASCII 4 byte Exif version */ @@ -165,6 +121,11 @@ enum IFD_tags { /* Comment */ IFD_USER_COMMENT = 0x9286, + /* Subsec time in addition to IFD_DATE_TIME* */ + IFD_SUBSEC_TIME = 0x9290, + IFD_SUBSEC_TIME_ORIGINAL = 0x9291, + IFD_SUBSEC_TIME_DIGITIZED = 0x9292, + /* Stores FlashPix version, undefined, may be four ASCII numbers */ IFD_FLASH_PIX_VERSION = 0xa000, /* Unknown may be 1 */ @@ -174,6 +135,8 @@ enum IFD_tags { IFD_EXIF_IMAGE_HEIGHT = 0xa003, /* May store related audio filename */ IFD_RELATED_SOUND_FILE = 0xa004, + /* Offset to Interoperability SubIFD */ + IFD_INTEROPERABILITY_OFFSET = 0xa005, /* */ IFD_FOCAL_PLANE_X_RESOLUTION = 0xa20e, IFD_FOCAL_PLANE_Y_RESOLUTION = 0xa20f, @@ -183,33 +146,47 @@ enum IFD_tags { IFD_SENSING_METHOD = 0xa217, IFD_FILE_SOURCE = 0xa300, IFD_SCENE_TYPE = 0xa301, + /* Color Filter Array pattern */ + IFD_CFA_PATTERN = 0xa302, /* 0 = Normal, 1 = Custom */ IFD_CUSTOM_RENDERER = 0xa401, /* 0 = Auto, 1 = Manual, 2 = Auto bracket */ IFD_EXPOSURE_MODE = 0xa402, /* 0 = Auto, 1 = Manual */ IFD_WHITE_BALANCE = 0xa403, + /* 0 == Not Used */ + IFD_DIGITAL_ZOOM_RATIO = 0xa404, + /* Equivalent lenght assuming 35mm camera */ + IFD_FOCAL_LENGTH_IN_35_MM_FILM = 0xa405, /* 0 = Standard, 1 = Landscape, 2 = Portrait, 3 = Night Scene */ IFD_SCENE_CAPTURE_TYPE = 0xa406, + /* 0 = None, 1 = Low Gain Up, 2 = High Gain Up, 3 = Low Gain Down, 4 = High Gain Down */ + IFD_GAIN_CONTROL = 0xa407, /* 0 = Normal, 1 = Soft, 2 = Hard */ IFD_CONTRAST = 0xa408, /* 0 = Normal, 1 = Low Saturation, 2 = Hight Saturation */ IFD_SATURATION = 0xa409, /* 0 = Normal, 1 = Sort, 2 = Hard */ IFD_SHARPNESS = 0xa40a, + /* 0 = Unknown, 1 = Macro, 2 = Close View, 3 = Distant View */ + IFD_SUBJECT_DISTANCE_RANGE = 0xa40c, + /* Unique in hex string */ + IFD_IMAGE_UNIQUE_ID = 0xa420, + + /* ??? */ + IFD_PRINT_IM = 0xc4a5, + + /* Padding */ + IFD_PADDING = 0xea1c, + /* Microsoft's ill-conceived maker note offset difference */ + IFD_OFFSET_SCHEMA = 0xea1d, }; -struct IFD_tag { - uint16_t tag; - const char *name; - uint16_t format; - /* 0 == not defined */ - uint32_t num_components; -}; +/* MUST SORTED BY TAG */ +static const struct IFD_tag IFD_EXIF_taglist[] = { + /* Stored in interop IFD */ + {IFD_INTEROP_VERSION, "Interop Version", IFD_UNDEFINED, 4}, -/* These are sorted by tag */ -static const struct IFD_tag IFD_tags[] = { - /* TAGs from IFD0 */ /* TODO May be LONG */ {IFD_IMAGE_WIDTH, "Image Width", IFD_UNSIGNED_SHORT, 1}, {IFD_IMAGE_HEIGHT, "Image Height", IFD_UNSIGNED_SHORT, 1}, @@ -228,22 +205,25 @@ static const struct IFD_tag IFD_tags[] = { {IFD_RESOLUTION_UNIT, "Resolution Unit", IFD_UNSIGNED_SHORT, 1}, {IFD_SOFTWARE, "Software", IFD_ASCII_STRING, 0}, {IFD_DATE_TIME, "Date Time", IFD_ASCII_STRING, 20}, + {IFD_ARTIST, "Artist", IFD_ASCII_STRING, 0}, {IFD_WHITE_POINT, "White Point", IFD_UNSIGNED_RATIONAL, 2}, {IFD_PRIMARY_CHROMATICIES, "Primary Chromaticies", IFD_UNSIGNED_RATIONAL, 6}, {IFD_Y_CB_CR_COEFFICIENTS, "YCbCr Conefficients", IFD_UNSIGNED_RATIONAL, 3}, {IFD_Y_CB_CR_POSITIONING, "YCbCr Positioning", IFD_UNSIGNED_SHORT, 1}, {IFD_REFERENCE_BLACK_WHITE, "Reference Black White", IFD_UNSIGNED_RATIONAL, 6}, + + /* Stored in interop IFD */ + {IFD_RELATED_IMAGE_WIDTH, "Related Image Width", IFD_UNSIGNED_LONG, 1}, + {IFD_RELATED_IMAGE_HEIGHT, "Related Image Height", IFD_UNSIGNED_LONG, 1}, + {IFD_COPYRIGHT, "Copyright", IFD_ASCII_STRING, 0}, /* TAGs from Exif SubIFD */ {IFD_EXPOSURE_TIME, "Exposure Time", IFD_UNSIGNED_RATIONAL, 1}, {IFD_F_NUMBER, "F-Number", IFD_UNSIGNED_RATIONAL, 1}, - - /* TAG from IFD0 */ {IFD_EXIF_OFFSET, "Exif Offset", IFD_UNSIGNED_LONG, 1}, - - /* TAGs from Exif SubIFD */ {IFD_EXPOSURE_PROGRAM, "Exposure Program", IFD_UNSIGNED_SHORT, 1}, + {IFD_GPS_OFFSET, "GPS Offset", IFD_UNSIGNED_LONG, 1}, {IFD_ISO_SPEED_RATINGS, "ISO Speed Ratings", IFD_UNSIGNED_SHORT, 1}, {IFD_EXIF_VERSION, "Exif Version", IFD_UNDEFINED, 4}, {IFD_DATE_TIME_ORIGINAL, "Date Time Original", IFD_ASCII_STRING, 20}, @@ -262,348 +242,42 @@ static const struct IFD_tag IFD_tags[] = { {IFD_FOCAL_LENGTH, "Focal Length", IFD_UNSIGNED_RATIONAL, 1}, {IFD_MAKER_NOTE, "Maker Note", IFD_UNDEFINED, 0}, {IFD_USER_COMMENT, "User Comment", IFD_UNDEFINED, 0}, + {IFD_SUBSEC_TIME, "Subsec Time", IFD_ASCII_STRING, 0}, + {IFD_SUBSEC_TIME_ORIGINAL, "Subsec Time Original", IFD_ASCII_STRING, 0}, + {IFD_SUBSEC_TIME_DIGITIZED, "Subsec Time Digitized", IFD_ASCII_STRING, 0}, {IFD_FLASH_PIX_VERSION, "Flash Pix Version", IFD_UNDEFINED, 4}, {IFD_COLOR_SPACE, "Color Space", IFD_UNSIGNED_SHORT, 1}, /* these two may be short in some cases */ {IFD_EXIF_IMAGE_WIDTH, "Exif Image Width", IFD_UNSIGNED_LONG, 1}, {IFD_EXIF_IMAGE_HEIGHT, "Exif Image Height", IFD_UNSIGNED_LONG, 1}, {IFD_RELATED_SOUND_FILE, "Related Soundfile", IFD_ASCII_STRING, 0}, + {IFD_INTEROPERABILITY_OFFSET, "Interoperability Offset", IFD_UNSIGNED_LONG, 1}, {IFD_FOCAL_PLANE_X_RESOLUTION, "Focal Plane X Resolution", IFD_UNSIGNED_RATIONAL, 1}, {IFD_FOCAL_PLANE_Y_RESOLUTION, "Focal Plane Y Resolution", IFD_UNSIGNED_RATIONAL, 1}, {IFD_FOCAL_PLANE_RESOLUTION_UNIT, "Focal Plane Resolution Unit", IFD_UNSIGNED_SHORT, 1}, {IFD_SENSING_METHOD, "Sensing Method", IFD_UNSIGNED_SHORT, 1}, {IFD_FILE_SOURCE, "File Source", IFD_UNDEFINED, 1}, {IFD_SCENE_TYPE, "Scene Type", IFD_UNDEFINED, 1}, + {IFD_CFA_PATTERN, "CFA Pattern", IFD_UNDEFINED, 0}, {IFD_CUSTOM_RENDERER, "Custom Renderer", IFD_UNSIGNED_SHORT, 1}, {IFD_EXPOSURE_MODE, "Exposure Mode", IFD_UNSIGNED_SHORT, 1}, {IFD_WHITE_BALANCE, "White Balance", IFD_UNSIGNED_SHORT, 1}, + {IFD_DIGITAL_ZOOM_RATIO, "Digital Zoom Ratio", IFD_UNSIGNED_RATIONAL, 1}, + {IFD_FOCAL_LENGTH_IN_35_MM_FILM, "Focal Lenght In 35mm Film", IFD_UNSIGNED_SHORT, 1}, {IFD_SCENE_CAPTURE_TYPE, "Scene Capture Type", IFD_UNSIGNED_SHORT, 1}, + {IFD_GAIN_CONTROL, "Gain Control", IFD_UNSIGNED_SHORT, 1}, {IFD_CONTRAST, "Contrast", IFD_UNSIGNED_SHORT, 1}, {IFD_SATURATION, "Saturation", IFD_UNSIGNED_SHORT, 1}, {IFD_SHARPNESS, "Sharpness", IFD_UNSIGNED_SHORT, 1}, + {IFD_SUBJECT_DISTANCE_RANGE, "Subject Distance Range", IFD_UNSIGNED_SHORT, 1}, + {IFD_IMAGE_UNIQUE_ID, "Image Unique ID", IFD_ASCII_STRING, 33}, + {IFD_PRINT_IM, "Print IM", IFD_UNDEFINED, 0}, + {IFD_PADDING, "Padding", IFD_UNDEFINED, 0}, + {IFD_OFFSET_SCHEMA, "Offset Schema", IFD_SIGNED_LONG, 1}, }; -static const char *IFD_format_name(uint16_t format) -{ - if (format == 0 || format > IFD_FORMAT_LAST) - return "Unknown"; - - return IFD_format_names[format - 1]; -} - -static const struct IFD_tag *IFD_tag_get(uint16_t tag) -{ - int left = 0; - int right = sizeof(IFD_tags)/sizeof(struct IFD_tag) - 1; - - while (right - left > 1) { - int middle = (right + left)/2; - - if (IFD_tags[middle].tag == tag) - return &IFD_tags[middle]; - - - if (IFD_tags[middle].tag > tag) - right = middle; - else - left = middle; - } - - if (IFD_tags[left].tag == tag) - return &IFD_tags[left]; - - if (IFD_tags[right].tag == tag) - return &IFD_tags[right]; - - return NULL; -} - -static const char *IFD_tag_name(uint16_t tag) -{ - const struct IFD_tag *res = IFD_tag_get(tag); - - if (res == NULL) - return "Unknown"; - else - return res->name; -} - -static int get_buf(GP_IO *io, off_t offset, char *buf, size_t len) -{ - off_t off; - - off = GP_IOTell(io); - - if (GP_IOSeek(io, offset, GP_IO_SEEK_SET) == -1) { - GP_WARN("Failed to seek to data"); - return 1; - } - - if (GP_IOFill(io, buf, len)) { - GP_WARN("Failed to read data"); - return 1; - } - - if (GP_IOSeek(io, off, GP_IO_SEEK_SET) == -1) { - GP_WARN("Failed to seek back"); - return 1; - } - - return 0; -} - -static int load_string(GP_IO *io, GP_DataStorage *storage, GP_DataNode *node, - const char *id, uint32_t num_comp, uint32_t *val) -{ - size_t max_len = GP_MIN(num_comp, 1024u); - char buf[max_len]; - - /* Short strings are stored in the value directly */ - if (num_comp <= 4) { - memcpy(buf, val, num_comp); - buf[num_comp > 0 ? num_comp - 1 : num_comp] = 0; - goto add; - } - - /* Longer are stored at offset starting from II or MM */ - if (get_buf(io, *val + 6, buf, max_len)) - return 1; - - buf[max_len - 1] = '0'; - -add: - GP_DEBUG(2, "ASCII String value = '%s'", buf); - - return GP_DataStorageAddString(storage, node, id, buf) != NULL; -} - -static int load_rat(GP_IO *io, GP_DataStorage *storage, GP_DataNode *node, - const char *id, uint32_t num_comp, uint32_t val) -{ - uint32_t buf[2]; - - return GP_DataStorageAddRational(storage, node, id, 0, 0) != NULL; -} - -/* -static int rat_num(void *buf, uint32_t offset, size_t buf_len, int swap) -{ - int ret; - - GET_32(ret, buf, offset, buf_len, swap); - - return ret; -} - -static int rat_den(void *buf, uint32_t offset, size_t buf_len, int swap) -{ - int ret; - - GET_32(ret, buf, offset + 4, buf_len, swap); - - return ret; -} -*/ - -static int load_tag(GP_IO *io, GP_DataStorage *storage, - GP_DataNode* node, int endian, - uint16_t tag, uint16_t format, - uint32_t num_comp, uint32_t val) -{ - const struct IFD_tag *res = IFD_tag_get(tag); - - if (res == NULL) { - GP_TODO("Skipping unknown IFD tag 0x%02x format %s", - tag, IFD_format_name(format)); - return 0; - } - - if (res->format != format) { - GP_WARN("Unexpected tag '%s' format '%s' (0x%02x) " - "expected '%s'", res->name, - IFD_format_name(format), format, - IFD_format_name(res->format)); - } - - if ((res->num_components != 0) && - (res->num_components != num_comp)) { - GP_WARN("Unexpected tag '%s' num_components %u expected %u", - res->name, num_comp, res->num_components); - } - - switch (format) { - case IFD_ASCII_STRING: - if (load_string(io, storage, node, res->name, num_comp, &val)) - return 1; - break; - //case IFD_UNSIGNED_LONG: - case IFD_UNSIGNED_SHORT: - if (num_comp == 1) - GP_DataStorageAddInt(storage, node, res->name, val); - else - goto unused; - break; - - case IFD_UNSIGNED_RATIONAL: - case IFD_SIGNED_RATIONAL: - if (load_rat(io, storage, node, res->name, num_comp, val)) - return 1; - -/* if (num_comp == 1) { - rec.type = GP_DATA_RATIONAL; - rec.value.rat. - GP_MetaDataCreateRat(self, res->name, - rat_num(buf, val, buf_len, swap), - rat_den(buf, val, buf_len, swap)); - } else { - goto unused; - } -*/ - break; - case IFD_UNDEFINED: - switch (res->tag) { - case IFD_EXIF_VERSION: - case IFD_FLASH_PIX_VERSION: - case IFD_MAKER_NOTE: - if (load_string(io, storage, node, res->name, num_comp, &val)) - return 1; - break; - default: - goto unused; - } - break; - - unused: - default: - GP_TODO("Unused record '%s' format '%s' (0x%02x)", res->name, - IFD_format_name(format), format); - } - - return 0; -} - -static int load_IFD(GP_IO *io, GP_DataStorage *storage, GP_DataNode *node, - uint32_t IFD_offset, int endian) -{ - uint16_t IFD_entries_count; - uint16_t i2 = endian == 'I' ? GP_IO_L2 : GP_IO_B2; - - uint16_t IFD_header[] = { - GP_IO_IGN | IFD_offset, - i2, - GP_IO_END, - }; - - if (GP_IOReadF(io, IFD_header, &IFD_entries_count) != 2) { - GP_DEBUG(1, "Failed to read IFD entries count"); - return 1; - } - - GP_DEBUG(2, "-- IFD Offset 0x%08x Entries 0x%04x --", - IFD_offset, IFD_entries_count); - - uint16_t IFD_record_LE[] = { - GP_IO_L2, /* Tag */ - GP_IO_L2, /* Format */ - GP_IO_L4, /* Number of components */ - GP_IO_L4, /* Value */ - GP_IO_END, - }; - - uint16_t IFD_record_BE[] = { - GP_IO_B2, /* Tag */ - GP_IO_B2, /* Format */ - GP_IO_B4, /* Number of components */ - GP_IO_B4, /* Value */ - GP_IO_END, - }; - - uint16_t *IFD_record = endian == 'I' ? IFD_record_LE : IFD_record_BE; - - int i; - - for (i = 0; i < IFD_entries_count; i++) { - uint16_t tag, format; - uint32_t num_comp, val; - off_t cur_off; - - if (GP_IOReadF(io, IFD_record, &tag, &format, &num_comp, &val) != 4) { - GP_DEBUG(1, "Failed to read IFD record"); - return 1; - } - - GP_DEBUG(3, "IFD Entry tag 0x%04x format (0x%04x) components 0x%08x val 0x%08x", - tag, format, num_comp, val); - - GP_DEBUG(3, "IFD Entry tag '%s' format '%s'", - IFD_tag_name(tag), IFD_format_name(format)); - - - if (tag == IFD_EXIF_OFFSET) { - cur_off = GP_IOTell(io); - - /* Offset is counted from the II or MM in the Exif header */ - if (val + 6 < cur_off) - GP_DEBUG(1, "Negative offset!"); - else - load_IFD(io, storage, node, val + 6 - cur_off, endian); - } else { - load_tag(io, storage, node, endian, tag, format, num_comp, val); - } - } - -/* - GET_32(IFD_offset, buf, IFD_offset, buf_len, swap); - - if (IFD_offset != 0x00000000) - load_IFD(self, buf, buf_len, IFD_offset, swap); -*/ - return 0; -} - -int GP_ReadExif(GP_IO *io, GP_DataStorage *storage) -{ - static int swap = 0; - char b1, b2; - uint32_t IFD_offset; - - uint16_t exif_header[] = { - 'E', 'x', 'i', 'f', 0, 0, /* EXIF signature */ - GP_IO_BYTE, GP_IO_BYTE, /* Endianity markers II or MM */ - 0x2a, 0x00, /* TIFF tag */ - GP_IO_L4, /* IFD offset */ - GP_IO_END, - }; - - if (GP_IOReadF(io, exif_header, &b1, &b2, &IFD_offset) != 11) { - GP_DEBUG(1, "Failed to read Exif header"); - return 1; - } - - if (b1 != b2 || (b1 != 'I' && b1 != 'M')) { - GP_WARN("Expected II or MM got %x%x, corrupt header?", b1, b2); - errno = EINVAL; - return 1; - } - - swap = (b1 == 'M'); - - GP_DEBUG(2, "TIFF aligment is '%c%c' swap = %i", b1, b1, swap); - - if (swap) { - //SWAP IFD_offset - } - - GP_DEBUG(2, "IFD offset is 0x%08x", IFD_offset); - - if (IFD_offset < 8) { - GP_WARN("Invalid (negative) IFD offset"); - errno = EINVAL; - return 1; - } - - GP_DataNode *exif_root = GP_DataStorageAddDict(storage, NULL, "Exif"); - - /* The offset starts from the II or MM */ - return load_IFD(io, storage, exif_root, IFD_offset - 8, b1); -} +static const struct IFD_tags IFD_EXIF_tags = { + .tags = IFD_EXIF_taglist, + .tag_cnt = GP_ARRAY_SIZE(IFD_EXIF_taglist), + .id = "Exif", +}; diff --git a/libs/loaders/GP_ExifGPS.h b/libs/loaders/GP_ExifGPS.h new file mode 100644 index 0000000..5e921f7 --- /dev/null +++ b/libs/loaders/GP_ExifGPS.h @@ -0,0 +1,62 @@ +/***************************************************************************** + * This file is part of gfxprim library. * + * * + * Gfxprim is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * Gfxprim is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with gfxprim; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, * + * Boston, MA 02110-1301 USA * + * * + * Copyright (C) 2009-2014 Cyril Hrubis <metan(a)ucw.cz> * + * * + *****************************************************************************/ + +enum IFD_GPS_tags { + IFD_GPS_VERSION_ID = 0x0, + /* 'N' = North, 'S' = South */ + IFD_GPS_LATITUDE_REF = 0x1, + /* Degrees, Minutes, Seconds */ + IFD_GPS_LATITUDE = 0x2, + /* 'E' = East, 'W' = West */ + IFD_GPS_LONGITUDE_REF = 0x3, + /* Degrees, Minutes, Seconds */ + IFD_GPS_LONGITUDE = 0x4, + /* 0 = Sea level, 1 = Sea level reference (negative value) */ + IFD_GPS_ALTITUDE_REF = 0x5, + /* Altitude in meters */ + IFD_GPS_ALTITUDE = 0x6, + /* Hour, Minute, Second */ + IFD_GPS_TIMESTAMP = 0x7, + + /* 'TOKYO' or 'WGS-84' */ + IFD_GPS_MAP_DATUM = 0x12, +}; + +/* MUST SORTED BY TAG */ +static const struct IFD_tag IFD_GPS_taglist[] = { + {IFD_GPS_VERSION_ID, "Version Info", IFD_UNSIGNED_BYTE, 4}, + {IFD_GPS_LATITUDE_REF, "Latitude Ref", IFD_ASCII_STRING, 2}, + {IFD_GPS_LATITUDE, "Latitude", IFD_UNSIGNED_RATIONAL, 3}, + {IFD_GPS_LONGITUDE_REF, "Longitude Ref", IFD_ASCII_STRING, 2}, + {IFD_GPS_LONGITUDE, "Longitude", IFD_UNSIGNED_RATIONAL, 3}, + {IFD_GPS_ALTITUDE_REF, "Altitude Ref", IFD_UNSIGNED_BYTE, 1}, + {IFD_GPS_ALTITUDE, "Altitude", IFD_UNSIGNED_RATIONAL, 1}, + {IFD_GPS_TIMESTAMP, "Time Stamp", IFD_UNSIGNED_RATIONAL, 3}, + + {IFD_GPS_MAP_DATUM, "Map Datum", IFD_ASCII_STRING, 0}, +}; + +static const struct IFD_tags IFD_GPS_tags = { + .tags = IFD_GPS_taglist, + .tag_cnt = GP_ARRAY_SIZE(IFD_GPS_taglist), + .id = "GPS", +}; ----------------------------------------------------------------------- Summary of changes: libs/loaders/GP_DataStorage.c | 2 +- libs/loaders/GP_Exif.c | 383 +++++------------- libs/loaders/{GP_Exif.c => GP_Exif.h} | 462 ++++------------------ tests/loaders/PBM.h => libs/loaders/GP_ExifGPS.h | 67 ++-- 4 files changed, 209 insertions(+), 705 deletions(-) copy libs/loaders/{GP_Exif.c => GP_Exif.h} (53%) copy tests/loaders/PBM.h => libs/loaders/GP_ExifGPS.h (56%) repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos(a)gmail.com if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive no reply. -- gfxprim.git ("A simple 2D graphics library with emphasis on correctness and well-defined operation.")
1
0
0
0
[repo.or.cz] gfxprim.git branch master updated: 1.0.0-rc1-137-g143e4e0
by metan
08 Feb '15
08 Feb '15
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project gfxprim.git. The branch, master has been updated via 143e4e08779b9dcd3aeed69e2de28c64d9c3d4d0 (commit) via 6d6eb1804dbbcf8a8507f2cd2474a3c282a1633b (commit) from 84df46f7a343005a0edbb3a744e8a62a109864ea (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log -----------------------------------------------------------------
http://repo.or.cz/w/gfxprim.git/commit/143e4e08779b9dcd3aeed69e2de28c64d9c3…
commit 143e4e08779b9dcd3aeed69e2de28c64d9c3d4d0 Author: Cyril Hrubis <metan(a)ucw.cz> Date: Sun Feb 8 10:58:16 2015 +0100 Exif: Add a few more tags. Signed-off-by: Cyril Hrubis <metan(a)ucw.cz> diff --git a/libs/loaders/GP_Exif.c b/libs/loaders/GP_Exif.c index f936589..99f49f7 100644 --- a/libs/loaders/GP_Exif.c +++ b/libs/loaders/GP_Exif.c @@ -174,16 +174,29 @@ enum IFD_tags { IFD_EXIF_IMAGE_HEIGHT = 0xa003, /* May store related audio filename */ IFD_RELATED_SOUND_FILE = 0xa004, + /* */ + IFD_FOCAL_PLANE_X_RESOLUTION = 0xa20e, + IFD_FOCAL_PLANE_Y_RESOLUTION = 0xa20f, + /* 1 = No unit, 2 = Inch (default), 3 = Centimeter */ + IFD_FOCAL_PLANE_RESOLUTION_UNIT = 0xa210, /* TODO: enum of sensing methods */ IFD_SENSING_METHOD = 0xa217, IFD_FILE_SOURCE = 0xa300, IFD_SCENE_TYPE = 0xa301, /* 0 = Normal, 1 = Custom */ - IFD_CUSTOM_RENDERER = 0x0a401, + IFD_CUSTOM_RENDERER = 0xa401, /* 0 = Auto, 1 = Manual, 2 = Auto bracket */ - IFD_EXPOSURE_MODE = 0x0a402, + IFD_EXPOSURE_MODE = 0xa402, /* 0 = Auto, 1 = Manual */ - IFD_WHITE_BALANCE = 0x0a403, + IFD_WHITE_BALANCE = 0xa403, + /* 0 = Standard, 1 = Landscape, 2 = Portrait, 3 = Night Scene */ + IFD_SCENE_CAPTURE_TYPE = 0xa406, + /* 0 = Normal, 1 = Soft, 2 = Hard */ + IFD_CONTRAST = 0xa408, + /* 0 = Normal, 1 = Low Saturation, 2 = Hight Saturation */ + IFD_SATURATION = 0xa409, + /* 0 = Normal, 1 = Sort, 2 = Hard */ + IFD_SHARPNESS = 0xa40a, }; struct IFD_tag { @@ -255,12 +268,19 @@ static const struct IFD_tag IFD_tags[] = { {IFD_EXIF_IMAGE_WIDTH, "Exif Image Width", IFD_UNSIGNED_LONG, 1}, {IFD_EXIF_IMAGE_HEIGHT, "Exif Image Height", IFD_UNSIGNED_LONG, 1}, {IFD_RELATED_SOUND_FILE, "Related Soundfile", IFD_ASCII_STRING, 0}, + {IFD_FOCAL_PLANE_X_RESOLUTION, "Focal Plane X Resolution", IFD_UNSIGNED_RATIONAL, 1}, + {IFD_FOCAL_PLANE_Y_RESOLUTION, "Focal Plane Y Resolution", IFD_UNSIGNED_RATIONAL, 1}, + {IFD_FOCAL_PLANE_RESOLUTION_UNIT, "Focal Plane Resolution Unit", IFD_UNSIGNED_SHORT, 1}, {IFD_SENSING_METHOD, "Sensing Method", IFD_UNSIGNED_SHORT, 1}, {IFD_FILE_SOURCE, "File Source", IFD_UNDEFINED, 1}, {IFD_SCENE_TYPE, "Scene Type", IFD_UNDEFINED, 1}, {IFD_CUSTOM_RENDERER, "Custom Renderer", IFD_UNSIGNED_SHORT, 1}, {IFD_EXPOSURE_MODE, "Exposure Mode", IFD_UNSIGNED_SHORT, 1}, {IFD_WHITE_BALANCE, "White Balance", IFD_UNSIGNED_SHORT, 1}, + {IFD_SCENE_CAPTURE_TYPE, "Scene Capture Type", IFD_UNSIGNED_SHORT, 1}, + {IFD_CONTRAST, "Contrast", IFD_UNSIGNED_SHORT, 1}, + {IFD_SATURATION, "Saturation", IFD_UNSIGNED_SHORT, 1}, + {IFD_SHARPNESS, "Sharpness", IFD_UNSIGNED_SHORT, 1}, }; static const char *IFD_format_name(uint16_t format)
http://repo.or.cz/w/gfxprim.git/commit/6d6eb1804dbbcf8a8507f2cd2474a3c282a1…
commit 6d6eb1804dbbcf8a8507f2cd2474a3c282a1633b Author: Cyril Hrubis <metan(a)ucw.cz> Date: Sun Feb 8 11:26:04 2015 +0100 loaders: DataStorage: Fix segfault. Fix segfault in GP_DataStorageGetByPath() in debug message that dereferenced possibly NULL pointer. Signed-off-by: Cyril Hrubis <metan(a)ucw.cz> diff --git a/libs/loaders/GP_DataStorage.c b/libs/loaders/GP_DataStorage.c index b6e9db9..cb02425 100644 --- a/libs/loaders/GP_DataStorage.c +++ b/libs/loaders/GP_DataStorage.c @@ -320,6 +320,9 @@ static struct GP_DataNode *get_by_path(GP_DataNode *node, const char *path) node = lookup(node, path, i); + if (!node) + return NULL; + GP_DEBUG(3, "Lookup has node '%s'", node->id); if (path[i] == '/') ----------------------------------------------------------------------- Summary of changes: libs/loaders/GP_DataStorage.c | 3 +++ libs/loaders/GP_Exif.c | 26 +++++++++++++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos(a)gmail.com if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive no reply. -- gfxprim.git ("A simple 2D graphics library with emphasis on correctness and well-defined operation.")
1
0
0
0
[repo.or.cz] gfxprim.git branch master updated: 1.0.0-rc1-135-g84df46f
by metan
07 Feb '15
07 Feb '15
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project gfxprim.git. The branch, master has been updated via 84df46f7a343005a0edbb3a744e8a62a109864ea (commit) via d63cd2b2a46aacac0683b804d887a571a3a1a1a7 (commit) via fcb2c2cfccb1d7122b5d6683481ac7ed57fc59c2 (commit) via b71fd317db698aa14a847020003be950257ae83d (commit) via c440a1bcd759c147b8f2b6739f41f9f94159ce64 (commit) via 32b937c63052f6686b1d818744f172c8658d4be2 (commit) via e42857ad289d9333411766b2df90cffea906cf11 (commit) from 1109c295817003da4e1da28179040c3060dc1326 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log -----------------------------------------------------------------
http://repo.or.cz/w/gfxprim.git/commit/84df46f7a343005a0edbb3a744e8a62a1098…
commit 84df46f7a343005a0edbb3a744e8a62a109864ea Author: Cyril Hrubis <metan(a)ucw.cz> Date: Sat Feb 7 22:24:13 2015 +0100 spiv: Implement EXIF autorotation Signed-off-by: Cyril Hrubis <metan(a)ucw.cz> diff --git a/demos/spiv/spiv.c b/demos/spiv/spiv.c index 75af202..91b1a2a 100644 --- a/demos/spiv/spiv.c +++ b/demos/spiv/spiv.c @@ -309,7 +309,7 @@ static void update_display(struct loader_params *params, GP_Context *img, struct cpu_timer timer; GP_ProgressCallback callback = {.callback = image_loader_callback}; - switch (config.orientation) { + switch (config.combined_orientation) { case ROTATE_0: break; case ROTATE_90: @@ -324,6 +324,8 @@ static void update_display(struct loader_params *params, GP_Context *img, callback.priv = "Rotating image (270)"; img = GP_FilterRotate270Alloc(img, &callback); break; + default: + break; } if (img == NULL) @@ -384,7 +386,7 @@ static void update_display(struct loader_params *params, GP_Context *img, show_info(params, img, orig_img); - if (config.orientation) + if (config.combined_orientation) GP_ContextFree(img); GP_BackendFlip(backend); @@ -465,6 +467,39 @@ GP_Context *load_resized_image(struct loader_params *params, GP_Size w, GP_Size return img; } +static void exif_autorotate(void) +{ + GP_DataNode *orientation; + + config.combined_orientation = config.orientation; + + if (!config.exif_autorotate) + return; + + orientation = GP_DataStorageGetByPath(image_loader_get_meta_data(), + NULL, "/Exif/Orientation"); + if (!orientation) + return; + + switch (orientation->value.i) { + case GP_EXIF_UPPER_LEFT: + config.combined_orientation += ROTATE_0; + break; + case GP_EXIF_LOWER_RIGHT: + config.combined_orientation += ROTATE_180; + break; + case GP_EXIF_UPPER_RIGHT: + config.combined_orientation += ROTATE_90; + break; + case GP_EXIF_LOWER_LEFT: + config.combined_orientation += ROTATE_270; + break; + } + + if (config.combined_orientation > ROTATE_270) + config.combined_orientation -= ROTATE_360; +} + static float calc_img_size(struct loader_params *params, uint32_t img_w, uint32_t img_h, uint32_t win_w, uint32_t win_h) @@ -473,7 +508,9 @@ static float calc_img_size(struct loader_params *params, unsigned int max_win_w = config.max_win_w; unsigned int max_win_h = config.max_win_h; - switch (config.orientation) { + exif_autorotate(); + + switch (config.combined_orientation) { case ROTATE_90: case ROTATE_270: GP_SWAP(win_w, win_h); @@ -488,7 +525,7 @@ static float calc_img_size(struct loader_params *params, win_w = GP_MIN(max_win_w, img_w * params->zoom_rat + 0.5); win_h = GP_MIN(max_win_h, img_h * params->zoom_rat + 0.5); - switch (config.orientation) { + switch (config.combined_orientation) { case ROTATE_90: case ROTATE_270: GP_BackendResize(backend, win_h, win_w); @@ -527,7 +564,7 @@ static float calc_img_size(struct loader_params *params, win_h = rat * img_h + 0.5; } - switch (config.orientation) { + switch (config.combined_orientation) { case ROTATE_90: case ROTATE_270: GP_BackendResize(backend, win_h, win_w); @@ -885,13 +922,13 @@ int main(int argc, char *argv[]) config.orientation++; if (config.orientation > ROTATE_270) - config.orientation = 0; + config.orientation = ROTATE_0; params.show_progress_once = 1; show_image(¶ms); break; case GP_KEY_E: - if (config.orientation > 0) + if (config.orientation > ROTATE_0) config.orientation--; else config.orientation = ROTATE_270; diff --git a/demos/spiv/spiv_config.c b/demos/spiv/spiv_config.c index 6fa95f4..73db91b 100644 --- a/demos/spiv/spiv_config.c +++ b/demos/spiv/spiv_config.c @@ -39,6 +39,7 @@ struct spiv_config config = { .zoom_strategy = ZOOM_IMAGE_DOWNSCALE, .win_strategy = ZOOM_WIN_FIXED, .full_screen = 0, + .exif_autorotate = 1, .max_win_w = 1024, .max_win_h = 768, @@ -132,6 +133,9 @@ static int set_opt(struct cfg_opt *self, unsigned int lineno) case 't': config.timers = 1; break; + case 'r': + config.exif_autorotate = 0; + break; } return 0; @@ -339,6 +343,14 @@ struct cfg_opt spiv_opts[] = { .help = "Orientation, one of 0, 90, 180, 270", }, {.name_space = "Gui", + .key = "DisableExifAutorotate", + .opt = 'r', + .opt_long = "disable_exif_autorotate", + .opt_has_value = 0, + .set = set_opt, + .help = "Disables automatic rotation by EXIF", + }, + {.name_space = "Gui", .key = "FullScreen", .opt = 'f', .opt_long = "full-screen", diff --git a/demos/spiv/spiv_config.h b/demos/spiv/spiv_config.h index 144ec6e..e8c713d 100644 --- a/demos/spiv/spiv_config.h +++ b/demos/spiv/spiv_config.h @@ -30,6 +30,7 @@ enum orientation { ROTATE_90, ROTATE_180, ROTATE_270, + ROTATE_360, }; enum zoom_strategy { @@ -46,7 +47,10 @@ enum zoom_strategy { struct spiv_config { float slideshow_delay; + /* orientation set by user */ enum orientation orientation; + /* combined orientation (user orientation + EXIF rotation) */ + enum orientation combined_orientation; int win_strategy:2; int zoom_strategy:2; /* Maximal window size */ @@ -58,6 +62,7 @@ struct spiv_config { int floyd_steinberg:1; int timers:1; int full_screen:1; + int exif_autorotate:1; char backend_init[128]; GP_PixelType emul_type;
http://repo.or.cz/w/gfxprim.git/commit/d63cd2b2a46aacac0683b804d887a571a3a1…
commit d63cd2b2a46aacac0683b804d887a571a3a1a1a7 Author: Cyril Hrubis <metan(a)ucw.cz> Date: Sat Feb 7 22:02:37 2015 +0100 DataStorage: Implement GP_DataStorageGetByPath() Signed-off-by: Cyril Hrubis <metan(a)ucw.cz> diff --git a/build/syms/Loaders_symbols.txt b/build/syms/Loaders_symbols.txt index 79ada50..5f8d749 100644 --- a/build/syms/Loaders_symbols.txt +++ b/build/syms/Loaders_symbols.txt @@ -154,6 +154,7 @@ GP_DataStorageClear GP_DataStorageRoot GP_DataDictFirst GP_DataStorageGet +GP_DataStorageGetByPath GP_DataStorageAdd GP_DataStorageAddInt GP_DataStorageAddDouble diff --git a/include/loaders/GP_DataStorage.h b/include/loaders/GP_DataStorage.h index e8b3279..4ad9705 100644 --- a/include/loaders/GP_DataStorage.h +++ b/include/loaders/GP_DataStorage.h @@ -108,6 +108,17 @@ GP_DataNode *GP_DataStorageGet(GP_DataStorage *self, GP_DataNode *node, const char *id); /* + * Returns data node by a path in the data storage. + * + * Example path: "/Exif/Orientation" + * + * The path works like filesystem path. The equivalent to working + * directory is the node pointer. + */ +GP_DataNode *GP_DataStorageGetByPath(GP_DataStorage *self, GP_DataNode *node, + const char *path); + +/* * Adds data into a dict. * * If node is NULL, data storage root is used. diff --git a/include/loaders/GP_Exif.h b/include/loaders/GP_Exif.h index f00cb69..5f42973 100644 --- a/include/loaders/GP_Exif.h +++ b/include/loaders/GP_Exif.h @@ -42,4 +42,14 @@ int GP_ReadExif(GP_IO *io, GP_DataStorage *storage); */ int GP_MatchExif(const void *buf); +/* + * Defines position to 0,0 coordinate. + */ +enum GP_EXIF_ORIENTATION { + GP_EXIF_UPPER_LEFT = 1, + GP_EXIF_LOWER_RIGHT = 3, + GP_EXIF_UPPER_RIGHT = 6, + GP_EXIF_LOWER_LEFT = 8, +}; + #endif /* LOADERS_GP_EXIF_H */ diff --git a/libs/loaders/GP_DataStorage.c b/libs/loaders/GP_DataStorage.c index 2257699..b6e9db9 100644 --- a/libs/loaders/GP_DataStorage.c +++ b/libs/loaders/GP_DataStorage.c @@ -293,6 +293,60 @@ GP_DataNode *GP_DataStorageGet(GP_DataStorage *self, return NULL; } +static struct GP_DataNode *lookup(GP_DataNode *node, const char *id, + const int id_len) +{ + struct GP_DataNode *i; + + if (!node) + return NULL; + + for (i = GP_DataDictFirst(node); i; i = i->next) { + if (!strncmp(i->id, id, id_len)) + return i; + } + + return NULL; +} + +static struct GP_DataNode *get_by_path(GP_DataNode *node, const char *path) +{ + unsigned int i; + + for (i = 0; path[i] && path[i] != '/'; i++); + + if (!i) + return node; + + node = lookup(node, path, i); + + GP_DEBUG(3, "Lookup has node '%s'", node->id); + + if (path[i] == '/') + path++; + + path+=i; + + return get_by_path(node, path); +} + +GP_DataNode *GP_DataStorageGetByPath(GP_DataStorage *self, GP_DataNode *node, + const char *path) +{ + GP_DEBUG(3, "Looking for '%s' in %p", path, node); + + if (path[0] == '/') { + + if (!self) + return NULL; + + node = GP_DataStorageRoot(self); + path++; + } + + return get_by_path(node, path); +} + static void padd_printf(size_t padd, const char *id, size_t id_padd, const char *fmt, ...)
http://repo.or.cz/w/gfxprim.git/commit/fcb2c2cfccb1d7122b5d6683481ac7ed57fc…
commit fcb2c2cfccb1d7122b5d6683481ac7ed57fc59c2 Author: Cyril Hrubis <metan(a)ucw.cz> Date: Sun Jan 25 21:28:40 2015 +0100 backends: X11: Catch UnmapNotify events. Signed-off-by: Cyril Hrubis <metan(a)ucw.cz> diff --git a/libs/backends/GP_X11_Input.h b/libs/backends/GP_X11_Input.h index c4364b4..6305874 100644 --- a/libs/backends/GP_X11_Input.h +++ b/libs/backends/GP_X11_Input.h @@ -276,6 +276,9 @@ static void x11_input_event_put(struct GP_EventQueue *event_queue, case GravityNotify: GP_DEBUG(1, "GravityNotify event received"); break; + case UnmapNotify: + GP_DEBUG(1, "UnmapNotify event received"); + break; default: GP_WARN("Unhandled X11 event type %u", ev->type); }
http://repo.or.cz/w/gfxprim.git/commit/b71fd317db698aa14a847020003be950257a…
commit b71fd317db698aa14a847020003be950257ae83d Author: Cyril Hrubis <metan(a)ucw.cz> Date: Fri Jan 16 17:20:51 2015 +0100 bogoman: Do screenshot on pressing s key. Signed-off-by: Cyril Hrubis <metan(a)ucw.cz> diff --git a/demos/bogoman/Makefile b/demos/bogoman/Makefile index a448fee..c998522 100644 --- a/demos/bogoman/Makefile +++ b/demos/bogoman/Makefile @@ -4,7 +4,7 @@ include $(TOPDIR)/pre.mk CSOURCES=$(shell echo *.c) INCLUDE= -LDLIBS+=-lgfxprim-backends +LDLIBS+=-lgfxprim-backends -lgfxprim-loaders APPS=bogoman diff --git a/demos/bogoman/bogoman.c b/demos/bogoman/bogoman.c index a83cba3..36402c8 100644 --- a/demos/bogoman/bogoman.c +++ b/demos/bogoman/bogoman.c @@ -62,6 +62,8 @@ static struct GP_Backend *backend; static void event_loop(struct bogoman_render *render, GP_Backend *backend) { struct bogoman_map *map = render->map; + char path[128]; + static int screenshots; while (GP_BackendEventsQueued(backend)) { GP_Event ev; @@ -90,6 +92,11 @@ static void event_loop(struct bogoman_render *render, GP_Backend *backend) case GP_KEY_DOWN: bogoman_map_player_move(map, 0, 1); break; + case GP_KEY_S: + snprintf(path, sizeof(path), + "screenshot%04i.png", screenshots++); + save_png(map, render->map_elem_size, path); + break; } bogoman_render(render, BOGOMAN_RENDER_DIRTY); break;
http://repo.or.cz/w/gfxprim.git/commit/c440a1bcd759c147b8f2b6739f41f9f94159…
commit c440a1bcd759c147b8f2b6739f41f9f94159ce64 Author: Cyril Hrubis <metan(a)ucw.cz> Date: Fri Jan 16 16:48:19 2015 +0100 build: Add missing histogram symbol. Signed-off-by: Cyril Hrubis <metan(a)ucw.cz> diff --git a/build/syms/Filters_symbols.txt b/build/syms/Filters_symbols.txt index 4304919..52e078f 100644 --- a/build/syms/Filters_symbols.txt +++ b/build/syms/Filters_symbols.txt @@ -59,6 +59,7 @@ GP_FilterHLinearConvolution_Raw GP_FilterHistogram GP_HistogramAlloc GP_HistogramFree +GP_HistogramChannelByName GP_FilterKernelPrint_Raw
http://repo.or.cz/w/gfxprim.git/commit/32b937c63052f6686b1d818744f172c8658d…
commit 32b937c63052f6686b1d818744f172c8658d4be2 Author: Cyril Hrubis <metan(a)ucw.cz> Date: Fri Jan 16 16:44:18 2015 +0100 core: Get rid of GP_Color. Special thanks to coccinelle and spatch for making this easy job. :) Signed-off-by: Cyril Hrubis <metan(a)ucw.cz> diff --git a/build/syms/Core_symbols.txt b/build/syms/Core_symbols.txt index 902dbdb..47acec5 100644 --- a/build/syms/Core_symbols.txt +++ b/build/syms/Core_symbols.txt @@ -28,8 +28,6 @@ GP_SetDebugHandler GP_PrintAbortInfo -GP_ColorToPixel -GP_ColorLoadPixels GP_RGBA8888ToPixel GP_PixelRGBMatch GP_PixelTypeByName @@ -63,9 +61,6 @@ GP_PutPixel GP_GetPixel GP_PixelRGBLookup GP_PixelToRGB888 -GP_ColorNameToPixel -GP_ColorNameToColor -GP_ColorToColorName GP_PixelToRGBA8888 GP_Fill diff --git a/demos/c_simple/SDL_glue.c b/demos/c_simple/SDL_glue.c index a613159..8e9e216 100644 --- a/demos/c_simple/SDL_glue.c +++ b/demos/c_simple/SDL_glue.c @@ -102,8 +102,8 @@ int main(void) GP_ContextFromSDLSurface(&context, display); - black_pixel = GP_ColorToContextPixel(GP_COL_BLACK, &context); - darkgray_pixel = GP_ColorToContextPixel(GP_COL_GRAY_DARK, &context); + black_pixel = GP_RGBToContextPixel(0x00, 0x00, 0x00, &context); + darkgray_pixel = GP_RGBToContextPixel(0x7f, 0x7f, 0x7f, &context); redraw_screen(); SDL_Flip(display); diff --git a/demos/c_simple/backend_example.c b/demos/c_simple/backend_example.c index 651ffff..5e87ff1 100644 --- a/demos/c_simple/backend_example.c +++ b/demos/c_simple/backend_example.c @@ -34,8 +34,8 @@ static void redraw(GP_Backend *self) GP_Context *context = self->context; GP_Pixel white_pixel, black_pixel; - black_pixel = GP_ColorToContextPixel(GP_COL_BLACK, context); - white_pixel = GP_ColorToContextPixel(GP_COL_WHITE, context); + black_pixel = GP_RGBToContextPixel(0x00, 0x00, 0x00, context); + white_pixel = GP_RGBToContextPixel(0xff, 0xff, 0xff, context); GP_Fill(context, black_pixel); GP_Line(context, 0, 0, context->w - 1, context->h - 1, white_pixel); diff --git a/demos/c_simple/backend_timers_example.c b/demos/c_simple/backend_timers_example.c index 8d860e5..7b7aae2 100644 --- a/demos/c_simple/backend_timers_example.c +++ b/demos/c_simple/backend_timers_example.c @@ -32,7 +32,7 @@ static void redraw(GP_Backend *self) { GP_Context *context = self->context; - GP_Pixel black_pixel = GP_ColorToContextPixel(GP_COL_BLACK, context); + GP_Pixel black_pixel = GP_RGBToContextPixel(0x00, 0x00, 0x00, context); GP_Fill(context, black_pixel); diff --git a/demos/c_simple/blittest.c b/demos/c_simple/blittest.c index c6cd275..ecdb39a 100644 --- a/demos/c_simple/blittest.c +++ b/demos/c_simple/blittest.c @@ -174,8 +174,8 @@ int main(void) win->context->pixel_type); change_bitmap(); - black = GP_ColorToContextPixel(GP_COL_BLACK, win->context); - white = GP_ColorToContextPixel(GP_COL_WHITE, win->context); + black = GP_RGBToContextPixel(0x00, 0x00, 0x00, win->context); + white = GP_RGBToContextPixel(0xff, 0xff, 0xff, win->context); GP_Fill(win->context, black); GP_BackendFlip(win); diff --git a/demos/c_simple/fileview.c b/demos/c_simple/fileview.c index 2d06dae..972514b 100644 --- a/demos/c_simple/fileview.c +++ b/demos/c_simple/fileview.c @@ -263,12 +263,12 @@ int main(int argc, char *argv[]) win = backend->context; - white_pixel = GP_ColorToContextPixel(GP_COL_WHITE, win); - gray_pixel = GP_ColorToContextPixel(GP_COL_GRAY_LIGHT, win); - dark_gray_pixel = GP_ColorToContextPixel(GP_COL_GRAY_DARK, win); - black_pixel = GP_ColorToContextPixel(GP_COL_BLACK, win); - red_pixel = GP_ColorToContextPixel(GP_COL_RED, win); - blue_pixel = GP_ColorToContextPixel(GP_COL_BLUE, win); + white_pixel = GP_RGBToContextPixel(0xff, 0xff, 0xff, win); + gray_pixel = GP_RGBToContextPixel(0xbe, 0xbe, 0xbe, win); + dark_gray_pixel = GP_RGBToContextPixel(0x7f, 0x7f, 0x7f, win); + black_pixel = GP_RGBToContextPixel(0x00, 0x00, 0x00, win); + red_pixel = GP_RGBToContextPixel(0xff, 0x00, 0x00, win); + blue_pixel = GP_RGBToContextPixel(0x00, 0x00, 0xff, win); redraw_screen(); GP_BackendFlip(backend); diff --git a/demos/c_simple/fonttest.c b/demos/c_simple/fonttest.c index 4e33020..9a3aff1 100644 --- a/demos/c_simple/fonttest.c +++ b/demos/c_simple/fonttest.c @@ -277,12 +277,12 @@ int main(int argc, char *argv[]) return 1; } - white_pixel = GP_ColorToContextPixel(GP_COL_WHITE, win->context); - gray_pixel = GP_ColorToContextPixel(GP_COL_GRAY_LIGHT, win->context); - dark_gray_pixel = GP_ColorToContextPixel(GP_COL_GRAY_DARK, win->context); - black_pixel = GP_ColorToContextPixel(GP_COL_BLACK, win->context); - red_pixel = GP_ColorToContextPixel(GP_COL_RED, win->context); - blue_pixel = GP_ColorToContextPixel(GP_COL_BLUE, win->context); + white_pixel = GP_RGBToContextPixel(0xff, 0xff, 0xff, win->context); + gray_pixel = GP_RGBToContextPixel(0xbe, 0xbe, 0xbe, win->context); + dark_gray_pixel = GP_RGBToContextPixel(0x7f, 0x7f, 0x7f, win->context); + black_pixel = GP_RGBToContextPixel(0x00, 0x00, 0x00, win->context); + red_pixel = GP_RGBToContextPixel(0xff, 0x00, 0x00, win->context); + blue_pixel = GP_RGBToContextPixel(0x00, 0x00, 0xff, win->context); redraw_screen(); GP_BackendFlip(win); diff --git a/demos/c_simple/input_example.c b/demos/c_simple/input_example.c index 3b94ce3..3a294d2 100644 --- a/demos/c_simple/input_example.c +++ b/demos/c_simple/input_example.c @@ -150,10 +150,10 @@ int main(int argc, char *argv[]) win = backend->context; - red = GP_ColorToContextPixel(GP_COL_RED, win); - green = GP_ColorToContextPixel(GP_COL_GREEN, win); - white = GP_ColorToContextPixel(GP_COL_WHITE, win); - black = GP_ColorToContextPixel(GP_COL_BLACK, win); + red = GP_RGBToContextPixel(0xff, 0x00, 0x00, win); + green = GP_RGBToContextPixel(0x00, 0xff, 0x00, win); + white = GP_RGBToContextPixel(0xff, 0xff, 0xff, win); + black = GP_RGBToContextPixel(0x00, 0x00, 0x00, win); GP_Fill(win, black); GP_BackendFlip(backend); diff --git a/demos/c_simple/koch.c b/demos/c_simple/koch.c index 335815d..5bb1538 100644 --- a/demos/c_simple/koch.c +++ b/demos/c_simple/koch.c @@ -138,10 +138,10 @@ int main(void) context = backend->context; - black = GP_ColorToContextPixel(GP_COL_BLACK, context); - blue = GP_ColorToContextPixel(GP_COL_BLUE, context); - gray = GP_ColorToContextPixel(GP_COL_GRAY_LIGHT, context); - red = GP_ColorToContextPixel(GP_COL_RED, context); + black = GP_RGBToContextPixel(0x00, 0x00, 0x00, context); + blue = GP_RGBToContextPixel(0x00, 0x00, 0xff, context); + gray = GP_RGBToContextPixel(0xbe, 0xbe, 0xbe, context); + red = GP_RGBToContextPixel(0xff, 0x00, 0x00, context); iter = 0; draw(context->w/2, context->h/2, l, iter); diff --git a/demos/c_simple/linetest.c b/demos/c_simple/linetest.c index 1df6e6e..19a0244 100644 --- a/demos/c_simple/linetest.c +++ b/demos/c_simple/linetest.c @@ -135,8 +135,8 @@ int main(int argc, char *argv[]) return 1; } - white = GP_ColorToContextPixel(GP_COL_WHITE, win->context); - black = GP_ColorToContextPixel(GP_COL_BLACK, win->context); + white = GP_RGBToContextPixel(0xff, 0xff, 0xff, win->context); + black = GP_RGBToContextPixel(0x00, 0x00, 0x00, win->context); redraw_screen(); diff --git a/demos/c_simple/randomshapetest.c b/demos/c_simple/randomshapetest.c index f3dbaa1..e5f4e5d 100644 --- a/demos/c_simple/randomshapetest.c +++ b/demos/c_simple/randomshapetest.c @@ -268,8 +268,8 @@ int main(void) return 1; } - white = GP_ColorToContextPixel(GP_COL_WHITE, win->context); - black = GP_ColorToContextPixel(GP_COL_BLACK, win->context); + white = GP_RGBToContextPixel(0xff, 0xff, 0xff, win->context); + black = GP_RGBToContextPixel(0x00, 0x00, 0x00, win->context); for (;;) { GP_BackendPoll(win); diff --git a/demos/c_simple/shapetest.c b/demos/c_simple/shapetest.c index db32938..b114fd8 100644 --- a/demos/c_simple/shapetest.c +++ b/demos/c_simple/shapetest.c @@ -505,13 +505,13 @@ int main(int argc, char *argv[]) center_y = win->h / 2; /* Load colors compatible with the display */ - black = GP_ColorToContextPixel(GP_COL_BLACK, win); - white = GP_ColorToContextPixel(GP_COL_WHITE, win); - yellow = GP_ColorToContextPixel(GP_COL_YELLOW, win); - green = GP_ColorToContextPixel(GP_COL_GREEN, win); - red = GP_ColorToContextPixel(GP_COL_RED, win); - gray = GP_ColorToContextPixel(GP_COL_GRAY_LIGHT, win); - darkgray = GP_ColorToContextPixel(GP_COL_GRAY_DARK, win); + black = GP_RGBToContextPixel(0x00, 0x00, 0x00, win); + white = GP_RGBToContextPixel(0xff, 0xff, 0xff, win); + yellow = GP_RGBToContextPixel(0xff, 0xff, 0x00, win); + green = GP_RGBToContextPixel(0x00, 0xff, 0x00, win); + red = GP_RGBToContextPixel(0xff, 0x00, 0x00, win); + gray = GP_RGBToContextPixel(0xbe, 0xbe, 0xbe, win); + darkgray = GP_RGBToContextPixel(0x7f, 0x7f, 0x7f, win); print_instructions(); redraw_screen(); diff --git a/demos/c_simple/textaligntest.c b/demos/c_simple/textaligntest.c index 70b2fd2..5e2fbd6 100644 --- a/demos/c_simple/textaligntest.c +++ b/demos/c_simple/textaligntest.c @@ -181,13 +181,13 @@ int main(int argc, char *argv[]) return 1; } - black_pixel = GP_ColorToContextPixel(GP_COL_BLACK, win->context); - red_pixel = GP_ColorToContextPixel(GP_COL_RED, win->context); - blue_pixel = GP_ColorToContextPixel(GP_COL_BLUE, win->context); - green_pixel = GP_ColorToContextPixel(GP_COL_GREEN, win->context); - yellow_pixel = GP_ColorToContextPixel(GP_COL_YELLOW, win->context); - white_pixel = GP_ColorToContextPixel(GP_COL_WHITE, win->context); - darkgray_pixel = GP_ColorToContextPixel(GP_COL_GRAY_DARK, win->context); + black_pixel = GP_RGBToContextPixel(0x00, 0x00, 0x00, win->context); + red_pixel = GP_RGBToContextPixel(0xff, 0x00, 0x00, win->context); + blue_pixel = GP_RGBToContextPixel(0x00, 0x00, 0xff, win->context); + green_pixel = GP_RGBToContextPixel(0x00, 0xff, 0x00, win->context); + yellow_pixel = GP_RGBToContextPixel(0xff, 0xff, 0x00, win->context); + white_pixel = GP_RGBToContextPixel(0xff, 0xff, 0xff, win->context); + darkgray_pixel = GP_RGBToContextPixel(0x7f, 0x7f, 0x7f, win->context); redraw_screen(); GP_BackendFlip(win); diff --git a/demos/c_simple/virtual_backend_example.c b/demos/c_simple/virtual_backend_example.c index 925a3d6..5ef5a8e 100644 --- a/demos/c_simple/virtual_backend_example.c +++ b/demos/c_simple/virtual_backend_example.c @@ -93,11 +93,11 @@ int main(int argc, char *argv[]) context = backend->context; /* Now draw some testing patters */ - black_pixel = GP_ColorToContextPixel(GP_COL_BLACK, context); - white_pixel = GP_ColorToContextPixel(GP_COL_WHITE, context); - red_pixel = GP_ColorToContextPixel(GP_COL_RED, context); - blue_pixel = GP_ColorToContextPixel(GP_COL_BLUE, context); - green_pixel = GP_ColorToContextPixel(GP_COL_GREEN, context); + black_pixel = GP_RGBToContextPixel(0x00, 0x00, 0x00, context); + white_pixel = GP_RGBToContextPixel(0xff, 0xff, 0xff, context); + red_pixel = GP_RGBToContextPixel(0xff, 0x00, 0x00, context); + blue_pixel = GP_RGBToContextPixel(0x00, 0x00, 0xff, context); + green_pixel = GP_RGBToContextPixel(0x00, 0xff, 0x00, context); GP_Fill(context, white_pixel); diff --git a/demos/c_simple/x11_windows.c b/demos/c_simple/x11_windows.c index fa52cc2..1c5b2d0 100644 --- a/demos/c_simple/x11_windows.c +++ b/demos/c_simple/x11_windows.c @@ -33,8 +33,8 @@ static void redraw(struct GP_Context *context) { GP_Pixel white_pixel, black_pixel; - black_pixel = GP_ColorToContextPixel(GP_COL_BLACK, context); - white_pixel = GP_ColorToContextPixel(GP_COL_WHITE, context); + black_pixel = GP_RGBToContextPixel(0x00, 0x00, 0x00, context); + white_pixel = GP_RGBToContextPixel(0xff, 0xff, 0xff, context); GP_Fill(context, black_pixel); GP_Line(context, 0, 0, context->w - 1, context->h - 1, white_pixel); diff --git a/demos/particle/particle_demo.c b/demos/particle/particle_demo.c index 2b902a0..46fafe2 100644 --- a/demos/particle/particle_demo.c +++ b/demos/particle/particle_demo.c @@ -90,8 +90,8 @@ int main(int argc, char *argv[]) context = backend->context; - black_pixel = GP_ColorToContextPixel(GP_COL_BLACK, context); - white_pixel = GP_ColorToContextPixel(GP_COL_WHITE, context); + black_pixel = GP_RGBToContextPixel(0x00, 0x00, 0x00, context); + white_pixel = GP_RGBToContextPixel(0xff, 0xff, 0xff, context); GP_Fill(context, black_pixel); GP_BackendFlip(backend); diff --git a/demos/spiv/spiv.c b/demos/spiv/spiv.c index 40a5687..75af202 100644 --- a/demos/spiv/spiv.c +++ b/demos/spiv/spiv.c @@ -818,8 +818,8 @@ int main(int argc, char *argv[]) context = backend->context; - black_pixel = GP_ColorToContextPixel(GP_COL_BLACK, context); - white_pixel = GP_ColorToContextPixel(GP_COL_WHITE, context); + black_pixel = GP_RGBToContextPixel(0x00, 0x00, 0x00, context); + white_pixel = GP_RGBToContextPixel(0xff, 0xff, 0xff, context); gray_pixel = GP_RGBToContextPixel(0x33, 0x33, 0x33, context); GP_Fill(context, black_pixel); diff --git a/demos/spiv/spiv_help.c b/demos/spiv/spiv_help.c index ef1f0c5..2d7eac9 100644 --- a/demos/spiv/spiv_help.c +++ b/demos/spiv/spiv_help.c @@ -235,8 +235,8 @@ static int last_line; static int redraw_help(GP_Backend *backend, unsigned int loff, GP_Coord xoff) { GP_Context *c = backend->context; - GP_Pixel black = GP_ColorToContextPixel(GP_COL_BLACK, c); - GP_Pixel white = GP_ColorToContextPixel(GP_COL_WHITE, c); + GP_Pixel black = GP_RGBToContextPixel(0x00, 0x00, 0x00, c); + GP_Pixel white = GP_RGBToContextPixel(0xff, 0xff, 0xff, c); int i; int spacing = GP_TextHeight(config.style)/10 + 2; diff --git a/demos/ttf2img/ttf2img.c b/demos/ttf2img/ttf2img.c index 9bc4558..deaa37a 100644 --- a/demos/ttf2img/ttf2img.c +++ b/demos/ttf2img/ttf2img.c @@ -76,8 +76,8 @@ int main(int argc, char *argv[]) GP_Context *context = GP_ContextAlloc(img_w, img_h, GP_PIXEL_RGB888); - GP_Pixel black_pixel = GP_ColorToContextPixel(GP_COL_BLACK, context); - GP_Pixel white_pixel = GP_ColorToContextPixel(GP_COL_WHITE, context); + GP_Pixel black_pixel = GP_RGBToContextPixel(0x00, 0x00, 0x00, context); + GP_Pixel white_pixel = GP_RGBToContextPixel(0xff, 0xff, 0xff, context); GP_Fill(context, white_pixel); diff --git a/doc/basic_types.txt b/doc/basic_types.txt index 11ff214..3b6c6fd 100644 --- a/doc/basic_types.txt +++ b/doc/basic_types.txt @@ -17,75 +17,3 @@ values. The default typedef for 'GP_Pixel' is set to 32 bit integer, which may be changed at compile time to support colors with more than 10 bits per channel. The 'GP_Pixel' is thus used as opaque value big enough to hold any supported pixel value. - -[[Color]] -Color -~~~~~ - -The 'GP_Color' enumeration holds symbolic constants for basic colors. - -A 'GP_Color' can be converted into a 'GP_Pixel' for a given 'GP_PixelType'. -Symbolic values can also be converted to/from strings (color name in English). - -The 'GP_Color' enum is defined as follows: - -[source,c] --------------------------------------------------------------------------------- -typedef enum GP_Color { - GP_COL_INVALID = -1, - - /* full-intensity RGB and CMYK */ - GP_COL_BLACK, - GP_COL_RED, - GP_COL_GREEN, - GP_COL_BLUE, - GP_COL_YELLOW, - GP_COL_CYAN, - GP_COL_MAGENTA, - - /* various common mixes */ - GP_COL_BROWN, - GP_COL_ORANGE, - GP_COL_GRAY_DARK, /* exactly half RGB values of white */ - GP_COL_GRAY_LIGHT, - GP_COL_PURPLE, - - GP_COL_WHITE, /* full-intensity white */ - GP_COL_MAX, -} GP_Color; --------------------------------------------------------------------------------- - -[source,c] --------------------------------------------------------------------------------- -#include <core/GP_Color.h> -/* or */ -#include <GP.h> - -GP_Pixel GP_ColorToPixel(GP_Color color, GP_PixelType pixel_type); -GP_Pixel GP_ColorToContextPixel(GP_Color color, GP_Context *context); - -GP_Color GP_ColorNameToColor(const char *color_name); -const char *GP_ColorToColorName(GP_Color color); - -bool GP_ColorNameToPixel(const char *color_name, GP_PixelType pixel_type, - GP_Pixel *pixel); -bool GP_ColorNameToContextPixel(const char *color_name, GP_Context *context, - GP_Pixel *pixel); --------------------------------------------------------------------------------- - -Functions for conversion between colors, pixels and color names. The last two -returns true if color with such name was found. - -[source,c] --------------------------------------------------------------------------------- -#include <core/GP_Color.h> -/* or */ -#include <GP.h> - -void GP_ColorLoadPixels(GP_Pixel pixels[], GP_PixelType pixel_type); -void GP_ColorLoadContextPixels(GP_Pixel pixels[], GP_Context *context); --------------------------------------------------------------------------------- - -Loads array of 'GP_Pixel' of size 'GP_COL_MAX', the array is then used with -the GP_Color enum as 'pixels[GP_COL_BLACK]'. - diff --git a/doc/convert.txt b/doc/convert.txt index 9191805..f11f932 100644 --- a/doc/convert.txt +++ b/doc/convert.txt @@ -3,8 +3,6 @@ Pixel Conversions This page describes RGB tripplet to pixels conversions. -See also link:basic_types.html#Color[colors]. - [source,c] ------------------------------------------------------------------------------- #include <GP.h> diff --git a/doc/core_python.txt b/doc/core_python.txt index 487b903..108c859 100644 --- a/doc/core_python.txt +++ b/doc/core_python.txt @@ -101,15 +101,13 @@ Blit is clipped. TIP: See link:example_py_showimage.html[example Blit usage]. -[[Colors_and_Pixels]] -Colors and Pixels -~~~~~~~~~~~~~~~~~ +[[Pixels]] +Pixels +~~~~~~ Pixel in GFXprim is a number large enough to store a pixel value. Pixel is passed as a parameter to all drawing functions. -Color is a more abstract representation for example RGB triplet. - There are several functions to create a pixel value for a particular pixel type from color. @@ -128,7 +126,6 @@ import gfxprim.core as core These functions creates a pixel suitable for drawing into a bitmap with particular pixel type. - [source,python] ------------------------------------------------------------------------------- import gfxprim.core as core diff --git a/include/core/GP_Color.h b/include/core/GP_Color.h deleted file mode 100644 index de87e6a..0000000 --- a/include/core/GP_Color.h +++ /dev/null @@ -1,124 +0,0 @@ -/***************************************************************************** - * This file is part of gfxprim library. * - * * - * Gfxprim is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Lesser General Public * - * License as published by the Free Software Foundation; either * - * version 2.1 of the License, or (at your option) any later version. * - * * - * Gfxprim is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * - * Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public * - * License along with gfxprim; if not, write to the Free Software * - * Foundation, Inc., 51 Franklin Street, Fifth Floor, * - * Boston, MA 02110-1301 USA * - * * - * Copyright (C) 2009-2010 Jiri "BlueBear" Dluhos * - * <jiri.bluebear.dluhos(a)gmail.com> * - * * - * Copyright (C) 2009-2011 Cyril Hrubis <metan(a)ucw.cz> * - * * - *****************************************************************************/ - - /* - - Color is enumeration of color names which may be converted into pixel values - in desired pixel format. - - */ - -#ifndef GP_COLOR_H -#define GP_COLOR_H - -#include "GP_Context.h" -#include "GP_Pixel.h" - -/* - * Enumeration of color constants. - */ -typedef enum GP_Color { - GP_COL_INVALID = -1, - GP_COL_BLACK, - GP_COL_RED, - GP_COL_GREEN, - GP_COL_BLUE, - GP_COL_YELLOW, - GP_COL_CYAN, - GP_COL_MAGENTA, - GP_COL_BROWN, - GP_COL_ORANGE, - GP_COL_GRAY_DARK, - GP_COL_GRAY_LIGHT, - GP_COL_PURPLE, - GP_COL_WHITE, - GP_COL_MAX, -} GP_Color; - -/* - * Converts GP_Color to GP_Pixel. - */ -GP_Pixel GP_ColorToPixel(GP_Color color, GP_PixelType pixel_type); - -/* - * Converts GP_Color to GP_Pixel. - */ -static inline GP_Pixel GP_ColorToContextPixel(GP_Color color, - GP_Context *context) -{ - return GP_ColorToPixel(color, context->pixel_type); -} - -/* - * Converts Color name (eg. string) to GP_Color. - */ -GP_Color GP_ColorNameToColor(const char *color_name); - -/* - * Converts GP_Color to color name. - * - * If color is not valid NULL is returned. - */ -const char *GP_ColorToColorName(GP_Color color); - -/* - * Converts Color name to Pixel. - * - * Returns true if conversion was successful false otherwise. - */ -bool GP_ColorNameToPixel(const char *color_name, GP_PixelType pixel_type, - GP_Pixel *pixel); - -/* - * Converts Color name to Pixel. - * - * Returns true if conversion was successful false otherwise. - */ -static inline bool GP_ColorNameToContextPixel(const char *color_name, - GP_Context *context, - GP_Pixel *pixel) -{ - return GP_ColorNameToPixel(color_name, context->pixel_type, pixel); -} - -/* - * Loads all colors into array of GP_Pixel of size GP_COL_MAX. - * - * The colors are then used as pixels[GP_COL_XXX]; - */ -void GP_ColorLoadPixels(GP_Pixel pixels[], GP_PixelType pixel_type); - -/* - * Loads all colors into array of GP_Pixel of size GP_COL_MAX. - * - * The colors are then used as pixels[GP_COL_XXX]; - */ -static inline void GP_ColorLoadContextPixels(GP_Pixel pixels[], - GP_Context *context) -{ - GP_ColorLoadPixels(pixels, context->pixel_type); -} - -#endif /* GP_COLOR_H */ diff --git a/include/core/GP_Core.h b/include/core/GP_Core.h index b9f1b6a..bef6834 100644 --- a/include/core/GP_Core.h +++ b/include/core/GP_Core.h @@ -65,9 +65,6 @@ /* Debug and debug level */ #include "core/GP_Debug.h" -/* Color */ -#include "core/GP_Color.h" - /* Progress callback */ #include "core/GP_ProgressCallback.h" diff --git a/libs/core/GP_Color.c b/libs/core/GP_Color.c deleted file mode 100644 index 2c42d4a..0000000 --- a/libs/core/GP_Color.c +++ /dev/null @@ -1,135 +0,0 @@ -/***************************************************************************** - * This file is part of gfxprim library. * - * * - * Gfxprim is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Lesser General Public * - * License as published by the Free Software Foundation; either * - * version 2.1 of the License, or (at your option) any later version. * - * * - * Gfxprim is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * - * Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public * - * License along with gfxprim; if not, write to the Free Software * - * Foundation, Inc., 51 Franklin Street, Fifth Floor, * - * Boston, MA 02110-1301 USA * - * * - * Copyright (C) 2009-2010 Jiri "BlueBear" Dluhos * - * <jiri.bluebear.dluhos(a)gmail.com> * - * * - * Copyright (C) 2009-2011 Cyril Hrubis <metan(a)ucw.cz> * - * * - *****************************************************************************/ - -#include <stdint.h> -#include <string.h> - -#include "GP_Convert.h" - -#include "GP_Color.h" - - -static char *color_names[] = { - "Black", - "Red", - "Green", - "Blue", - "Yellow", - "Cyan", - "Magenta", - "Brown", - "Orange", - "DarkGray", - "LightGray", - "Purple", - "White" -}; - -static uint8_t rgb888_colors[][3] = { - {0x00, 0x00, 0x00}, /* Black */ - {0xff, 0x00, 0x00}, /* Red */ - {0x00, 0xff, 0x00}, /* Green */ - {0x00, 0x00, 0xff}, /* Blue */ - {0xff, 0xff, 0x00}, /* Yellow */ - {0x00, 0xff, 0xff}, /* Cyan */ - {0xff, 0x00, 0xff}, /* Magenta */ - {0xa5, 0x2a, 0x2a}, /* Brown */ - {0xff, 0xa5, 0x00}, /* Orange */ - {0x7f, 0x7f, 0x7f}, /* DarkGray */ - {0xbe, 0xbe, 0xbe}, /* LightGray */ - {0xa0, 0x20, 0xf0}, /* Purple */ - {0xff, 0xff, 0xff}, /* White */ -}; - -/* 3-2-3 RGB palette */ -static uint8_t p8_colors[] = { - 0x00, /* Black */ - 0xe0, /* Red */ - 0x1c, /* Green */ - 0x03, /* Blue */ - 0xfc, /* Yellow */ - 0x1f, /* Cyan */ - 0xe7, /* Magenta */ - 0x88, /* Brown */ - 0xf0, /* Orange */ - 0x49, /* DarkGray */ - 0x92, /* LightGray */ - 0x8a, /* Purple */ - 0xff, /* White */ -}; - -GP_Pixel GP_ColorToPixel(GP_Color color, GP_PixelType pixel_type) -{ - GP_ASSERT(color < GP_COL_MAX); - GP_ASSERT(color >= 0); - - if (pixel_type == GP_PIXEL_P8) - return p8_colors[color]; - - return GP_RGBToPixel(rgb888_colors[color][0], - rgb888_colors[color][1], - rgb888_colors[color][2], - pixel_type); -} - -GP_Color GP_ColorNameToColor(const char *color_name) -{ - unsigned int i; - - for (i = 0; i < GP_COL_MAX; i++) - if (!strcasecmp(color_name, color_names[i])) - return i; - - return -1; -} - -const char *GP_ColorToColorName(GP_Color color) -{ - if (color < 0 || color >= GP_COL_MAX) - return NULL; - - return color_names[color]; -} - -bool GP_ColorNameToPixel(const char *color_name, GP_PixelType pixel_type, - GP_Pixel *pixel) -{ - GP_Color color = GP_ColorNameToColor(color_name); - - if (color == GP_COL_INVALID) - return false; - - *pixel = GP_ColorToPixel(color, pixel_type); - - return true; -} - -void GP_ColorLoadPixels(GP_Pixel pixels[], GP_PixelType pixel_type) -{ - unsigned int i; - - for (i = 0; i < GP_COL_MAX; i++) - pixels[i] = GP_ColorToPixel(i, pixel_type); -} diff --git a/pylib/gfxprim/core/core.i b/pylib/gfxprim/core/core.i index ff0c062..b0aff17 100644 --- a/pylib/gfxprim/core/core.i +++ b/pylib/gfxprim/core/core.i @@ -28,12 +28,8 @@ %include "GP_Debug.h" /* - * Color and pixel types + * Pixel types */ - -ERROR_ON_NULL(GP_ColorToColorName); - -%include "GP_Color.h" %include "GP_Pixel.h" %include "GP_Pixel.gen.h" /* Includes enum GP_PixelType definition */ %include "GP_Convert.h"
http://repo.or.cz/w/gfxprim.git/commit/e42857ad289d9333411766b2df90cffea906…
commit e42857ad289d9333411766b2df90cffea906cf11 Author: Cyril Hrubis <metan(a)ucw.cz> Date: Fri Jan 16 16:14:38 2015 +0100 spiv: Add support for metadata viewer. Signed-off-by: Cyril Hrubis <metan(a)ucw.cz> diff --git a/demos/spiv/image_cache.c b/demos/spiv/image_cache.c index c030405..5f270a8 100644 --- a/demos/spiv/image_cache.c +++ b/demos/spiv/image_cache.c @@ -27,6 +27,7 @@ struct image { GP_Context *ctx; + GP_DataStorage *meta_data; struct image *prev; struct image *next; @@ -72,15 +73,23 @@ size_t image_cache_get_ram_size(void) /* * Reports correct image record size. */ -static size_t image_size2(GP_Context *ctx, const char *path) +static size_t image_size2(GP_Context *ctx, GP_DataStorage *meta_data, + const char *path) { - return ctx->bytes_per_row * ctx->h + sizeof(GP_Context) + + size_t meta_data_size = 0; + size_t context_size = ctx->bytes_per_row * ctx->h + sizeof(GP_Context); + + //TODO! 4096 is a size of single block, data storage may have more blocks + if (meta_data) + meta_data_size = 4096; + + return meta_data_size + context_size + sizeof(struct image) + strlen(path) + 1; } static size_t image_size(struct image *img) { - return image_size2(img->ctx, img->path); + return image_size2(img->ctx, NULL, img->path); } struct image_cache *image_cache_create(unsigned int max_size_kbytes) @@ -127,6 +136,7 @@ static void remove_img_free(struct image_cache *self, remove_img(self, img, size); GP_ContextFree(img->ctx); + GP_DataStorageDestroy(img->meta_data); free(img); } @@ -149,13 +159,13 @@ static void add_img(struct image_cache *self, struct image *img, size_t size) self->end = img; } -GP_Context *image_cache_get(struct image_cache *self, int elevate, - const char *key) +int image_cache_get(struct image_cache *self, GP_Context **img, + GP_DataStorage **meta_data, int elevate, const char *key) { struct image *i; if (self == NULL) - return NULL; + return 1; GP_DEBUG(2, "Looking for image '%s'", key); @@ -164,7 +174,7 @@ GP_Context *image_cache_get(struct image_cache *self, int elevate, break; if (i == NULL) - return NULL; + return 1; /* Push the image to the root of the list */ if (elevate) { @@ -178,7 +188,13 @@ GP_Context *image_cache_get(struct image_cache *self, int elevate, i->elevated++; } - return i->ctx; + if (img) + *img = i->ctx; + + if (meta_data) + *meta_data = i->meta_data; + + return 0; } GP_Context *image_cache_get2(struct image_cache *self, int elevate, @@ -268,14 +284,14 @@ static int assert_size(struct image_cache *self, size_t size) } int image_cache_put(struct image_cache *self, GP_Context *ctx, - const char *key) + GP_DataStorage *meta_data, const char *key) { size_t size; if (self == NULL) return 1; - size = image_size2(ctx, key); + size = image_size2(ctx, meta_data, key); /* * We try to create room for the image. If this fails we add the image @@ -292,6 +308,7 @@ int image_cache_put(struct image_cache *self, GP_Context *ctx, } img->ctx = ctx; + img->meta_data = meta_data; img->elevated = 0; strcpy(img->path, key); @@ -303,7 +320,7 @@ int image_cache_put(struct image_cache *self, GP_Context *ctx, } int image_cache_put2(struct image_cache *self, GP_Context *ctx, - const char *fmt, ...) + GP_DataStorage *meta_data, const char *fmt, ...) { size_t size, len; va_list va; @@ -316,7 +333,7 @@ int image_cache_put2(struct image_cache *self, GP_Context *ctx, va_end(va); //TODO: FIX THIS - size = image_size2(ctx, "") + len + 1; + size = image_size2(ctx, meta_data, "") + len + 1; /* * We try to create room for the image. If this fails we add the image @@ -333,6 +350,7 @@ int image_cache_put2(struct image_cache *self, GP_Context *ctx, } img->ctx = ctx; + img->meta_data = meta_data; img->elevated = 0; va_start(va, fmt); diff --git a/demos/spiv/image_cache.h b/demos/spiv/image_cache.h index b08ed48..f2ea1fa 100644 --- a/demos/spiv/image_cache.h +++ b/demos/spiv/image_cache.h @@ -47,8 +47,9 @@ struct image_cache *image_cache_create(unsigned int max_size_kbytes); * If elevate set and image is found, the image is elevated to the top so * it has lesser chance of being freed. */ -GP_Context *image_cache_get(struct image_cache *self, int elevate, - const char *key); +int image_cache_get(struct image_cache *self, GP_Context **img, + GP_DataStorage **meta_data, int elevate, + const char *key); GP_Context *image_cache_get2(struct image_cache *self, int elevate, const char *fmt, ...) @@ -57,11 +58,11 @@ GP_Context *image_cache_get2(struct image_cache *self, int elevate, * Puts an image into a cache. */ int image_cache_put(struct image_cache *self, GP_Context *img, - const char *key); + GP_DataStorage *meta_data, const char *key); int image_cache_put2(struct image_cache *self, GP_Context *img, - const char *fmt, ...) - __attribute__ ((format (printf, 3, 4))); + GP_DataStorage *meta_data, const char *fmt, ...) + __attribute__ ((format (printf, 4, 5))); /* * Drop all image in cache. diff --git a/demos/spiv/image_loader.c b/demos/spiv/image_loader.c index d033529..c7e0f9b 100644 --- a/demos/spiv/image_loader.c +++ b/demos/spiv/image_loader.c @@ -35,6 +35,7 @@ static struct image_cache *img_cache; static struct image_list *img_list; static GP_Context *cur_img; +static GP_DataStorage *cur_meta_data; static GP_Container *cur_cont; int image_loader_init(const char *args[], unsigned int cache_max_bytes) @@ -61,30 +62,31 @@ GP_Context *image_loader_get_image(GP_ProgressCallback *callback, int elevate) struct cpu_timer timer; const char *path; GP_Context *img; - int err; + int err, ret; if (cur_img) return cur_img; if (cur_cont) { cpu_timer_start(&timer, "Loading"); - cur_img = GP_ContainerLoad(cur_cont, callback); + cur_meta_data = GP_DataStorageCreate(); + GP_ContainerLoadEx(cur_cont, &cur_img, cur_meta_data, callback); cpu_timer_stop(&timer); return cur_img; } path = image_list_img_path(img_list); - cur_img = image_cache_get(img_cache, elevate, path); - - if (cur_img) + if (!image_cache_get(img_cache, &cur_img, &cur_meta_data, elevate, path)) return cur_img; cpu_timer_start(&timer, "Loading"); - img = GP_LoadImage(path, callback); + cur_meta_data = GP_DataStorageCreate(); - if (!img) { + ret = GP_LoadImageEx(path, &img, cur_meta_data, callback); + + if (ret) { err = errno; /* @@ -95,7 +97,7 @@ GP_Context *image_loader_get_image(GP_ProgressCallback *callback, int elevate) cur_cont = GP_OpenZip(path); if (cur_cont) { - img = GP_ContainerLoad(cur_cont, callback); + GP_ContainerLoadEx(cur_cont, &img, cur_meta_data, callback); if (img) { cur_img = img; @@ -111,13 +113,18 @@ GP_Context *image_loader_get_image(GP_ProgressCallback *callback, int elevate) return NULL; } - image_cache_put(img_cache, img, path); + image_cache_put(img_cache, img, cur_meta_data, path); cpu_timer_stop(&timer); return img; } +GP_DataStorage *image_loader_get_meta_data(void) +{ + return cur_meta_data; +} + const char *image_loader_img_path(void) { //TODO: Make this more elegant @@ -146,10 +153,13 @@ static void drop_cur_img(void) /* * Currently loaded image is too big to be cached -> free it. */ - if (!image_cache_get(img_cache, 0, path)) + if (image_cache_get(img_cache, NULL, NULL, 0, path)) { GP_ContextFree(cur_img); + GP_DataStorageDestroy(cur_meta_data); + } cur_img = NULL; + cur_meta_data = NULL; } void image_loader_seek(enum img_seek_offset offset, int whence) diff --git a/demos/spiv/image_loader.h b/demos/spiv/image_loader.h index 46b65fa..9992bca 100644 --- a/demos/spiv/image_loader.h +++ b/demos/spiv/image_loader.h @@ -49,6 +49,11 @@ int image_loader_init(const char *args[], unsigned int cache_max_bytes); GP_Context *image_loader_get_image(GP_ProgressCallback *callback, int elevate); /* + * Retruns current image meta data or NULL there are none. + */ +GP_DataStorage *image_loader_get_meta_data(void); + +/* * Returns path to current image. */ const char *image_loader_img_path(void); diff --git a/demos/spiv/spiv.c b/demos/spiv/spiv.c index 3cf212c..40a5687 100644 --- a/demos/spiv/spiv.c +++ b/demos/spiv/spiv.c @@ -213,6 +213,39 @@ static void info_printf(GP_Context *ctx, GP_Coord x, GP_Coord y, va_end(va); } +static unsigned int print_meta_data(GP_DataNode *node, GP_Context *context, + unsigned int th, unsigned int y, int level) +{ + GP_DataNode *i; + unsigned int x; + + for (i = GP_DataDictFirst(node); i; i = i->next) { + y += th; + x = th * level + 10; + switch (i->type) { + case GP_DATA_INT: + info_printf(context, x, y, "%s : %li", i->id, i->value.i); + break; + case GP_DATA_DOUBLE: + info_printf(context, x, y, "%s : %lf", i->id, i->value.d); + break; + case GP_DATA_STRING: + info_printf(context, x, y, "%s : %s", i->id, i->value.str); + break; + case GP_DATA_RATIONAL: + info_printf(context, x, y, "%s : %li/%li", + i->id, i->value.rat.num, i->value.rat.den); + break; + case GP_DATA_DICT: + info_printf(context, x, y, "%s", i->id); + y = print_meta_data(i, context, th, y, level+1); + break; + } + } + + return y; +} + static void show_info(struct loader_params *params, GP_Context *img, GP_Context *orig_img) { @@ -248,14 +281,25 @@ static void show_info(struct loader_params *params, GP_Context *img, info_printf(context, 10, y, "%u of %u", pos, count); y += th + 2; - if (!image_loader_is_in_dir()) + if (image_loader_is_in_dir()) { + unsigned int dir_count = image_loader_dir_count(); + unsigned int dir_pos = image_loader_dir_pos() + 1; + + info_printf(context, 10, y, + "%u of %u in directory", dir_pos, dir_count); + } + + GP_DataStorage *meta_data = image_loader_get_meta_data(); + + if (!meta_data) return; - unsigned int dir_count = image_loader_dir_count(); - unsigned int dir_pos = image_loader_dir_pos() + 1; + GP_DataNode *node = GP_DataStorageRoot(meta_data); + + if (node->type != GP_DATA_DICT) + return; - info_printf(context, 10, y, - "%u of %u in directory", dir_pos, dir_count); + print_meta_data(node, context, th + 2, y + th, 0); } static void update_display(struct loader_params *params, GP_Context *img, @@ -414,7 +458,7 @@ GP_Context *load_resized_image(struct loader_params *params, GP_Size w, GP_Size if (img == NULL) return NULL; - image_cache_put2(params->img_resized_cache, img, "%s %ux%u r%i l%i", + image_cache_put2(params->img_resized_cache, img, NULL, "%s %ux%u r%i l%i", img_path, w, h, params->resampling_method, params->use_low_pass); ----------------------------------------------------------------------- Summary of changes: build/syms/Core_symbols.txt | 5 - build/syms/Filters_symbols.txt | 1 + build/syms/Loaders_symbols.txt | 1 + demos/bogoman/Makefile | 2 +- demos/bogoman/bogoman.c | 7 ++ demos/c_simple/SDL_glue.c | 4 +- demos/c_simple/backend_example.c | 4 +- demos/c_simple/backend_timers_example.c | 2 +- demos/c_simple/blittest.c | 4 +- demos/c_simple/fileview.c | 12 ++-- demos/c_simple/fonttest.c | 12 ++-- demos/c_simple/input_example.c | 8 +- demos/c_simple/koch.c | 8 +- demos/c_simple/linetest.c | 4 +- demos/c_simple/randomshapetest.c | 4 +- demos/c_simple/shapetest.c | 14 ++-- demos/c_simple/textaligntest.c | 14 ++-- demos/c_simple/virtual_backend_example.c | 10 +- demos/c_simple/x11_windows.c | 4 +- demos/particle/particle_demo.c | 4 +- demos/spiv/image_cache.c | 42 +++++++--- demos/spiv/image_cache.h | 11 ++- demos/spiv/image_loader.c | 30 +++++-- demos/spiv/image_loader.h | 5 + demos/spiv/spiv.c | 111 +++++++++++++++++++++---- demos/spiv/spiv_config.c | 12 +++ demos/spiv/spiv_config.h | 5 + demos/spiv/spiv_help.c | 4 +- demos/ttf2img/ttf2img.c | 4 +- doc/basic_types.txt | 72 ---------------- doc/convert.txt | 2 - doc/core_python.txt | 9 +-- include/core/GP_Color.h | 124 --------------------------- include/core/GP_Core.h | 3 - include/loaders/GP_DataStorage.h | 11 +++ include/loaders/GP_Exif.h | 10 ++ libs/backends/GP_X11_Input.h | 3 + libs/core/GP_Color.c | 135 ------------------------------ libs/loaders/GP_DataStorage.c | 54 ++++++++++++ pylib/gfxprim/core/core.i | 6 +- 40 files changed, 324 insertions(+), 453 deletions(-) delete mode 100644 include/core/GP_Color.h delete mode 100644 libs/core/GP_Color.c repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos(a)gmail.com if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive no reply. -- gfxprim.git ("A simple 2D graphics library with emphasis on correctness and well-defined operation.")
1
0
0
0
Results per page:
10
25
50
100
200