IDS peak genericC++ v1.17.0
Loading...
Searching...
No Matches
peak_image_view_impl.hpp
Go to the documentation of this file.
1
6
7#pragma once
8
9#include "peak_image_view.hpp"
10
12
15
22
23#include <memory>
24
25namespace peak
26{
27namespace core
28{
29
30namespace detail
31{
32constexpr uint64_t usableRoiChunkId = 0x73020405;
33constexpr uint64_t imageChunkId = 0x73688300;
34
36{
37 uint16_t usableWidth{};
38 uint16_t usableHeight{};
39 uint16_t offsetX{};
40 uint16_t offsetY{};
41};
42
44 const std::shared_ptr<peak::core::BufferChunk>& chunk)
45{
46 if (chunk->ID() != usableRoiChunkId)
47 {
48 throw core::InternalErrorException("Cannot extract usable roi chunk info from chunk with wrong ID!");
49 }
50
51 const auto* base = static_cast<uint16_t*>(chunk->BasePtr());
52 return { base[0], base[1], base[2], base[3] };
53}
54
55PEAK_COMMON_NO_DISCARD inline std::shared_ptr<core::BufferChunk> FindBufferChunkById(
56 const std::vector<std::shared_ptr<peak::core::BufferChunk>>& chunks, uint64_t chunkId)
57{
58 const auto it = std::find_if(
59 chunks.cbegin(), chunks.cend(), [chunkId](const auto& chunk) { return chunk->ID() == chunkId; });
60 if (it == chunks.cend())
61 {
62 return nullptr;
63 }
64 return *it;
65}
66
69 const std::vector<std::shared_ptr<peak::core::BufferChunk>>& chunks)
70{
71 const auto imageChunk = FindBufferChunkById(chunks, imageChunkId);
72 if (imageChunk == nullptr)
73 {
74 throw core::InternalErrorException("Buffer has no image chunk.");
75 }
76
77 const auto imageSizeWithPaddingWithoutChunks = imageChunk->Size();
78
79 const auto usableRoiChunk = FindBufferChunkById(chunks, usableRoiChunkId);
80 if (usableRoiChunk == nullptr)
81 {
82 return payload;
83 }
84
85 ExtractedPayload result{ payload };
86
87 const auto chunkInfo = ExtractUsableRoiChunkInfo(usableRoiChunk);
88
89 result.size = peak::common::Size{ chunkInfo.usableWidth, chunkInfo.usableHeight };
90
91 auto buffer = imageChunk->ParentBuffer();
92 if (result.bytesPerLine != imageSizeWithPaddingWithoutChunks / buffer->Height())
93 {
94 throw core::InternalErrorException("Unexpected pitch!");
95 }
96
97 const auto bytesToSkip = result.bytesPerLine * chunkInfo.offsetY;
98 result.dataPtr = static_cast<void*>(static_cast<uint8_t*>(result.dataPtr) + bytesToSkip);
99
100 const peak::common::PixelFormatInfo pixelFormatInfo(result.pixelFormat);
101 result.lineStartOffset = pixelFormatInfo.GetSizeInBytes({ chunkInfo.offsetX, 1 });
102 result.dataSize = pixelFormatInfo.GetSizeInBytes(
103 { static_cast<uint32_t>(buffer->Width()), chunkInfo.usableHeight });
104 if (result.dataSize > imageSizeWithPaddingWithoutChunks)
105 {
106 throw core::InternalErrorException("Chunk size is not large enough to fit the expected image size!");
107 }
108
109 return result;
110}
111
113 const std::shared_ptr<peak::core::Buffer>& buffer)
114{
115 assert(buffer->PixelFormatNamespace() != core::PixelFormatNamespace::IIDC
116 && buffer->PixelFormatNamespace() != core::PixelFormatNamespace::Custom);
117
118 ExtractedPayload result{};
119
120 result.size = { static_cast<uint32_t>(buffer->Width()), static_cast<uint32_t>(buffer->Height()) };
121 result.pixelFormat = static_cast<peak::common::PixelFormat>(buffer->PixelFormat());
122 result.dataPtr = static_cast<uint8_t*>(buffer->BasePtr()) + buffer->ImageOffset();
123
124 const auto pixelFormatInfo = peak::common::PixelFormatInfo(result.pixelFormat);
125
126 result.bytesPerLine = pixelFormatInfo.GetSizeInBytes({ static_cast<uint32_t>(buffer->Width()), 1 });
127 result.lineStartOffset = 0;
128 result.dataSize = pixelFormatInfo.GetSizeInBytes(
129 { static_cast<uint32_t>(buffer->Width()), static_cast<uint32_t>(buffer->Height()) });
130
131 const auto imageSizeWithPadding = buffer->Size() - buffer->ImageOffset();
132 if (result.dataSize > imageSizeWithPadding)
133 {
134 throw core::InternalErrorException("Buffer is not large enough to fit the expected image size!");
135 }
136
137 if (buffer->HasChunks())
138 {
139 result = UpdatePayloadInfoWithChunks(result, buffer->Chunks());
140 }
141
142 return result;
143}
144
146 const std::shared_ptr<peak::core::Buffer>& buffer)
147{
148 const auto remoteNodeMap = buffer->ParentDataStream()->ParentDevice()->RemoteDevice()->NodeMaps().at(0);
149 remoteNodeMap->UpdateChunkNodes(buffer);
150
151 const auto chunkWidth = remoteNodeMap->TryFindNode<core::nodes::IntegerNode>("ChunkWidth");
152 if (chunkWidth == nullptr || chunkWidth->AccessStatus() == core::nodes::NodeAccessStatus::NotAvailable)
153 {
154 throw core::InvalidCastException("Buffer has no ChunkWidth.");
155 }
156
157 const auto chunkHeight = remoteNodeMap->TryFindNode<core::nodes::IntegerNode>("ChunkHeight");
158 if (chunkHeight == nullptr || chunkHeight->AccessStatus() == core::nodes::NodeAccessStatus::NotAvailable)
159 {
160 throw core::InvalidCastException("Buffer has no ChunkHeight.");
161 }
162
163 const peak::common::Size size(
164 static_cast<uint32_t>(chunkWidth->Value()), static_cast<uint32_t>(chunkHeight->Value()));
165
166 const auto chunkPixelFormat = remoteNodeMap->TryFindNode<core::nodes::EnumerationNode>("ChunkPixelFormat");
167 if (chunkPixelFormat == nullptr || chunkPixelFormat->AccessStatus() == core::nodes::NodeAccessStatus::NotAvailable)
168 {
169 throw core::InvalidCastException("Buffer has no ChunkPixelFormat.");
170 }
171
172 const auto pixelFormat = static_cast<peak::common::PixelFormat>(
173 chunkPixelFormat->CurrentEntry()->NumericValue());
174
175 // assume first chunks is image data
176 const auto imageChunk = FindBufferChunkById(buffer->Chunks(), imageChunkId);
177 if (imageChunk == nullptr)
178 {
179 throw core::InternalErrorException("Buffer has no image chunk.");
180 }
181
182 const auto sizeInBytes = imageChunk->Size();
183
184 const auto pixelFormatInfo = peak::common::PixelFormatInfo(pixelFormat);
185 const auto expectedDataSize = pixelFormatInfo.GetSizeInBytes(size);
186 if (sizeInBytes < expectedDataSize)
187 {
188 std::stringstream msg;
189 msg << "The buffer's first chunk's size (" << imageChunk->Size() << ") is smaller than the expected data size ("
190 << expectedDataSize << ").";
191 throw core::InvalidCastException(msg.str());
192 }
193
194 return { size, pixelFormat, imageChunk->BasePtr(), sizeInBytes,
195 pixelFormatInfo.GetSizeInBytes(peak::common::Size(size.GetWidth(), 1)), 0 };
196}
197
199 const std::shared_ptr<peak::core::BufferPart>& part)
200{
201 if (part == nullptr)
202 {
203 throw core::InvalidArgumentException("The given part is a nullptr!");
204 }
205
206 const auto partType = part->Type();
207
208 if (partType != BufferPartType::Image2D && partType != BufferPartType::ConfidenceMap
209 && partType != BufferPartType::Image3D)
210 {
211 throw core::InvalidCastException("BufferPart has no image data.");
212 }
213
214 assert(part->FormatNamespace() != static_cast<uint64_t>(core::PixelFormatNamespace::IIDC)
215 && part->FormatNamespace() != static_cast<uint64_t>(core::PixelFormatNamespace::Custom));
216
217 const auto pixelFormat = static_cast<peak::common::PixelFormat>(part->Format());
218 const auto bytesPerLine = peak::common::PixelFormatInfo(pixelFormat)
219 .GetSizeInBytes({ static_cast<uint32_t>(part->Width()), 1 });
220 return { peak::common::Size{ static_cast<uint32_t>(part->Width()), static_cast<uint32_t>(part->Height()) },
221 pixelFormat, part->BasePtr(), part->Size(), bytesPerLine, 0 };
222}
223
225 const std::shared_ptr<peak::core::Buffer>& buffer)
226{
227 if (buffer == nullptr)
228 {
229 throw core::InvalidArgumentException("The given buffer is a nullptr!");
230 }
231
232 if (buffer->HasImage())
233 {
234 return ExtractPayloadTypeImage(buffer);
235 }
236
237 if (buffer->PayloadType() == core::BufferPayloadType::Chunk)
238 {
239 return ExtractPayloadTypeChunk(buffer);
240 }
241
242 throw core::InvalidCastException("Buffer has no image data and no chunks.");
243}
244
245PEAK_COMMON_NO_DISCARD inline std::shared_ptr<peak::common::Metadata> ExtractMetadataFromBuffer(
246 const std::shared_ptr<peak::core::Buffer>& buffer, MetadataExtractionMode mode)
247{
248 if (buffer == nullptr)
249 {
250 throw core::InvalidArgumentException("The given buffer is a nullptr!");
251 }
252
253 auto metadata = std::make_shared<peak::common::Metadata>();
254
255 // NOTE: BUFFER_INFO_FRAMEID is a mandatory GenTL feature. It MUST be implemented.
256 metadata->SetValueByKey<peak::common::MetadataKey::DeviceFrameID>(buffer->FrameID());
257
258 // NOTE: We need to try, as the timestamp might not be supported by the TL.
259 try
260 {
261 metadata->SetValueByKey<peak::common::MetadataKey::DeviceTimestamp>(buffer->Timestamp_ns());
262 }
263 catch (const peak::core::Exception&)
264 {}
265
266 // NOTE: The system timestamp is optional and may not be supported by the TL or device.
267 try
268 {
269 metadata->SetValueByKey<peak::common::MetadataKey::SystemTimestamp>(buffer->SystemTimestamp_ns());
270 }
271 catch (const peak::core::Exception&)
272 {}
273
275 {
276 return metadata;
277 }
278
279 // MetadataExtractionMode::Extended
280
281 const auto remoteNodeMap = buffer->ParentDataStream()->ParentDevice()->RemoteDevice()->NodeMaps().at(0);
282 const auto chunkExposureTimeNode = remoteNodeMap->TryFindNode<nodes::FloatNode>("ChunkExposureTime");
283 const auto chunkGainSelectorNode = remoteNodeMap->TryFindNode<nodes::EnumerationNode>("ChunkGainSelector");
284 const auto chunkGainNode = remoteNodeMap->TryFindNode<nodes::FloatNode>("ChunkGain");
285
286 const auto lock = remoteNodeMap->Lock();
287 remoteNodeMap->UpdateChunkNodes(buffer);
288
289 if (chunkExposureTimeNode != nullptr && chunkExposureTimeNode->IsReadable())
290 {
291 metadata->SetValueByKey<peak::common::MetadataKey::DeviceExposureTime>(chunkExposureTimeNode->Value());
292 }
293
294 if (chunkGainSelectorNode != nullptr && chunkGainSelectorNode->AccessStatus() == nodes::NodeAccessStatus::ReadWrite
295 && chunkGainNode != nullptr)
296 {
297 const auto availableEntries = chunkGainSelectorNode->AvailableEntries();
298
299 bool found = false;
300 auto readChunkGain = [&](const std::string& entryName) {
301 const auto entry = chunkGainSelectorNode->TryFindEntry(entryName);
302 if (entry == nullptr || !entry->IsAvailable())
303 {
304 return 1.0;
305 }
306
307 chunkGainSelectorNode->SetCurrentEntry(entry);
308 if (!chunkGainNode->IsReadable())
309 {
310 return 1.0;
311 }
312 found = true;
313 return chunkGainNode->Value();
314 };
315
316 const auto gainAll = readChunkGain("All");
317 const auto gainAnalogAll = readChunkGain("AnalogAll");
318 const auto gainDigitalAll = readChunkGain("DigitalAll");
319
320 if (found)
321 {
322 metadata->SetValueByKey<peak::common::MetadataKey::DeviceGain>(
323 gainAll * gainAnalogAll * gainDigitalAll);
324 }
325 }
326
327 return metadata;
328}
329
330} // namespace detail
331
333 const detail::ExtractedPayload& payload, std::shared_ptr<peak::common::Metadata> metadata)
334 : m_metadata{ std::move(metadata) }
335 , m_payload{ payload }
336{}
337
338inline ImageView::ImageView(const std::shared_ptr<peak::core::Buffer>& buffer)
339 : ImageView(detail::ExtractPayloadFromBuffer(buffer),
340 detail::ExtractMetadataFromBuffer(buffer, MetadataExtractionMode::Minimal))
341{
342 m_parentBuffer = buffer;
343}
344
345inline ImageView::ImageView(const std::shared_ptr<Buffer>& buffer, MetadataExtractionMode mode)
346 : ImageView(detail::ExtractPayloadFromBuffer(buffer), detail::ExtractMetadataFromBuffer(buffer, mode))
347{
348 m_parentBuffer = buffer;
349}
350
351inline ImageView::ImageView(const std::shared_ptr<core::BufferPart>& part)
352 : ImageView(detail::ExtractPayloadFromBufferPart(part),
353 detail::ExtractMetadataFromBuffer(part->ParentBuffer(), MetadataExtractionMode::Minimal))
354{
355 m_parentBuffer = part->ParentBuffer();
356}
357
358inline ImageView::ImageView(const std::shared_ptr<core::BufferPart>& part, MetadataExtractionMode mode)
359 : ImageView(
360 detail::ExtractPayloadFromBufferPart(part), detail::ExtractMetadataFromBuffer(part->ParentBuffer(), mode))
361{
362 m_parentBuffer = part->ParentBuffer();
363}
364
365inline const uint8_t* ImageView::GetData() const
366{
367 return static_cast<uint8_t*>(m_payload.dataPtr);
368}
369
370inline uint8_t* ImageView::GetData()
371{
372 return static_cast<uint8_t*>(m_payload.dataPtr);
373}
374
375inline std::size_t ImageView::GetLineStartOffset() const
376{
377 return m_payload.lineStartOffset;
378}
379
380inline std::size_t ImageView::GetSizeInBytes() const
381{
382 return m_payload.dataSize;
383}
384
386{
387 return m_payload.pixelFormat;
388}
389
391{
392 return peak::common::PixelFormatInfo(m_payload.pixelFormat);
393}
394
396{
397 return m_payload.size;
398}
399
400inline uint32_t ImageView::GetWidth() const
401{
402 return m_payload.size.GetWidth();
403}
404
405inline uint32_t ImageView::GetHeight() const
406{
407 return m_payload.size.GetHeight();
408}
409
410inline size_t ImageView::GetBitsPerPixel() const
411{
412 return peak::common::PixelFormatInfo(m_payload.pixelFormat).GetAllocatedBitsPerPixel();
413}
414
415inline size_t ImageView::GetBytesPerLine() const
416{
417 return m_payload.bytesPerLine;
418}
419
420inline std::shared_ptr<peak::common::Metadata> ImageView::GetMetadata()
421{
422 return m_metadata;
423}
424
425inline std::shared_ptr<const peak::common::Metadata> ImageView::GetMetadata() const
426{
427 return m_metadata;
428}
429
430inline std::shared_ptr<peak::core::Buffer> ImageView::GetParentBuffer() const
431{
432 return LockOrThrow(m_parentBuffer);
433}
434
435} // namespace core
436} // namespace peak
Provides information and utility functions for pixel formats.
Definition peak_common_pixel_format.hpp:234
PEAK_COMMON_NO_DISCARD size_t GetSizeInBytes(const Size &size) const
Calculates the memory size in bytes for a given image size.
Definition peak_common_pixel_format_info.ipp:1183
PEAK_COMMON_NO_DISCARD size_t GetAllocatedBitsPerPixel() const
Returns the number of allocated bits per pixel.
Definition peak_common_pixel_format_info.ipp:926
PEAK_COMMON_NO_DISCARD constexpr T GetWidth() const
Returns the width.
Definition peak_common_size.hpp:114
The base class for all exceptions thrown by the library.
Definition peak_exception.hpp:24
PEAK_COMMON_NO_DISCARD uint32_t GetHeight() const override
Height of the image in pixels.
Definition peak_image_view_impl.hpp:405
PEAK_COMMON_NO_DISCARD std::size_t GetSizeInBytes() const override
Returns the number of bytes in a single image row.
Definition peak_image_view_impl.hpp:380
PEAK_COMMON_NO_DISCARD std::size_t GetLineStartOffset() const override
Returns the byte offset to the first pixel of a line.
Definition peak_image_view_impl.hpp:375
PEAK_COMMON_NO_DISCARD size_t GetBytesPerLine() const override
The amount of bytes per line.
Definition peak_image_view_impl.hpp:415
PEAK_COMMON_NO_DISCARD peak::common::PixelFormatInfo GetPixelFormatInfo() const override
Information object for the PixelFormat of the contained image.
Definition peak_image_view_impl.hpp:390
PEAK_COMMON_NO_DISCARD size_t GetBitsPerPixel() const override
The amount of bits in one pixel.
Definition peak_image_view_impl.hpp:410
PEAK_COMMON_NO_DISCARD std::shared_ptr< peak::core::Buffer > GetParentBuffer() const
The parent buffer object, the image view was created from.
Definition peak_image_view_impl.hpp:430
PEAK_COMMON_NO_DISCARD uint32_t GetWidth() const override
Width of the image in pixels.
Definition peak_image_view_impl.hpp:400
PEAK_COMMON_NO_DISCARD const uint8_t * GetData() const override
Returns a pointer to the start of the first line that contains valid image data (read-only).
Definition peak_image_view_impl.hpp:365
ImageView(const std::shared_ptr< Buffer > &buffer)
Construct an ImageView from a Buffer.
Definition peak_image_view_impl.hpp:338
PEAK_COMMON_NO_DISCARD peak::common::PixelFormat GetPixelFormat() const override
PixelFormat of the contained image.
Definition peak_image_view_impl.hpp:385
PEAK_COMMON_NO_DISCARD peak::common::Size GetSize() const override
Get the dimensions of the image. I.e. Width, Height, etc.
Definition peak_image_view_impl.hpp:395
PEAK_COMMON_NO_DISCARD std::shared_ptr< peak::common::Metadata > GetMetadata() override
The metadata object belonging to the image.
Definition peak_image_view_impl.hpp:420
The exception thrown for internal errors.
Definition peak_exception.hpp:81
The exception thrown for passing an invalid argument to a function.
Definition peak_exception.hpp:118
The exception thrown for trying to apply an invalid cast.
Definition peak_exception.hpp:146
Represents a GenAPI enumeration node.
Definition peak_enumeration_node.hpp:37
Represents a GenAPI float node.
Definition peak_float_node.hpp:48
Represents a GenAPI integer node.
Definition peak_integer_node.hpp:38
PEAK_COMMON_NO_DISCARD bool IsReadable() const
Returns whether the node is currently readable.
Definition peak_node.hpp:874
PEAK_COMMON_NO_DISCARD NodeAccessStatus AccessStatus() const
Returns the access status.
Definition peak_node.hpp:866
@ Image3D
Definition peak_buffer_part.hpp:40
@ ConfidenceMap
Definition peak_buffer_part.hpp:44
@ Image2D
Definition peak_buffer_part.hpp:36
@ Chunk
Definition peak_buffer.hpp:46
@ Custom
Definition peak_buffer.hpp:70
@ IIDC
Definition peak_buffer.hpp:66
detail::SizeT< uint32_t > Size
Size with unsigned 32-bit integer dimensions.
Definition peak_common_size.hpp:268
PixelFormat
Enum listing all supported pixel formats and their internal IDs.
Definition peak_common_pixel_format.hpp:59
@ NotAvailable
Definition peak_node.hpp:45
@ ReadWrite
Definition peak_node.hpp:48
@ DeviceGain
Device gain the image was captured with.
Definition peak_common_metadata_key.hpp:126
@ DeviceExposureTime
Device exposure time the image was captured with.
Definition peak_common_metadata_key.hpp:89
@ DeviceTimestamp
Device-provided image acquisition timestamp in nanoseconds.
Definition peak_common_metadata_key.hpp:38
@ SystemTimestamp
Timestamp of the system since unix epoch in nanoseconds.
Definition peak_common_metadata_key.hpp:105
@ DeviceFrameID
A sequentially incremented identifier for the frame.
Definition peak_common_metadata_key.hpp:51
Definition peak_image_view.hpp:29
PEAK_COMMON_NO_DISCARD std::shared_ptr< peak::common::Metadata > ExtractMetadataFromBuffer(const std::shared_ptr< peak::core::Buffer > &buffer, MetadataExtractionMode mode)
Definition peak_image_view_impl.hpp:245
PEAK_COMMON_NO_DISCARD UsableRoiChunkInfo ExtractUsableRoiChunkInfo(const std::shared_ptr< peak::core::BufferChunk > &chunk)
Definition peak_image_view_impl.hpp:43
PEAK_COMMON_NO_DISCARD ExtractedPayload ExtractPayloadFromBuffer(const std::shared_ptr< peak::core::Buffer > &buffer)
Definition peak_image_view_impl.hpp:224
PEAK_COMMON_NO_DISCARD ExtractedPayload ExtractPayloadTypeImage(const std::shared_ptr< peak::core::Buffer > &buffer)
Definition peak_image_view_impl.hpp:112
PEAK_COMMON_NO_DISCARD std::shared_ptr< core::BufferChunk > FindBufferChunkById(const std::vector< std::shared_ptr< peak::core::BufferChunk > > &chunks, uint64_t chunkId)
Definition peak_image_view_impl.hpp:55
PEAK_COMMON_NO_DISCARD ExtractedPayload ExtractPayloadFromBufferPart(const std::shared_ptr< peak::core::BufferPart > &part)
Definition peak_image_view_impl.hpp:198
PEAK_COMMON_NO_DISCARD ExtractedPayload ExtractPayloadTypeChunk(const std::shared_ptr< peak::core::Buffer > &buffer)
Definition peak_image_view_impl.hpp:145
constexpr uint64_t imageChunkId
Definition peak_image_view_impl.hpp:33
PEAK_COMMON_NO_DISCARD ExtractedPayload UpdatePayloadInfoWithChunks(const peak::core::detail::ExtractedPayload &payload, const std::vector< std::shared_ptr< peak::core::BufferChunk > > &chunks)
Definition peak_image_view_impl.hpp:67
constexpr uint64_t usableRoiChunkId
Definition peak_image_view_impl.hpp:32
The "core" namespace contains the direct GenAPI and GenTL wrapper.
Definition peak_buffer.hpp:32
MetadataExtractionMode
Controls how metadata is extracted when constructing an ImageView.
Definition peak_image_view.hpp:50
@ Minimal
Definition peak_image_view.hpp:55
The "peak" namespace directly contains convenience functionality like the DeviceManager as well as th...
Definition peak_buffer.hpp:29
#define PEAK_COMMON_NO_DISCARD
Definition peak_common_defines.h:89
Definition peak_image_view.hpp:31
size_t bytesPerLine
Definition peak_image_view.hpp:36
size_t lineStartOffset
Definition peak_image_view.hpp:37
size_t dataSize
Definition peak_image_view.hpp:35
peak::common::PixelFormat pixelFormat
Definition peak_image_view.hpp:33
peak::common::Size size
Definition peak_image_view.hpp:32
void * dataPtr
Definition peak_image_view.hpp:34
Definition peak_image_view_impl.hpp:36
uint16_t offsetY
Definition peak_image_view_impl.hpp:40
uint16_t usableWidth
Definition peak_image_view_impl.hpp:37
uint16_t offsetX
Definition peak_image_view_impl.hpp:39
uint16_t usableHeight
Definition peak_image_view_impl.hpp:38