A pixel format reaches your code as a number more often than as a string: a PFNC constant such as 0x01080002 sits in a config file, a database row or a hardware abstraction layer, while the camera only ever accepts Mono8. Passing the integer straight at the enumeration fails, and hard-coding the string skips the one check that matters — whether this camera actually lists the format. This how-to gives you the lookup that resolves any integer through the device's own enumeration, the guards it needs, and the bandwidth arithmetic that tells you which format your link survives.
Why does a GenICam enumeration refuse to take an integer?
GenICam standardizes the symbolic string of every enumeration entry — Mono8, BayerRG8, RGB8 — and leaves the integer values unstandardized, with one exception: pixel formats follow the PFNC companion standard, which fixes constants such as 0x01080002 for Mono8.
That asymmetry is why a GenICam client library exposes only a string version of SetValue on an enumeration node: a numeric setter would promise behavior the standard does not define. The Standard Features Naming Convention (SFNC) fixes the feature names and their symbolics; on top of it, the Pixel Format Naming Convention (PFNC) assigns one integer constant per named pixel format — the GenICam standards page hosted by the EMVA is the source — so 0x01080002 means Mono8 on every compliant device. For a trigger selector or a user-set selector no PFNC exists, and the same integer can name different modes on different devices.
The bridge between your integer and the accepted string is the device itself. Its node map lists every entry with two values: a numeric value and a symbolic value. Your job is a lookup against that list, not a conversion table kept in your code — the device's list already knows what this camera offers. When an enumeration rejects a value outright, the companion article GenICam enumeration invalid value: check symbolics before you set covers the readback-side diagnosis.
How do you turn a PFNC integer into a symbolic string?
You resolve the code against the device's own entry list: fetch the enumeration's entries, match the entry whose numeric value equals your integer, and set the symbolic value of that entry. A code that matches nothing means the camera does not offer the format, so you fail the call instead of guessing.
Run the lookup once, right after you open the device and before you start streaming — the same initialization order a manual exposure setting needs. Then:
- Read the PixelFormat node from the device's node map; SFNC gives every GenICam device this feature name.
- Cast the node to the enumeration interface your library provides — the entry list lives there.
- Hold your code as a 64-bit signed integer and compare it against each entry's numeric value.
- Keep the matching entry's symbolic string; stop with an error if no entry matches or the string comes back empty.
- Call the enumeration's SetValue with that symbolic string.
- Read the node back and check the first delivered frame before you trust the set.
Treat the entry list as the authority on availability. Two cameras built around the same sensor can enumerate different format lists, and no listing page shows which formats a device offers — only the node map does.
What does the integer-to-symbolic lookup look like in code?
The pattern is one search over the entries plus two guards: match on the 64-bit numeric value, refuse an empty symbolic, and return failure when nothing matches. The single standardized call in the whole path is SetValue with a string.
// Illustrative spellings: every GenICam client library exposes the same three
// parts — an enumeration interface, its entry list, and per-entry numeric and
// symbolic values. Match the names to your SDK's enumeration node.
bool SetPixelFormatByCode(std::int64_t code, EnumNode& fmt)
{
const auto entries = fmt.Entries(); // the device's own table
if (entries.empty())
return false; // no entries, nothing to match
const auto match = std::find_if(entries.begin(), entries.end(),
[code](const EnumEntryPtr& e) { return e->NumericValue() == code; });
if (match == entries.end())
return false; // this camera lacks the format
if (match->SymbolicValue().empty())
return false; // entry carries no symbolic
fmt.SetValue(match->SymbolicValue()); // the standardized string call
return true;
}
Prove the result with a readback:
// Test: resolve 0x01080002 and prove what the camera took.
assert(SetPixelFormatByCode(0x01080002, pixelFormat));
assert(pixelFormat.CurrentSymbolic() == "Mono8"); // readback names illustrative
assert(pixelFormat.CurrentNumeric() == 0x01080002);
How much bandwidth does each pixel format need?
The format sets your payload: a 4000 × 3000 Mono8 frame carries 12 MB, so 30 fps needs 360 MB/s — about three times the 125 MB/s a GigE link offers, and just inside the 400–450 MB/s USB 3 delivers in practice.
The bases, so you can re-derive for your own resolution: a GigE link runs at 1 Gbit/s, which is 125 MB/s of line rate before protocol overhead, so the real cap sits a few percent lower. USB 3 runs a 5 Gbit/s line with 8b/10b coding — theoretical payload near 500 MB/s, about 400–450 MB/s delivered in practice. Both rates are payload only; packet headers and driver copies come on top.
| Pixel format | PFNC constant | Bytes per pixel | Frame at 4000 × 3000 | GigE cap | USB 3 cap |
|---|---|---|---|---|---|
| Mono8 | 0x01080002 | 1 | 12 MB | about 10 fps | about 37 fps |
| RGB8 | 0x02180014 | 3 | 36 MB | about 3 fps | about 12 fps |
The decisions follow directly. Mono8 at 30 fps fits USB 3 with margin and does not fit GigE, where the camera settles near 10 fps. RGB8 at full rate — 1,080 MB/s — fits neither link: move to 10GigE or CoaXPress, or drop to about 12 fps on USB 3. The same arithmetic sizes your buffers and the converter stages downstream, which read the numeric value too.
The camera behind these numbers streams 4000 × 3000 at 30 fps over USB3 at 12 MP resolution: the LS-CMR-0166.
- Sensor format
- 1/1.7"
- Interface
- USB3
- Resolution
- 12 MP
- Shutter
- Rolling
How do you prove the format took effect?
Verify in two places: the node reports the new symbolic and its numeric value on readback, and the first delivered buffer matches the size the format predicts — 12,000,000 bytes for a 4000 × 3000 Mono8 frame.
A mismatch is a diagnosis, not just a failure. A buffer of 36,000,000 bytes means an RGB format is still active somewhere in the chain; 18,000,000 bytes points at a packed 12-bit format that stores 1.5 bytes per pixel. If your pipeline converts pixels before processing, run the same size check on the converted object — converted image object pixel format: verify before processing walks through that step. And when a color camera delivers mono images, the pixel format default is the first suspect: GigE camera shows no color image: fix the pixel format default.
When is setting an integer directly the wrong move?
The moment the enumeration is anything other than PixelFormat, the integer is device-specific: trigger selectors, user-set selectors, line sources and vendor extensions standardize only their symbolics, so a hardcoded integer maps correctly on one camera and fails or mis-sets on the next.
Even where your library accepts an integer on such an enumeration, the camera receives the problem: it answers with a generic error or, worse, applies a silently wrong mode. Resolve against the entries as in the function above and the failure lands in your code with a clear message instead. Trigger settings are the usual offender — camera trigger mode source readback mismatches: find the real value shows a readback disagreeing with the value you set.
For configuration storage, keep one rule: PFNC constants for PixelFormat are safe to store and resolve at run time, because the standard fixes the mapping; every other enumeration gets stored as its symbolic string.
The wider set of node-map checks lives on the systems topic page.
Which hardware exposes this pattern?
Every GenICam device you program this way exposes the same node map and the same PixelFormat feature: GigE and USB3 area scan cameras directly, CoaXPress and Camera Link setups through a frame grabber's own node map, all driven by the client running on your vision controller.
The two cameras below cover both interfaces: the MV-CU020-90GC is a 2.5 MP color GigE model with a global shutter, and the MV-CS200-10UM is a 20 MP mono USB3 model.
- Sensor format
- 1/1.7"
- Lens mount
- C-mount
- Sensor format
- 1"
- Lens mount
- C-mount
When the camera sits behind a frame grabber, run the same lookup against the grabber's node map; the frame grabbers category lists the cards. The client itself lives on a vision controller with enough LAN ports for the camera count, and the area scan cameras category with its camera finder narrows models by interface, shutter and resolution.
The configurator matches a camera, lens, light, light controller and cables to each other, step by step, and lists only parts that fit what you already picked.
Next step: dump your camera's PixelFormat entries once and keep the list with the project — it is the ground truth every format decision checks against. Size the link with the table above, start the configurator here, and send the list to us through the contact page when a format choice needs a second opinion.
Questions
Does 0x01080002 mean Mono8 on every camera?
For PixelFormat, yes where the camera follows PFNC: the standard assigns Mono8 the constant 0x01080002, and compliant devices print the same integer for the same named format. That guarantee covers pixel formats only. Trigger selectors, user sets, test patterns and other enumerations have no standardized integers, so their numbers can differ between vendors and models — resolve those from the device's entries at runtime, never from a table.
What happens if the camera does not list the format my integer maps to?
Your lookup finds no entry whose numeric value matches, so the correct behavior is to fail before calling SetValue — log the code and the camera's available symbolics. The device's enumeration is the authority: a 12-bit sensor may not offer Mono8, and some color sensors skip packed formats. Never fall back to a numeric or string guess; pick a supported format deliberately.
How do I check the pixel format from the delivered image alone?
Ignore the node and read the bytes: width × height × bytes per pixel predicts the buffer size, so a 4000 × 3000 Mono8 frame must be 12,000,000 bytes. Receiving 36,000,000 means RGB8 or another 3-byte format is active; 18,000,000 means a packed 12-bit format. Measure the first frame after every configuration change — it catches fallbacks a readback can miss.
Why do pixel formats get integers at all if only strings are standardized?
Because pixel formats follow PFNC, a GenICam companion specification that defines one integer constant per named format. The integers let host software size buffers, build converters and match formats across SDKs without string parsing. Other SFNC features standardize only the symbolic strings, which is why a string-only SetValue is the general rule and the numeric lookup is the safe pattern for codes you hold as integers.


