1 /* 2 * Simd Library (http://ermig1979.github.io/Simd). 3 * 4 * Copyright (c) 2011-2019 Yermalayeu Ihar, 5 * 2014-2019 Antonenka Mikhail, 6 * 2018-2019 Dmitry Fedorov, 7 * 2019-2019 Artur Voronkov. 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a copy 10 * of this software and associated documentation files (the "Software"), to deal 11 * in the Software without restriction, including without limitation the rights 12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 * copies of the Software, and to permit persons to whom the Software is 14 * furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included in 17 * all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 * SOFTWARE. 26 */ 27 #ifndef __SimdView_hpp__ 28 #define __SimdView_hpp__ 29 30 #include "Simd/SimdDefs.h" 31 #include "Simd/SimdRectangle.hpp" 32 #include "Simd/SimdAllocator.hpp" 33 34 #include <memory.h> 35 #include <assert.h> 36 #include <algorithm> 37 #include <fstream> 38 39 namespace Simd 40 { 41 /*! @ingroup cpp_view 42 43 \short The View structure provides storage and manipulation of images. 44 45 In order to have mutual conversion with OpenCV image type (cv::Mat) you have to define macro SIMD_OPENCV_ENABLE: 46 \verbatim 47 #include "opencv2/core/core.hpp" 48 #define SIMD_OPENCV_ENABLE 49 #include "Simd/SimdView.hpp" 50 51 int main() 52 { 53 typedef Simd::View<Simd::Allocator> View; 54 55 View view1(40, 30, View::Bgr24); 56 cv::Mat mat1(80, 60, CV_8UC3) 57 58 View view2 = mat1; // view2 will be refer to mat1, it is not a copy! 59 cv::Mat mat2 = view1; // mat2 will be refer to view1, it is not a copy! 60 61 return 0; 62 } 63 \endverbatim 64 65 \ref cpp_view_functions. 66 */ 67 template <template<class> class A> 68 struct View 69 { 70 typedef A<uint8_t> Allocator; /*!< Allocator type definition. */ 71 72 /*! 73 \enum Format 74 Describes pixel format types of an image view. 75 \note This type is corresponds to C type ::SimdPixelFormatType. 76 */ 77 enum Format 78 { 79 /*! An undefined pixel format. */ 80 None = 0, 81 /*! A 8-bit gray pixel format. */ 82 Gray8, 83 /*! A 24-bit (3 8-bit channels) BGR (Blue, Green, Red) pixel format. */ 84 Bgr24, 85 /*! A 32-bit (4 8-bit channels) BGRA (Blue, Green, Red, Alpha) pixel format. */ 86 Bgra32, 87 /*! A single channel 16-bit integer pixel format. */ 88 Int16, 89 /*! A single channel 32-bit integer pixel format. */ 90 Int32, 91 /*! A single channel 64-bit integer pixel format. */ 92 Int64, 93 /*! A single channel 32-bit float point pixel format. */ 94 Float, 95 /*! A single channel 64-bit float point pixel format. */ 96 Double, 97 /*! A 24-bit (3 8-bit channels) RGB (Red, Green, Blue) pixel format. */ 98 Rgb24 99 }; 100 101 /*! 102 \enum Position 103 Describes the position of the child image view to the parent image view. 104 This enum is used for creation of sub image view in method Simd::View::Region. 105 */ 106 enum Position 107 { 108 TopLeft, /*!< A position in the top-left corner. */ 109 TopCenter, /*!< A position at the top center. */ 110 TopRight, /*!< A position in the top-right corner. */ 111 MiddleLeft, /*!< A position of the left in the middle. */ 112 MiddleCenter, /*!< A central position. */ 113 MiddleRight, /*!< A position of the right in the middle. */ 114 BottomLeft, /*!< A position in the bottom-left corner. */ 115 BottomCenter, /*!< A position at the bottom center. */ 116 BottomRight, /*!< A position in the bottom-right corner. */ 117 }; 118 119 const size_t width; /*!< \brief A width of the image. */ 120 const size_t height; /*!< \brief A height of the image. */ 121 const ptrdiff_t stride; /*!< \brief A row size of the image in bytes. */ 122 const Format format; /*!< \brief A pixel format types of the image. */ 123 uint8_t * const data; /*!< \brief A pointer to the pixel data (first row) of the image. */ 124 125 /*! 126 Creates a new empty View structure. 127 */ 128 View(); 129 130 /*! 131 Creates a new View structure on the base of the image view. 132 133 \note This constructor is not create new image view! It only creates a reference to the same image. If you want to create a copy then must use method Simd::View::Clone. 134 135 \param [in] view - an original image view. 136 */ 137 View(const View & view); 138 139 #ifdef SIMD_OPENCV_ENABLE 140 /*! 141 Creates a new View structure on the base of OpenCV Mat type. 142 143 \note You have to define SIMD_OPENCV_ENABLE in order to use this functionality. 144 145 \param [in] mat - an OpenCV Mat. 146 */ 147 View(const cv::Mat & mat); 148 #endif 149 150 151 /*! 152 Creates a new View structure with specified width, height, row size, pixel format and pointer to pixel data. 153 154 \param [in] w - a width of created image view. 155 \param [in] h - a height of created image view. 156 \param [in] s - a stride (row size) of created image view. 157 \param [in] f - a pixel format of created image view. 158 \param [in] d - a pointer to the external buffer with pixel data. If this pointer is NULL then will be created own buffer. 159 */ 160 View(size_t w, size_t h, ptrdiff_t s, Format f, void * d); 161 162 /*! 163 Creates a new View structure with specified width, height, pixel format, pointer to pixel data and memory alignment. 164 165 \param [in] w - a width of created image view. 166 \param [in] h - a height of created image view. 167 \param [in] f - a pixel format of created image view. 168 \param [in] d - a pointer to the external buffer with pixel data. If this pointer is NULL then will be created own buffer. 169 \param [in] align - a required memory alignment. Its default value is determined by function Allocator::Alignment. 170 */ 171 View(size_t w, size_t h, Format f, void * d = NULL, size_t align = Allocator::Alignment()); 172 173 /*! 174 Creates a new View structure with specified width, height and pixel format. 175 176 \param [in] size - a size (width and height) of created image view. 177 \param [in] f - a pixel format of created image view. 178 */ 179 View(const Point<ptrdiff_t> & size, Format f); 180 181 /*! 182 A View destructor. 183 */ 184 ~View(); 185 186 #ifdef SIMD_OPENCV_ENABLE 187 /*! 188 Creates an OpenCV Mat which references this image. 189 190 \note You have to define SIMD_OPENCV_ENABLE in order to use this functionality. 191 192 \return an OpenCV Mat which references to this image. 193 */ 194 operator cv::Mat() const; 195 #endif 196 197 198 #ifdef SIMD_TENSORFLOW_ENABLE 199 /*! 200 Creates an Tensorflow Tensor which references this image. 201 202 \note You have to define SIMD_TENSORFLOW_ENABLE in order to use this functionality. 203 204 \return an Tensorflow Tensor which references to this image. 205 */ 206 void ToTFTensor(tensorflow::Tensor & tensor, float shift = 0, float scale = 1) const; 207 208 209 /*! 210 Creates an Tensorflow Tensor which references this image. 211 212 \note You have to define SIMD_TENSORFLOW_ENABLE in order to use this functionality. 213 214 \return an Tensorflow Tensor which references to this image. 215 */ 216 void ToTFTensor(tensorflow::Tensor & tensor, int batchIndex, float shift = 0, float scale = 0) const; 217 #endif 218 219 /*! 220 Gets a copy of current image view. 221 222 \return a pointer to the new View structure. The user must free this pointer after usage. 223 */ 224 View * Clone() const; 225 226 /*! 227 Gets a copy of current image view using buffer as a storage. 228 229 \param [in] buffer - an external view as a buffer. 230 \return a pointer to the new View structure (not owner). The user must free this pointer after usage. 231 */ 232 View * Clone(View & buffer) const; 233 234 /*! 235 Creates view which references to other View structure. 236 237 \note This function does not create a copy of image view! It only creates a reference to the same image. 238 239 \param [in] view - an original image view. 240 \return a reference to itself. 241 */ 242 View & operator = (const View & view); 243 244 #ifdef SIMD_OPENCV_ENABLE 245 /*! 246 Creates view which references to an OpenCV Mat. 247 248 \note You have to define SIMD_OPENCV_ENABLE in order to use this functionality. 249 250 \param [in] mat - an OpenCV Mat. 251 \return a reference to itself. 252 */ 253 View & operator = (const cv::Mat & mat); 254 #endif 255 256 /*! 257 Creates reference to itself. 258 It may be useful if we need to create reference to the temporary object: 259 \verbatim 260 #include "Simd/SimdLib.hpp" 261 262 int main() 263 { 264 typedef Simd::View<Simd::Allocator> View; 265 View a(100, 100, View::Gray8); 266 View b(100, 100, View::Gray8); 267 // Copying of a central part of a to the center of b: 268 Simd::Copy(a.Region(20, 20, 80, 80), b.Region(20, 20, 80, 80).Ref()); 269 return 0; 270 } 271 \endverbatim 272 273 \return a reference to itself. 274 */ 275 View & Ref(); 276 277 /*! 278 Re-creates a View structure with specified width, height, pixel format, pointer to pixel data and memory alignment. 279 280 \param [in] w - a width of re-created image view. 281 \param [in] h - a height of re-created image view. 282 \param [in] f - a pixel format of re-created image view. 283 \param [in] d - a pointer to the external buffer with pixel data. If this pointer is NULL then will be created own buffer. 284 \param [in] align - a required memory alignment. Its default value is determined by function Allocator::Alignment. 285 */ 286 void Recreate(size_t w, size_t h, Format f, void * d = NULL, size_t align = Allocator::Alignment()); 287 288 /*! 289 Re-creates a View structure with specified width, height and pixel format. 290 291 \param [in] size - a size (width and height) of re-created image view. 292 \param [in] f - a pixel format of re-created image view. 293 */ 294 void Recreate(const Point<ptrdiff_t> & size, Format f); 295 296 /*! 297 Creates a new View structure which points to the region of current image bounded by the rectangle with specified coordinates. 298 299 \param [in] left - a left side of the region. 300 \param [in] top - a top side of the region. 301 \param [in] right - a right side of the region. 302 \param [in] bottom - a bottom side of the region. 303 \return - a new View structure which points to the region of current image. 304 */ 305 View Region(ptrdiff_t left, ptrdiff_t top, ptrdiff_t right, ptrdiff_t bottom) const; 306 307 /*! 308 Creates a new View structure which points to the region of current image bounded by the rectangle with specified coordinates. 309 310 \param [in] topLeft - a top-left corner of the region. 311 \param [in] bottomRight - a bottom-right corner of the region. 312 \return - a new View structure which points to the region of current image. 313 */ 314 View Region(const Point<ptrdiff_t> & topLeft, const Point<ptrdiff_t> & bottomRight) const; 315 316 /*! 317 Creates a new View structure which points to the region of current image bounded by the rectangle with specified coordinates. 318 319 \param [in] rect - a rectangle which bound the region. 320 \return - a new View structure which points to the region of current image. 321 */ 322 View Region(const Rectangle<ptrdiff_t> & rect) const; 323 324 /*! 325 Creates a new View structure which points to the region of current image bounded by the rectangle with specified coordinates. 326 327 \param [in] size - a size (width and height) of the region. 328 \param [in] position - a value represents the position of the region (see Simd::View::Position). 329 \return - a new View structure which points to the region of current image. 330 */ 331 View Region(const Point<ptrdiff_t> & size, Position position) const; 332 333 /*! 334 Creates a new View structure which points to the vertically flipped image. 335 336 \return - a new View structure which points to the flipped image. 337 */ 338 View Flipped() const; 339 340 /*! 341 Gets size (width and height) of the image. 342 343 \return - a new Point structure with image width and height. 344 */ 345 Point<ptrdiff_t> Size() const; 346 347 /*! 348 Gets size in bytes required to store pixel data of current View structure. 349 350 \return - a size of data pixels in bytes. 351 */ 352 size_t DataSize() const; 353 354 /*! 355 Gets area in pixels of of current View structure. 356 357 \return - a area of current View in pixels. 358 */ 359 size_t Area() const; 360 361 /*! 362 Gets constant reference to the pixel of arbitrary type into current view with specified coordinates. 363 364 \param [in] x - a x-coordinate of the pixel. 365 \param [in] y - a y-coordinate of the pixel. 366 \return - a constant reference to pixel of arbitrary type. 367 */ 368 template <class T> const T & At(size_t x, size_t y) const; 369 370 /*! 371 Gets reference to the pixel of arbitrary type into current view with specified coordinates. 372 373 \param [in] x - a x-coordinate of the pixel. 374 \param [in] y - a y-coordinate of the pixel. 375 \return - a reference to pixel of arbitrary type. 376 */ 377 template <class T> T & At(size_t x, size_t y); 378 379 /*! 380 Gets constant reference to the pixel of arbitrary type into current view with specified coordinates. 381 382 \param [in] p - a point with coordinates of the pixel. 383 \return - a constant reference to pixel of arbitrary type. 384 */ 385 template <class T> const T & At(const Point<ptrdiff_t> & p) const; 386 387 /*! 388 Gets reference to the pixel of arbitrary type into current view with specified coordinates. 389 390 \param [in] p - a point with coordinates of the pixel. 391 \return - a reference to pixel of arbitrary type. 392 */ 393 template <class T> T & At(const Point<ptrdiff_t> & p); 394 395 /*! 396 Gets constant pointer to the first pixel of specified row. 397 398 \param [in] row - a row of the image. 399 \return - a constant pointer to the first pixel. 400 */ 401 template <class T> const T * Row(size_t row) const; 402 403 /*! 404 Gets pointer to the first pixel of specified row. 405 406 \param [in] row - a row of the image. 407 \return - a pointer to the first pixel. 408 */ 409 template <class T> T * Row(size_t row); 410 411 /*! 412 \fn size_t PixelSize(Format format); 413 414 Gets pixel size in bytes for current pixel format. 415 416 \param [in] format - a pixel format. 417 \return - a pixel size in bytes. 418 */ 419 static size_t PixelSize(Format format); 420 421 /*! 422 Gets pixel size in bytes for current image. 423 424 \return - a pixel size in bytes. 425 */ 426 size_t PixelSize() const; 427 428 /*! 429 \fn size_t ChannelSize(Format format); 430 431 Gets pixel channel size in bytes for current pixel format. 432 433 \param [in] format - a pixel format. 434 \return - a pixel channel size in bytes. 435 */ 436 static size_t ChannelSize(Format format); 437 438 /*! 439 Gets pixel channel size in bytes for current image. 440 441 \return - a pixel channel size in bytes. 442 */ 443 size_t ChannelSize() const; 444 445 /*! 446 \fn size_t ChannelCount(Format format); 447 448 Gets number of channels in the pixel for current pixel format. 449 450 \param [in] format - a pixel format. 451 \return - a number of channels. 452 */ 453 static size_t ChannelCount(Format format); 454 455 /*! 456 Gets number of channels in the pixel for current image. 457 458 \return - a number of channels. 459 */ 460 size_t ChannelCount() const; 461 462 #ifdef SIMD_OPENCV_ENABLE 463 /*! 464 Converts Simd Library pixel format to OpenCV Matrix type. 465 466 \note You have to define SIMD_OPENCV_ENABLE in order to use this functionality. 467 468 \param [in] format - a Simd Library pixel format. 469 \return - an OpenCV Matrix type. 470 */ 471 static int ToOcv(Format format); 472 473 /*! 474 Converts OpenCV Matrix type to Simd Library pixel format. 475 476 \note You have to define SIMD_OPENCV_ENABLE in order to use this functionality. 477 478 \param [in] type - an OpenCV Matrix type. 479 \return - a Simd Library pixel format. 480 */ 481 static Format OcvTo(int type); 482 #endif 483 484 /*! 485 Swaps content of two (this and other) View structures. 486 487 \param [in] other - an other image view. 488 */ 489 void Swap(View & other); 490 491 /*! 492 Loads image from file. 493 494 Supported formats: 495 - PGM(Portable Gray Map) text(P2) or binary(P5) (the file is loaded as 8-bit gray image). 496 - PPM(Portable Pixel Map) text(P3) or binary(P6) (the file is loaded as 32-bit BGRA image). 497 498 \note PGM and PPM files with comments are not supported. 499 500 \param [in] path - a path to file with PGM or PPM image. 501 \return - a result of loading. 502 */ 503 bool Load(const std::string & path); 504 505 /*! 506 Saves image to file. 507 508 Supported formats: 509 - PGM(Portable Gray Map) binary(P5) (this format is used in order to save 8-bit gray images). 510 - PPM(Portable Pixel Map) binary(P6) (this format is used in order to save 24-bit BGR and 32-bit BGRA images). 511 512 \param [in] path - a path to file. 513 \return - a result of saving. 514 */ 515 bool Save(const std::string & path) const; 516 517 /*! 518 Clear View structure (reset all fields) and free memory if it's owner 519 */ 520 void Clear(); 521 522 private: 523 bool _owner; 524 }; 525 526 /*! @ingroup cpp_view_functions 527 528 \fn template <template<class> class A, class T> const T & At(const View<A> & view, size_t x, size_t y); 529 530 Gets constant reference to the pixel of arbitrary type at the point at the image with specified coordinates. 531 532 \param [in] view - an image. 533 \param [in] x - a x-coordinate of the pixel. 534 \param [in] y - a y-coordinate of the pixel. 535 \return - a const reference to pixel of arbitrary type. 536 */ 537 template <template<class> class A, class T> const T & At(const View<A> & view, size_t x, size_t y); 538 539 /*! @ingroup cpp_view_functions 540 541 \fn template <template<class> class A, class T> T & At(View<A> & view, size_t x, size_t y); 542 543 Gets reference to the pixel of arbitrary type at the point at the image with specified coordinates. 544 545 \param [in] view - an image. 546 \param [in] x - a x-coordinate of the pixel. 547 \param [in] y - a y-coordinate of the pixel. 548 \return - a reference to pixel of arbitrary type. 549 */ 550 template <template<class> class A, class T> T & At(View<A> & view, size_t x, size_t y); 551 552 553 /*! @ingroup cpp_view_functions 554 555 \fn template <template<class> class A, template<class> class B> bool EqualSize(const View<A> & a, const View<B> & b); 556 557 Checks two image views on the same size. 558 559 \param [in] a - a first image. 560 \param [in] b - a second image. 561 \return - a result of checking. 562 */ 563 template <template<class> class A, template<class> class B> bool EqualSize(const View<A> & a, const View<B> & b); 564 565 /*! @ingroup cpp_view_functions 566 567 \fn template <template<class> class A> bool EqualSize(const View<A> & a, const View<A> & b, const View<A> & c); 568 569 Checks three image views on the same size. 570 571 \param [in] a - a first image. 572 \param [in] b - a second image. 573 \param [in] c - a third image. 574 \return - a result of checking. 575 */ 576 template <template<class> class A> bool EqualSize(const View<A> & a, const View<A> & b, const View<A> & c); 577 578 579 /*! @ingroup cpp_view_functions 580 581 \fn template <template<class> class A> bool EqualSize(const View<A> & a, const View<A> & b, const View<A> & c, const View<A> & d); 582 583 Checks four image views on the same size. 584 585 \param [in] a - a first image. 586 \param [in] b - a second image. 587 \param [in] c - a third image. 588 \param [in] d - a fourth image. 589 \return - a result of checking. 590 */ 591 template <template<class> class A> bool EqualSize(const View<A> & a, const View<A> & b, const View<A> & c, const View<A> & d); 592 593 /*! @ingroup cpp_view_functions 594 595 \fn template <template<class> class A, template<class> class B> bool Compatible(const View<A> & a, const View<B> & b); 596 597 Checks two image views on compatibility (the images must have the same size and pixel format). 598 599 \param [in] a - a first image. 600 \param [in] b - a second image. 601 \return - a result of checking. 602 */ 603 template <template<class> class A, template<class> class B> bool Compatible(const View<A> & a, const View<B> & b); 604 605 /*! @ingroup cpp_view_functions 606 607 \fn template <template<class> class A> bool Compatible(const View<A> & a, const View<A> & b, const View<A> & c); 608 609 Checks three image views on compatibility (the images must have the same size and pixel format). 610 611 \param [in] a - a first image. 612 \param [in] b - a second image. 613 \param [in] c - a third image. 614 \return - a result of checking. 615 */ 616 template <template<class> class A> bool Compatible(const View<A> & a, const View<A> & b, const View<A> & c); 617 618 /*! @ingroup cpp_view_functions 619 620 \fn template <template<class> class A> bool Compatible(const View<A> & a, const View<A> & b, const View<A> & c, const View<A> & d); 621 622 Checks four image views on compatibility (the images must have the same size and pixel format). 623 624 \param [in] a - a first image. 625 \param [in] b - a second image. 626 \param [in] c - a third image. 627 \param [in] d - a fourth image. 628 \return - a result of checking. 629 */ 630 template <template<class> class A> bool Compatible(const View<A> & a, const View<A> & b, const View<A> & c, const View<A> & d); 631 632 /*! @ingroup cpp_view_functions 633 634 \fn template <template<class> class A> bool Compatible(const View<A> & a, const View<A> & b, const View<A> & c, const View<A> & d, const View<A> & e); 635 636 Checks five image views on compatibility (the images must have the same size and pixel format). 637 638 \param [in] a - a first image. 639 \param [in] b - a second image. 640 \param [in] c - a third image. 641 \param [in] d - a fourth image. 642 \param [in] e - a fifth image. 643 \return - a result of checking. 644 */ 645 template <template<class> class A> bool Compatible(const View<A> & a, const View<A> & b, const View<A> & c, const View<A> & d, const View<A> & e); 646 647 //------------------------------------------------------------------------- 648 649 // struct View implementation: 650 View()651 template <template<class> class A> SIMD_INLINE View<A>::View() 652 : width(0) 653 , height(0) 654 , stride(0) 655 , format(None) 656 , data(NULL) 657 , _owner(false) 658 { 659 } 660 661 /*! \cond */ View(const View<A> & view)662 template <template<class> class A> SIMD_INLINE View<A>::View(const View<A> & view) 663 : width(view.width) 664 , height(view.height) 665 , stride(view.stride) 666 , format(view.format) 667 , data(view.data) 668 , _owner(false) 669 { 670 } 671 /*! \endcond */ 672 673 #ifdef SIMD_OPENCV_ENABLE View(const cv::Mat & mat)674 template <template<class> class A> SIMD_INLINE View<A>::View(const cv::Mat & mat) 675 : width(mat.cols) 676 , height(mat.rows) 677 , stride(mat.step[0]) 678 , format(OcvTo(mat.type())) 679 , data(mat.data) 680 , _owner(false) 681 { 682 } 683 #endif 684 685 #ifdef SIMD_TENSORFLOW_ENABLE ToTFTensor(tensorflow::Tensor & tensor,float shift,float scale) const686 template <template<class> class A> SIMD_INLINE void View<A>::ToTFTensor( tensorflow::Tensor & tensor, float shift, float scale) const 687 { 688 auto mapped = tensor.tensor<float, 3>(); 689 690 if (format == View<A>::Bgr24) 691 { 692 for (size_t row = 0; row < height; ++row) 693 { 694 const uint8_t * bgr = data + row*stride; 695 for (size_t col = 0; col < width; ++col, bgr += 3) 696 { 697 mapped(row, col, 0) = (bgr[0] + shift) * scale; 698 mapped(row, col, 1) = (bgr[1] + shift) * scale; 699 mapped(row, col, 2) = (bgr[2] + shift) * scale; 700 } 701 } 702 } else if (format == View<A>::Bgra32) 703 { 704 705 for (size_t row = 0; row < height; ++row) 706 { 707 const uint8_t * bgra = data + row*stride; 708 for (size_t col = 0; col < width; ++col, bgra += 4) 709 { 710 mapped(row, col, 0) = (bgra[0] + shift) * scale; 711 mapped(row, col, 1) = (bgra[1] + shift) * scale; 712 mapped(row, col, 2) = (bgra[2] + shift) * scale; 713 } 714 } 715 } else if (format == View<A>::Gray8) 716 { 717 for (size_t row = 0; row < height; ++row) 718 { 719 const uint8_t * gray = data + row*stride; 720 for (size_t col = 0; col < width; ++col) 721 { 722 mapped(row, col, 0) = (gray[0] + shift) * scale; 723 } 724 } 725 } 726 } 727 ToTFTensor(tensorflow::Tensor & tensor,int batchIndex,float shift,float scale) const728 template <template<class> class A> SIMD_INLINE void View<A>::ToTFTensor( tensorflow::Tensor & tensor, int batchIndex, float shift, float scale) const 729 { 730 auto mapped = tensor.tensor<float, 4>(); 731 732 if (format == View<A>::Bgr24) 733 { 734 for (size_t row = 0; row < height; ++row) 735 { 736 const uint8_t * bgr = data + row*stride; 737 for (size_t col = 0; col < width; ++col, bgr += 3) 738 { 739 mapped(batchIndex, row, col, 0) = ((float)bgr[0] + shift) * scale; 740 mapped(batchIndex, row, col, 1) = ((float)bgr[1] + shift) * scale; 741 mapped(batchIndex, row, col, 2) = ((float)bgr[2] + shift) * scale; 742 } 743 } 744 } else if (format == View<A>::Bgra32) 745 { 746 747 for (size_t row = 0; row < height; ++row) 748 { 749 const uint8_t * bgra = data + row*stride; 750 for (size_t col = 0; col < width; ++col, bgra += 4) 751 { 752 mapped(batchIndex, row, col, 0) = ((float)bgra[0] + shift) * scale; 753 mapped(batchIndex, row, col, 1) = ((float)bgra[1] + shift) * scale; 754 mapped(batchIndex, row, col, 2) = ((float)bgra[2] + shift) * scale; 755 } 756 } 757 } else if (format == View<A>::Gray8) 758 { 759 for (size_t row = 0; row < height; ++row) 760 { 761 const uint8_t * gray = data + row*stride; 762 for (size_t col = 0; col < width; ++col) 763 { 764 mapped(batchIndex, row, col, 0) = ((float)gray[0] + shift) * scale; 765 } 766 } 767 } 768 } 769 #endif 770 View(size_t w,size_t h,ptrdiff_t s,Format f,void * d)771 template <template<class> class A> SIMD_INLINE View<A>::View(size_t w, size_t h, ptrdiff_t s, Format f, void * d) 772 : width(w) 773 , height(h) 774 , stride(s) 775 , format(f) 776 , data((uint8_t*)d) 777 , _owner(false) 778 { 779 if (data == NULL && height && width && stride && format != None) 780 { 781 *(void**)&data = Allocator::Allocate(height*stride, Allocator::Alignment()); 782 _owner = true; 783 } 784 } 785 View(size_t w,size_t h,Format f,void * d,size_t align)786 template <template<class> class A> SIMD_INLINE View<A>::View(size_t w, size_t h, Format f, void * d, size_t align) 787 : width(0) 788 , height(0) 789 , stride(0) 790 , format(None) 791 , data(NULL) 792 , _owner(false) 793 { 794 Recreate(w, h, f, d, align); 795 } 796 View(const Point<ptrdiff_t> & size,Format f)797 template <template<class> class A> SIMD_INLINE View<A>::View(const Point<ptrdiff_t> & size, Format f) 798 : width(0) 799 , height(0) 800 , stride(0) 801 , format(None) 802 , data(NULL) 803 , _owner(false) 804 { 805 Recreate(size.x, size.y, f); 806 } 807 ~View()808 template <template<class> class A> SIMD_INLINE View<A>::~View() 809 { 810 if (_owner && data) 811 { 812 Allocator::Free(data); 813 } 814 } 815 816 #ifdef SIMD_OPENCV_ENABLE operator cv::Mat() const817 template <template<class> class A> SIMD_INLINE View<A>::operator cv::Mat() const 818 { 819 return cv::Mat((int)height, (int)width, ToOcv(format), data, stride); 820 } 821 #endif 822 Clone() const823 template <template<class> class A> SIMD_INLINE View<A> * View<A>::Clone() const 824 { 825 View<A> * view = new View<A>(width, height, format); 826 size_t size = width*PixelSize(); 827 for (size_t row = 0; row < height; ++row) 828 memcpy(view->data + view->stride*row, data + stride*row, size); 829 return view; 830 } 831 Clone(View & buffer) const832 template <template<class> class A> SIMD_INLINE View<A> * View<A>::Clone(View & buffer) const 833 { 834 if (buffer.width < width || buffer.height < height) 835 buffer.Recreate(width, height, format); 836 837 View<A> * view = new View<A>(width, height, format, buffer.data); 838 size_t size = width*PixelSize(); 839 for (size_t row = 0; row < height; ++row) 840 memcpy(view->data + view->stride*row, data + stride*row, size); 841 return view; 842 } 843 844 /*! \cond */ operator =(const View<A> & view)845 template <template<class> class A> SIMD_INLINE View<A> & View<A>::operator = (const View<A> & view) 846 { 847 if (this != &view) 848 { 849 if (_owner && data) 850 { 851 Allocator::Free(data); 852 assert(0); 853 } 854 *(size_t*)&width = view.width; 855 *(size_t*)&height = view.height; 856 *(Format*)&format = view.format; 857 *(ptrdiff_t*)&stride = view.stride; 858 *(unsigned char**)&data = view.data; 859 _owner = false; 860 } 861 return *this; 862 } 863 /*! \endcond */ 864 865 #ifdef SIMD_OPENCV_ENABLE operator =(const cv::Mat & mat)866 template <template<class> class A> SIMD_INLINE View<A> & View<A>::operator = (const cv::Mat & mat) 867 { 868 *this = View<A>(mat); 869 return *this; 870 } 871 #endif 872 Ref()873 template <template<class> class A> SIMD_INLINE View<A> & View<A>::Ref() 874 { 875 return *this; 876 } 877 Recreate(size_t w,size_t h,Format f,void * d,size_t align)878 template <template<class> class A> SIMD_INLINE void View<A>::Recreate(size_t w, size_t h, Format f, void * d, size_t align) 879 { 880 if (_owner && data) 881 { 882 Allocator::Free(data); 883 *(void**)&data = NULL; 884 _owner = false; 885 } 886 *(size_t*)&width = w; 887 *(size_t*)&height = h; 888 *(Format*)&format = f; 889 *(ptrdiff_t*)&stride = Allocator::Align(width*PixelSize(format), align); 890 if (d) 891 { 892 *(void**)&data = Allocator::Align(d, align); 893 _owner = false; 894 } 895 else if(height && stride) 896 { 897 *(void**)&data = Allocator::Allocate(height*stride, align); 898 _owner = true; 899 } 900 } 901 Recreate(const Point<ptrdiff_t> & size,Format f)902 template <template<class> class A> SIMD_INLINE void View<A>::Recreate(const Point<ptrdiff_t> & size, Format f) 903 { 904 Recreate(size.x, size.y, f); 905 } 906 Region(ptrdiff_t left,ptrdiff_t top,ptrdiff_t right,ptrdiff_t bottom) const907 template <template<class> class A> SIMD_INLINE View<A> View<A>::Region(ptrdiff_t left, ptrdiff_t top, ptrdiff_t right, ptrdiff_t bottom) const 908 { 909 if (data != NULL && right >= left && bottom >= top) 910 { 911 left = std::min<ptrdiff_t>(std::max<ptrdiff_t>(left, 0), width); 912 top = std::min<ptrdiff_t>(std::max<ptrdiff_t>(top, 0), height); 913 right = std::min<ptrdiff_t>(std::max<ptrdiff_t>(right, 0), width); 914 bottom = std::min<ptrdiff_t>(std::max<ptrdiff_t>(bottom, 0), height); 915 return View<A>(right - left, bottom - top, stride, format, data + top*stride + left*PixelSize(format)); 916 } 917 else 918 return View<A>(); 919 } 920 Region(const Point<ptrdiff_t> & topLeft,const Point<ptrdiff_t> & bottomRight) const921 template <template<class> class A> SIMD_INLINE View<A> View<A>::Region(const Point<ptrdiff_t> & topLeft, const Point<ptrdiff_t> & bottomRight) const 922 { 923 return Region(topLeft.x, topLeft.y, bottomRight.x, bottomRight.y); 924 } 925 Region(const Rectangle<ptrdiff_t> & rect) const926 template <template<class> class A> SIMD_INLINE View<A> View<A>::Region(const Rectangle<ptrdiff_t> & rect) const 927 { 928 return Region(rect.Left(), rect.Top(), rect.Right(), rect.Bottom()); 929 } 930 Region(const Point<ptrdiff_t> & size,Position position) const931 template <template<class> class A> SIMD_INLINE View<A> View<A>::Region(const Point<ptrdiff_t> & size, Position position) const 932 { 933 ptrdiff_t w = width, h = height; 934 switch (position) 935 { 936 case TopLeft: 937 return Region(0, 0, size.x, size.y); 938 case TopCenter: 939 return Region((w - size.x) / 2, 0, (w + size.x) / 2, size.y); 940 case TopRight: 941 return Region(w - size.x, 0, w, size.y); 942 case MiddleLeft: 943 return Region(0, (h - size.y) / 2, size.x, (h + size.y) / 2); 944 case MiddleCenter: 945 return Region((w - size.x) / 2, (h - size.y) / 2, (w + size.x) / 2, (h + size.y) / 2); 946 case MiddleRight: 947 return Region(w - size.x, (h - size.y) / 2, w, (h + size.y) / 2); 948 case BottomLeft: 949 return Region(0, h - size.y, size.x, h); 950 case BottomCenter: 951 return Region((w - size.x) / 2, h - size.y, (w + size.x) / 2, h); 952 case BottomRight: 953 return Region(w - size.x, h - size.y, w, h); 954 default: 955 assert(0); 956 } 957 return View<A>(); 958 } 959 Flipped() const960 template <template<class> class A> SIMD_INLINE View<A> View<A>::Flipped() const 961 { 962 return View<A>(width, height, -stride, format, data + (height - 1)*stride); 963 } 964 Size() const965 template <template<class> class A> SIMD_INLINE Point<ptrdiff_t> View<A>::Size() const 966 { 967 return Point<ptrdiff_t>(width, height); 968 } 969 DataSize() const970 template <template<class> class A> SIMD_INLINE size_t View<A>::DataSize() const 971 { 972 return stride*height; 973 } 974 Area() const975 template <template<class> class A> SIMD_INLINE size_t View<A>::Area() const 976 { 977 return width*height; 978 } 979 At(size_t x,size_t y) const980 template <template<class> class A> template<class T> SIMD_INLINE const T & View<A>::At(size_t x, size_t y) const 981 { 982 assert(x < width && y < height); 983 return ((const T*)(data + y*stride))[x]; 984 } 985 At(size_t x,size_t y)986 template <template<class> class A> template<class T> SIMD_INLINE T & View<A>::At(size_t x, size_t y) 987 { 988 assert(x < width && y < height); 989 return ((T*)(data + y*stride))[x]; 990 } 991 At(const Point<ptrdiff_t> & p) const992 template <template<class> class A> template<class T> SIMD_INLINE const T & View<A>::At(const Point<ptrdiff_t> & p) const 993 { 994 return At<T>(p.x, p.y); 995 } 996 At(const Point<ptrdiff_t> & p)997 template <template<class> class A> template<class T> SIMD_INLINE T & View<A>::At(const Point<ptrdiff_t> & p) 998 { 999 return At<T>(p.x, p.y); 1000 } 1001 Row(size_t row) const1002 template <template<class> class A> template<class T> SIMD_INLINE const T * View<A>::Row(size_t row) const 1003 { 1004 assert(row < height); 1005 return ((const T*)(data + row*stride)); 1006 } 1007 Row(size_t row)1008 template <template<class> class A> template<class T> SIMD_INLINE T * View<A>::Row(size_t row) 1009 { 1010 assert(row < height); 1011 return ((T*)(data + row*stride)); 1012 } 1013 PixelSize(Format format)1014 template <template<class> class A> SIMD_INLINE size_t View<A>::PixelSize(Format format) 1015 { 1016 switch (format) 1017 { 1018 case None: return 0; 1019 case Gray8: return 1; 1020 case Bgr24: return 3; 1021 case Bgra32: return 4; 1022 case Int16: return 2; 1023 case Int32: return 4; 1024 case Int64: return 8; 1025 case Float: return 4; 1026 case Double: return 8; 1027 case Rgb24: return 3; 1028 default: assert(0); return 0; 1029 } 1030 } 1031 PixelSize() const1032 template <template<class> class A> SIMD_INLINE size_t View<A>::PixelSize() const 1033 { 1034 return PixelSize(format); 1035 } 1036 ChannelSize(Format format)1037 template <template<class> class A> SIMD_INLINE size_t View<A>::ChannelSize(Format format) 1038 { 1039 switch (format) 1040 { 1041 case None: return 0; 1042 case Gray8: return 1; 1043 case Bgr24: return 1; 1044 case Bgra32: return 1; 1045 case Int16: return 2; 1046 case Int32: return 4; 1047 case Int64: return 8; 1048 case Float: return 4; 1049 case Double: return 8; 1050 case Rgb24: return 1; 1051 default: assert(0); return 0; 1052 } 1053 } 1054 ChannelSize() const1055 template <template<class> class A> SIMD_INLINE size_t View<A>::ChannelSize() const 1056 { 1057 return ChannelSize(format); 1058 } 1059 ChannelCount(Format format)1060 template <template<class> class A> SIMD_INLINE size_t View<A>::ChannelCount(Format format) 1061 { 1062 switch (format) 1063 { 1064 case None: return 0; 1065 case Gray8: return 1; 1066 case Bgr24: return 3; 1067 case Bgra32: return 4; 1068 case Int16: return 1; 1069 case Int32: return 1; 1070 case Int64: return 1; 1071 case Float: return 1; 1072 case Double: return 1; 1073 case Rgb24: return 3; 1074 default: assert(0); return 0; 1075 } 1076 } 1077 ChannelCount() const1078 template <template<class> class A> SIMD_INLINE size_t View<A>::ChannelCount() const 1079 { 1080 return ChannelCount(format); 1081 } 1082 1083 #ifdef SIMD_OPENCV_ENABLE ToOcv(Format format)1084 template <template<class> class A> SIMD_INLINE int View<A>::ToOcv(Format format) 1085 { 1086 switch (format) 1087 { 1088 case Gray8: return CV_8UC1; 1089 case Bgr24: return CV_8UC3; 1090 case Bgra32: return CV_8UC4; 1091 case Int16: return CV_16SC1; 1092 case Int32: return CV_32SC1; 1093 case Float: return CV_32FC1; 1094 case Double: return CV_64FC1; 1095 default: assert(0); return 0; 1096 } 1097 } 1098 OcvTo(int type)1099 template <template<class> class A> SIMD_INLINE typename View<A>::Format View<A>::OcvTo(int type) 1100 { 1101 switch (type) 1102 { 1103 case CV_8UC1: return Gray8; 1104 case CV_8UC3: return Bgr24; 1105 case CV_8UC4: return Bgra32; 1106 case CV_16SC1: return Int16; 1107 case CV_32SC1: return Int32; 1108 case CV_32FC1: return Float; 1109 case CV_64FC1: return Double; 1110 default: assert(0); return None; 1111 } 1112 } 1113 #endif 1114 Swap(View<A> & other)1115 template <template<class> class A> SIMD_INLINE void View<A>::Swap(View<A> & other) 1116 { 1117 std::swap((size_t&)width, (size_t&)other.width); 1118 std::swap((size_t&)height, (size_t&)other.height); 1119 std::swap((ptrdiff_t&)stride, (ptrdiff_t&)other.stride); 1120 std::swap((Format&)format, (Format&)other.format); 1121 std::swap((uint8_t*&)data, (uint8_t*&)other.data); 1122 std::swap((bool&)_owner, (bool&)other._owner); 1123 } 1124 Load(const std::string & path)1125 template <template<class> class A> SIMD_INLINE bool View<A>::Load(const std::string & path) 1126 { 1127 std::ifstream ifs(path.c_str(), std::ifstream::binary); 1128 if (ifs.is_open()) 1129 { 1130 std::string type; 1131 ifs >> type; 1132 if (type == "P2" || type == "P5") 1133 { 1134 size_t w, h, d; 1135 ifs >> w >> h >> d; 1136 if (d != 255) 1137 return false; 1138 ifs.get(); 1139 Recreate(w, h, View<A>::Gray8); 1140 if (type == "P2") 1141 { 1142 for (size_t row = 0; row < height; ++row) 1143 { 1144 for (size_t col = 0; col < width; ++col) 1145 { 1146 int gray; 1147 ifs >> gray; 1148 data[row * stride + col] = (uint8_t)gray; 1149 } 1150 } 1151 } 1152 else 1153 { 1154 for (size_t row = 0; row < height; ++row) 1155 ifs.read((char*)(data + row*stride), width); 1156 } 1157 return true; 1158 } 1159 if (type == "P3" || type == "P6") 1160 { 1161 size_t w, h, d; 1162 ifs >> w >> h >> d; 1163 if (d != 255) 1164 return false; 1165 ifs.get(); 1166 Recreate(w, h, View<A>::Bgra32); 1167 if (type == "P3") 1168 { 1169 for (size_t row = 0; row < height; ++row) 1170 { 1171 uint8_t * bgra = data + row * stride; 1172 for (size_t col = 0; col < width; ++col, bgra += 4) 1173 { 1174 int blue, green, red; 1175 ifs >> red >> green >> blue; 1176 bgra[0] = (uint8_t)blue; 1177 bgra[1] = (uint8_t)green; 1178 bgra[2] = (uint8_t)red; 1179 bgra[3] = 0xFF; 1180 } 1181 } 1182 } 1183 else 1184 { 1185 View buffer(width, 1, Bgr24); 1186 for (size_t row = 0; row < height; ++row) 1187 { 1188 ifs.read((char*)buffer.data, width*3); 1189 const uint8_t * rgb = buffer.data; 1190 uint8_t * bgra = data + row*stride; 1191 for (size_t col = 0; col < width; ++col, rgb += 3, bgra += 4) 1192 { 1193 bgra[0] = rgb[2]; 1194 bgra[1] = rgb[1]; 1195 bgra[2] = rgb[0]; 1196 bgra[3] = 0xFF; 1197 } 1198 } 1199 } 1200 return true; 1201 } 1202 } 1203 return false; 1204 } 1205 Save(const std::string & path) const1206 template <template<class> class A> SIMD_INLINE bool View<A>::Save(const std::string & path) const 1207 { 1208 if (!(format == View<A>::Gray8 || format == View<A>::Bgr24 || format == View<A>::Bgra32)) 1209 return false; 1210 1211 std::ofstream ofs(path.c_str(), std::ofstream::binary); 1212 if (ofs.is_open()) 1213 { 1214 if (format == View<A>::Gray8) 1215 { 1216 ofs << "P5\n" << width << " " << height << "\n255\n"; 1217 for (size_t row = 0; row < height; ++row) 1218 ofs.write((const char*)(data + row*stride), width); 1219 } 1220 else if (format == View<A>::Bgr24) 1221 { 1222 ofs << "P6\n" << width << " " << height << "\n255\n"; 1223 View buffer(width, 1, Bgr24); 1224 for (size_t row = 0; row < height; ++row) 1225 { 1226 const uint8_t * bgr = data + row*stride; 1227 uint8_t * rgb = buffer.data; 1228 for (size_t col = 0; col < width; ++col, bgr += 3, rgb += 3) 1229 { 1230 rgb[0] = bgr[2]; 1231 rgb[1] = bgr[1]; 1232 rgb[2] = bgr[0]; 1233 } 1234 ofs.write((const char*)(buffer.data), width*3); 1235 } 1236 } 1237 else if (format == View<A>::Bgra32) 1238 { 1239 ofs << "P6\n" << width << " " << height << "\n255\n"; 1240 View buffer(width, 1, Bgr24); 1241 for (size_t row = 0; row < height; ++row) 1242 { 1243 const uint8_t * bgra = data + row*stride; 1244 uint8_t * rgb = buffer.data; 1245 for (size_t col = 0; col < width; ++col, bgra += 4, rgb += 3) 1246 { 1247 rgb[0] = bgra[2]; 1248 rgb[1] = bgra[1]; 1249 rgb[2] = bgra[0]; 1250 } 1251 ofs.write((const char*)buffer.data, width * 3); 1252 } 1253 } 1254 return true; 1255 } 1256 else 1257 return false; 1258 } 1259 Clear()1260 template <template<class> class A> SIMD_INLINE void View<A>::Clear() 1261 { 1262 if (_owner && data) 1263 Allocator::Free(data); 1264 #ifdef SIMD_CPP_2011_ENABLE 1265 *(void**)&data = nullptr; 1266 #else 1267 *(void**)&data = NULL; 1268 #endif 1269 _owner = false; 1270 *(size_t*)&width = 0; 1271 *(size_t*)&height = 0; 1272 *(ptrdiff_t *)&stride = 0; 1273 #ifdef SIMD_CPP_2011_ENABLE 1274 *(Format*)&format = Format::None; 1275 #else 1276 *(Format*)&format = 0; 1277 #endif 1278 } 1279 1280 // View utilities implementation: 1281 At(const View<A> & view,size_t x,size_t y)1282 template <template<class> class A, class T> const T & At(const View<A> & view, size_t x, size_t y) 1283 { 1284 assert(x < view.width && y < view.height); 1285 1286 return ((const T*)(view.data + y*view.stride))[x]; 1287 } 1288 At(View<A> & view,size_t x,size_t y)1289 template <template<class> class A, class T> T & At(View<A> & view, size_t x, size_t y) 1290 { 1291 assert(x < view.width && y < view.height); 1292 1293 return ((T*)(view.data + y*view.stride))[x]; 1294 } 1295 EqualSize(const View<A> & a,const View<B> & b)1296 template <template<class> class A, template<class> class B> SIMD_INLINE bool EqualSize(const View<A> & a, const View<B> & b) 1297 { 1298 return 1299 (a.width == b.width && a.height == b.height); 1300 } 1301 EqualSize(const View<A> & a,const View<A> & b,const View<A> & c)1302 template <template<class> class A> SIMD_INLINE bool EqualSize(const View<A> & a, const View<A> & b, const View<A> & c) 1303 { 1304 return 1305 (a.width == b.width && a.height == b.height) && 1306 (a.width == c.width && a.height == c.height); 1307 } 1308 EqualSize(const View<A> & a,const View<A> & b,const View<A> & c,const View<A> & d)1309 template <template<class> class A> SIMD_INLINE bool EqualSize(const View<A> & a, const View<A> & b, const View<A> & c, const View<A> & d) 1310 { 1311 return 1312 (a.width == b.width && a.height == b.height) && 1313 (a.width == c.width && a.height == c.height) && 1314 (a.width == d.width && a.height == d.height); 1315 } 1316 Compatible(const View<A> & a,const View<B> & b)1317 template <template<class> class A, template<class> class B> SIMD_INLINE bool Compatible(const View<A> & a, const View<B> & b) 1318 { 1319 typedef typename View<A>::Format Format; 1320 1321 return 1322 (a.width == b.width && a.height == b.height && a.format == (Format)b.format); 1323 } 1324 Compatible(const View<A> & a,const View<A> & b,const View<A> & c)1325 template <template<class> class A> SIMD_INLINE bool Compatible(const View<A> & a, const View<A> & b, const View<A> & c) 1326 { 1327 return 1328 (a.width == b.width && a.height == b.height && a.format == b.format) && 1329 (a.width == c.width && a.height == c.height && a.format == c.format); 1330 } 1331 Compatible(const View<A> & a,const View<A> & b,const View<A> & c,const View<A> & d)1332 template <template<class> class A> SIMD_INLINE bool Compatible(const View<A> & a, const View<A> & b, const View<A> & c, const View<A> & d) 1333 { 1334 return 1335 (a.width == b.width && a.height == b.height && a.format == b.format) && 1336 (a.width == c.width && a.height == c.height && a.format == c.format) && 1337 (a.width == d.width && a.height == d.height && a.format == d.format); 1338 } 1339 Compatible(const View<A> & a,const View<A> & b,const View<A> & c,const View<A> & d,const View<A> & e)1340 template <template<class> class A> SIMD_INLINE bool Compatible(const View<A> & a, const View<A> & b, const View<A> & c, const View<A> & d, const View<A> & e) 1341 { 1342 return 1343 (a.width == b.width && a.height == b.height && a.format == b.format) && 1344 (a.width == c.width && a.height == c.height && a.format == c.format) && 1345 (a.width == d.width && a.height == d.height && a.format == d.format) && 1346 (a.width == e.width && a.height == e.height && a.format == e.format); 1347 } 1348 } 1349 1350 #endif//__SimdView_hpp__ 1351