Skip to content

Commit

Permalink
new EOS ImageFormat get/set implementation
Browse files Browse the repository at this point in the history
The current `imageformat` with it's table lookup for every RAW+JPEG
combination became cumbersome to maintain and outdated. This leads to
e.g. lost of unsupported JPEG variants for e.g. the 5Ds, R5m2, 1DX.

The used naming also became inconsistent with the addition of the 1DXm2
labels in 1402f88

This patch adds an (incompatible) new imageformat2 widget as a temporary
test to then hopefully replace the existing imageformat. I expect this new
implementation to fix all "Unknown value" occurrences of all currently
available EOS cameras.

I chose to do away with the verbose and arbitrary labels like
"Smaller Fine JPEG" and instead tried to mimic the strings that are
actually used by the cameras, like 'S2', etc. I added a 'c' for the
higher compression versions, along the lines of 'cRAW'. The 'c' could
also stand for 'coarse' to describe the blocky curve that is used by the
Canons to distinguish between lower and higher Jpeg quality.

Here is some sample output from the 5Ds:
Choice: 5 cM2
Choice: 6 S1
Choice: 7 cS1
Choice: 8 S2
Choice: 9 S3
Choice: 10 RAW + L
Choice: 11 RAW + cL
Choice: 12 RAW + M1
Choice: 13 RAW + cM1
  • Loading branch information
axxel committed Sep 27, 2024
1 parent 601734e commit 7a254b8
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 0 deletions.
107 changes: 107 additions & 0 deletions camlibs/ptp2/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -2766,6 +2766,112 @@ static struct deviceproptableu16 canon_eos_image_format[] = {
};
GENERIC16TABLE(Canon_EOS_ImageFormat,canon_eos_image_format)

static struct deviceproptableu8 canon_eos_single_ImageFormats[] = {
{ N_("RAW"), 0x0c, 0 },
{ N_("mRAW"), 0x1c, 0 },
{ N_("sRAW"), 0x2c, 0 },
{ N_("cRAW"), 0x0b, 0 },

{ N_("L"), 0x03, 0 },
{ N_("M"), 0x13, 0 },
{ N_("S"), 0x23, 0 },
{ N_("cL"), 0x02, 0 },
{ N_("cM"), 0x12, 0 },
{ N_("cS"), 0x22, 0 },
/* e.g. 5Dm3 */
{ N_("S1"), 0xd3, 0 },
{ N_("S2"), 0xe3, 0 },
{ N_("S3"), 0xf3, 0 },
{ N_("cS1"), 0xd2, 0 },
{ N_("cS2"), 0xe2, 0 },
{ N_("cS3"), 0xf2, 0 },
/* e.g. 5Ds */
{ N_("M1"), 0x53, 0 },
{ N_("M2"), 0x63, 0 },
{ N_("cM1"), 0x52, 0 },
{ N_("cM2"), 0x62, 0 },
/* user/custom compression, e.g. 1DXm2 */
{ N_("L"), 0x01, 0 },
{ N_("M1"), 0x51, 0 },
{ N_("M2"), 0x61, 0 },
{ N_("S"), 0x21, 0 },
/* user/custom compression, e.g. R5m2 */
{ N_("L"), 0x00, 0 },
{ N_("M"), 0x10, 0 },
{ N_("S1"), 0xe0, 0 },
{ N_("S2"), 0xd0, 0 },
};

static const char*
_single_EOS_ImageFormat_name(uint8_t val)
{
for (unsigned i = 0; i < ARRAYSIZE(canon_eos_single_ImageFormats); ++i)
if (canon_eos_single_ImageFormats[i].value == val)
return canon_eos_single_ImageFormats[i].label;
static char buf[5];
sprintf (buf, "0x%02x", val);
return buf;
}

static int
_get_Canon_EOS_ImageFormat2(CONFIG_GET_ARGS)
{
gp_widget_new (GP_WIDGET_RADIO, _(menu->label), widget);
gp_widget_set_name (*widget, menu->name);

for (unsigned i = 0; i < dpd->FORM.Enum.NumberOfValues; i++) {
uint16_t val = dpd->FORM.Enum.SupportedValue[i].u16;
uint8_t val1 = (val >> 8) & 0xFF;
uint8_t val2 = (val >> 0) & 0xFF;

const char* name1 = _single_EOS_ImageFormat_name(val1);
const char* name2 = _single_EOS_ImageFormat_name(val2);

char buf[12] = { 0 };
strcpy (buf, name1);
if (val2 != 0xFF)
sprintf (buf + strlen(buf), " + %s", name2);

gp_widget_add_choice (*widget, buf);

if (val == dpd->CurrentValue.u16)
gp_widget_set_value (*widget, buf);
}

return GP_OK;
}

