diff --git a/camlibs/ptp2/config.c b/camlibs/ptp2/config.c index cf819fdf5..728098449 100644 --- a/camlibs/ptp2/config.c +++ b/camlibs/ptp2/config.c @@ -2687,20 +2687,20 @@ GENERIC16TABLE(Canon_ISO,canon_isospeed) /* see ptp-pack.c:ptp_unpack_EOS_ImageFormat */ static struct deviceproptableu16 canon_eos_image_format[] = { - { N_("RAW"), 0x0c00, 0 }, - { N_("mRAW"), 0x1c00, 0 }, - { N_("sRAW"), 0x2c00, 0 }, - { N_("cRAW"), 0x0b00, 0 }, - { N_("Large Fine JPEG"), 0x0300, 0 }, - { N_("Large Normal JPEG"), 0x0200, 0 }, - { N_("Medium Fine JPEG"), 0x1300, 0 }, - { N_("Medium Normal JPEG"), 0x1200, 0 }, - { N_("Small Fine JPEG"), 0x2300, 0 }, - { N_("Small Normal JPEG"), 0x2200, 0 }, - { N_("Small Fine JPEG"), 0xd300, 0 }, - { N_("Small Normal JPEG"), 0xd200, 0 }, - { N_("Smaller JPEG"), 0xe300, 0 }, - { N_("Tiny JPEG"), 0xf300, 0 }, + { N_("RAW"), 0x0cff, 0 }, + { N_("mRAW"), 0x1cff, 0 }, + { N_("sRAW"), 0x2cff, 0 }, + { N_("cRAW"), 0x0bff, 0 }, + { N_("Large Fine JPEG"), 0x03ff, 0 }, + { N_("Large Normal JPEG"), 0x02ff, 0 }, + { N_("Medium Fine JPEG"), 0x13ff, 0 }, + { N_("Medium Normal JPEG"), 0x12ff, 0 }, + { N_("Small Fine JPEG"), 0x23ff, 0 }, + { N_("Small Normal JPEG"), 0x22ff, 0 }, + { N_("Small Fine JPEG"), 0xd3ff, 0 }, + { N_("Small Normal JPEG"), 0xd2ff, 0 }, + { N_("Smaller JPEG"), 0xe3ff, 0 }, + { N_("Tiny JPEG"), 0xf3ff, 0 }, { N_("RAW + Large Fine JPEG"), 0x0c03, 0 }, { N_("mRAW + Large Fine JPEG"), 0x1c03, 0 }, { N_("sRAW + Large Fine JPEG"), 0x2c03, 0 }, @@ -2741,10 +2741,10 @@ static struct deviceproptableu16 canon_eos_image_format[] = { /* There are more RAW + 'smallish' JPEG combinations for at least the 5DM3 possible. Axel was simply to lazy to exercise the combinatorial explosion. :-/ */ /* 1DX series 0 compression options */ - { N_("Small"), 0x2100, 0 }, - { N_("Medium 1"), 0x5100, 0 }, - { N_("Medium 2"), 0x6100, 0 }, - { N_("Large"), 0x0100, 0 }, + { N_("Small"), 0x21ff, 0 }, + { N_("Medium 1"), 0x51ff, 0 }, + { N_("Medium 2"), 0x61ff, 0 }, + { N_("Large"), 0x01ff, 0 }, { N_("Small + RAW"), 0x0c21, 0 }, { N_("Medium 1 + RAW"), 0x0c51, 0 }, { N_("Medium 2 + RAW"), 0x0c61, 0 }, diff --git a/camlibs/ptp2/ptp-pack.c b/camlibs/ptp2/ptp-pack.c index 5d7fbed37..f1e41bf30 100644 --- a/camlibs/ptp2/ptp-pack.c +++ b/camlibs/ptp2/ptp-pack.c @@ -1407,37 +1407,48 @@ static inline uint16_t ptp_unpack_EOS_ImageFormat (PTPParams* params, const unsigned char** data ) { /* - EOS ImageFormat entries (of at least the 5DM2 and the 400D) look like this: - uint32: number of entries / generated files (1 or 2) - uint32: size of this entry in bytes (most likely always 0x10) - uint32: image type (1 == JPG, 6 == RAW) - uint32: image size (0 == Large, 1 == Medium, 2 == Small, 0xe == S1, 0xf == S2, 0x10 == S3) - uint32: image compression (2 == Standard/JPG, 3 == Fine/JPG, 4 == Lossles/RAW) - If the number of entries is 2 the last 4 uint32 repeat. - - example: - 0: 0x 1 - 1: 0x 10 - 2: 0x 6 - 3: 0x 1 - 4: 0x 4 + EOS ImageFormat entries look are a sequence of u32 values: + 0: number of entries / generated files (1 or 2) + 1: size of this entry in bytes (most likely always 0x10 = 4 x u32) + 2: image type: + 1 == JPG + 6 == RAW + 3: image size: + 0 == L + 1 == M + 2 == S + 5 == M1 (e.g. 5Ds) + 6 == M2 + e == S1 (e.g. 5Dm3) + f == S2 + 10 == S3 + 4: image compression: + 0 == user: JPG (e.g. 1DX, R5m2) + 1 == ???: JPG (e.g. 1DXm2, 1DXm3) + 2 == coarse: JPG (all) + 3 == fine: JPG/cRAW (all) + 4 == lossless: RAW (all) + + If the number of entries is 2 the values 1-4 repeat + + example (cRAW + coarse S1 JPEG): 2 10 6 0 3 10 1 e 2 The idea is to simply 'condense' these values to just one uint16 to be able to conveniently - use the available enumeration facilities (look-up table). The image size and compression - values used to fully describe the image format, but at least since EOS M50 (with cRAW) - it is no longer true - we need to store RAW flag (8). - Hence we generate a uint16 with the four nibles set as follows: + use the available enumeration facilities (look-up table). + Hence we generate a u16 value with the four nibles set as follows: - entry 1 size | entry 1 compression & RAW flag | entry 2 size | entry 2 compression & RAW flag. + entry 1 size | entry 1 type + compression | entry 2 size | entry 2 type + compression. - The above example would result in the value 0x1400. + * The S3 value (0xf) would overflow the nible, hence we decrease all S1,S2,S3 values by 1. + * The to encode the type RAW, we set the 4th bit in the compression nible to 1 (|= 8). + * To distinguish an "empty" second entry from the "custom L JPEG", we set it to 0xff. - The EOS 5D Mark III (and possibly other high-end EOS as well) added the extra fancy S1, S2 - and S3 JPEG options. S1 replaces the old Small. -1 the S1/S2/S3 to prevent the 0x10 overflow. - */ + The above example would result in the value 0x0bd2. + */ - const unsigned char* d = *data; - uint32_t n = dtoh32a( d ); + const uint8_t* d = *data; + uint32_t offset = 0; + uint32_t n = dtoh32o (d, offset); uint32_t l, t1, s1, c1, t2 = 0, s2 = 0, c2 = 0; if (n != 1 && n !=2) { @@ -1445,28 +1456,28 @@ ptp_unpack_EOS_ImageFormat (PTPParams* params, const unsigned char** data ) return 0; } - l = dtoh32a( d+=4 ); + l = dtoh32o (d, offset); if (l != 0x10) { ptp_debug (params, "parsing EOS ImageFormat property failed (l != 0x10: 0x%x)", l); return 0; } - t1 = dtoh32a( d+=4 ); - s1 = dtoh32a( d+=4 ); - c1 = dtoh32a( d+=4 ); + t1 = dtoh32o (d, offset); + s1 = dtoh32o (d, offset); + c1 = dtoh32o (d, offset); if (n == 2) { - l = dtoh32a( d+=4 ); + l = dtoh32o (d, offset); if (l != 0x10) { ptp_debug (params, "parsing EOS ImageFormat property failed (l != 0x10: 0x%x)", l); return 0; } - t2 = dtoh32a( d+=4 ); - s2 = dtoh32a( d+=4 ); - c2 = dtoh32a( d+=4 ); + t2 = dtoh32o (d, offset); + s2 = dtoh32o (d, offset); + c2 = dtoh32o (d, offset); } - *data = (unsigned char*) d+4; + *data += offset; /* deal with S1/S2/S3 JPEG sizes, see above. */ if( s1 >= 0xe ) @@ -1478,31 +1489,35 @@ ptp_unpack_EOS_ImageFormat (PTPParams* params, const unsigned char** data ) c1 |= (t1 == 6) ? 8 : 0; c2 |= (t2 == 6) ? 8 : 0; + if (s2 == 0 && c2 == 0) + s2 = c2 = 0xF; + return ((s1 & 0xF) << 12) | ((c1 & 0xF) << 8) | ((s2 & 0xF) << 4) | ((c2 & 0xF) << 0); } static inline uint32_t ptp_pack_EOS_ImageFormat (PTPParams* params, unsigned char* data, uint16_t value) { - uint32_t n = (value & 0xFF) ? 2 : 1; + uint32_t n = (value & 0xFF) == 0xFF ? 1 : 2; uint32_t s = 4 + 0x10 * n; if( !data ) return s; -#define PACK_5DM3_SMALL_JPEG_SIZE( X ) (X) >= 0xd ? (X)+1 : (X) +#define PACK_EOS_S123_JPEG_SIZE( X ) (X) >= 0xd ? (X)+1 : (X) htod32a(data+=0, n); + htod32a(data+=4, 0x10); - htod32a(data+=4, (((value >> 8) & 0xF) >> 3) ? 6 : 1); - htod32a(data+=4, PACK_5DM3_SMALL_JPEG_SIZE((value >> 12) & 0xF)); - htod32a(data+=4, ((value >> 8) & 0xF) & ~8); + htod32a(data+=4, value & 0x0800 ? 6 : 1); + htod32a(data+=4, PACK_EOS_S123_JPEG_SIZE((value >> 12) & 0xF)); + htod32a(data+=4, (value >> 8) & 0x7); if (n==2) { htod32a(data+=4, 0x10); - htod32a(data+=4, (((value >> 0) & 0xF) >> 3) ? 6 : 1); - htod32a(data+=4, PACK_5DM3_SMALL_JPEG_SIZE((value >> 4) & 0xF)); - htod32a(data+=4, ((value >> 0) & 0xF) & ~8); + htod32a(data+=4, value & 0x08 ? 6 : 1); + htod32a(data+=4, PACK_EOS_S123_JPEG_SIZE((value >> 4) & 0xF)); + htod32a(data+=4, (value >> 0) & 0x7); } #undef PACK_5DM3_SMALL_JPEG_SIZE