static uint8_t
_single_EOS_ImageFormat_value(const char *name, size_t n, PTPDevicePropDesc *dpd)
{
for (unsigned i = 0; i < ARRAYSIZE(canon_eos_single_ImageFormats); ++i)
if (strncmp (canon_eos_single_ImageFormats[i].label, name, n) == 0)
for (unsigned j = 0; j < dpd->FORM.Enum.NumberOfValues; ++j)
if (dpd->FORM.Enum.SupportedValue[j].u16 >> 8 == canon_eos_single_ImageFormats[i].value)
return canon_eos_single_ImageFormats[i].value;
return 0xFF;
}

static int
_put_Canon_EOS_ImageFormat2(CONFIG_PUT_ARGS) {
const char* label;
gp_widget_get_value(widget, &label);

const char *sep = strstr(label, " + ");
size_t n = sep ? (size_t)(sep - label) : strlen(label);

uint8_t val1 = _single_EOS_ImageFormat_value(label, n, dpd);
uint8_t val2 = sep ? _single_EOS_ImageFormat_value(sep + 3, -1, dpd) : 0xFF;
if (val1 == 0xFF) {
GP_LOG_E("could not find '%s' in list of supported image formats", label);
return GP_ERROR_BAD_PARAMETERS;
}
propval->u16 = val1 << 8 | val2;
GP_LOG_D("FOUND right value for %s in the enumeration at val %04x", label, propval->u16);

return GP_OK;
}

static struct deviceproptableu16 canon_eos_aeb[] = {
{ N_("off"), 0x0000, 0 },
{ "+/- 1/3", 0x0003, 0 },
Expand Down Expand Up @@ -10941,6 +11047,7 @@ static struct submenu image_settings_menu[] = {
{ N_("Image Format"), "imageformat", PTP_DPC_CANON_EOS_ImageFormat, PTP_VENDOR_CANON, PTP_DTC_UINT16, _get_Canon_EOS_ImageFormat, _put_Canon_EOS_ImageFormat },
{ N_("Image Format SD"), "imageformatsd", PTP_DPC_CANON_EOS_ImageFormatSD, PTP_VENDOR_CANON, PTP_DTC_UINT16, _get_Canon_EOS_ImageFormat, _put_Canon_EOS_ImageFormat },
{ N_("Image Format CF"), "imageformatcf", PTP_DPC_CANON_EOS_ImageFormatCF, PTP_VENDOR_CANON, PTP_DTC_UINT16, _get_Canon_EOS_ImageFormat, _put_Canon_EOS_ImageFormat },
{ N_("Image Format 2"), "imageformat2", PTP_DPC_CANON_EOS_ImageFormat, PTP_VENDOR_CANON, PTP_DTC_UINT16, _get_Canon_EOS_ImageFormat2, _put_Canon_EOS_ImageFormat2 },
{ N_("Image Format"), "imageformat", PTP_DPC_FUJI_Quality, PTP_VENDOR_FUJI, PTP_DTC_UINT16, _get_Fuji_ImageFormat, _put_Fuji_ImageFormat },
{ N_("Image Format"), "imageformat", 0, PTP_VENDOR_PANASONIC,PTP_DTC_UINT16, _get_Panasonic_ImageFormat, _put_Panasonic_ImageFormat },
{ N_("Image Format Ext HD"), "imageformatexthd", PTP_DPC_CANON_EOS_ImageFormatExtHD, PTP_VENDOR_CANON, PTP_DTC_UINT16, _get_Canon_EOS_ImageFormat, _put_Canon_EOS_ImageFormat },
Expand Down
2 changes: 2 additions & 0 deletions camlibs/ptp2/ptp-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ inline static int log_on_ptp_error_helper( int _r, const char* _func, const char
}\
} while (0)

#define ARRAYSIZE(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0]))

static inline int
is_canon_eos_m(PTPParams *params) {
if (params->deviceinfo.VendorExtensionID != PTP_VENDOR_CANON) return 0;
Expand Down

0 comments on commit 7a254b8

Please sign in to comment.