Mercurial > hg > octave-nkf
comparison libinterp/dldfcn/__magick_read__.cc @ 18610:30aa4e85f8d5 stable
Fix writing and reading of multipage images.
* __magick_read__.cc (encode_uint_image): reset the coordinates for each
Magick::Image object so that writing of multipage images (matrices with
non-singleton 4th dimension) work properly. Stride over the extra channels
at the end of each page, to fix writing of multipage RGB and CMYK images.
(read_images): correct stride over each frame for RGB and CMYK images.
* imwrite.m: add tests to write and read multipage grayscale and RGB images.
Reduce size of test images to speed up comparison.
author | Carnë Draug <carandraug@octave.org> |
---|---|
date | Tue, 04 Mar 2014 16:52:00 +0000 |
parents | bc1809fe55e4 |
children | e0cc67d5a462 |
comparison
equal
deleted
inserted
replaced
18603:11de7f82afe2 | 18610:30aa4e85f8d5 |
---|---|
414 // values not being handled in switch. | 414 // values not being handled in switch. |
415 ; | 415 ; |
416 } | 416 } |
417 } | 417 } |
418 | 418 |
419 const octave_idx_type colour_stride = nRows * nCols; | |
419 switch (type) | 420 switch (type) |
420 { | 421 { |
421 case Magick::BilevelType: // Monochrome bi-level image | 422 case Magick::BilevelType: // Monochrome bi-level image |
422 case Magick::GrayscaleType: // Grayscale image | 423 case Magick::GrayscaleType: // Grayscale image |
423 { | 424 { |
478 case Magick::TrueColorType: // Truecolor image | 479 case Magick::TrueColorType: // Truecolor image |
479 { | 480 { |
480 img = T (dim_vector (nRows, nCols, 3, nFrames)); | 481 img = T (dim_vector (nRows, nCols, 3, nFrames)); |
481 P *img_fvec = img.fortran_vec (); | 482 P *img_fvec = img.fortran_vec (); |
482 | 483 |
484 const octave_idx_type frame_stride = colour_stride * 3; | |
483 for (octave_idx_type frame = 0; frame < nFrames; frame++) | 485 for (octave_idx_type frame = 0; frame < nFrames; frame++) |
484 { | 486 { |
485 const Magick::PixelPacket *pix | 487 const Magick::PixelPacket *pix |
486 = imvec[frameidx(frame)].getConstPixels (col_start, row_start, | 488 = imvec[frameidx(frame)].getConstPixels (col_start, row_start, |
487 col_cache, row_cache); | 489 col_cache, row_cache); |
488 | 490 |
489 octave_idx_type idx = 0; | 491 octave_idx_type idx = 0; |
490 img_fvec += nRows * nCols * frame; | |
491 P *rbuf = img_fvec; | 492 P *rbuf = img_fvec; |
492 P *gbuf = img_fvec + nRows * nCols; | 493 P *gbuf = img_fvec + colour_stride; |
493 P *bbuf = img_fvec + nRows * nCols * 2; | 494 P *bbuf = img_fvec + colour_stride * 2; |
494 | 495 |
495 for (octave_idx_type col = 0; col < nCols; col++) | 496 for (octave_idx_type col = 0; col < nCols; col++) |
496 { | 497 { |
497 for (octave_idx_type row = 0; row < nRows; row++) | 498 for (octave_idx_type row = 0; row < nRows; row++) |
498 { | 499 { |
502 pix += row_shift; | 503 pix += row_shift; |
503 idx++; | 504 idx++; |
504 } | 505 } |
505 pix -= col_shift; | 506 pix -= col_shift; |
506 } | 507 } |
508 img_fvec += frame_stride; | |
507 } | 509 } |
508 break; | 510 break; |
509 } | 511 } |
510 | 512 |
511 case Magick::PaletteMatteType: // Indexed color image with opacity | 513 case Magick::PaletteMatteType: // Indexed color image with opacity |
513 { | 515 { |
514 img = T (dim_vector (nRows, nCols, 3, nFrames)); | 516 img = T (dim_vector (nRows, nCols, 3, nFrames)); |
515 T alpha (dim_vector (nRows, nCols, 1, nFrames)); | 517 T alpha (dim_vector (nRows, nCols, 1, nFrames)); |
516 P *img_fvec = img.fortran_vec (); | 518 P *img_fvec = img.fortran_vec (); |
517 P *a_fvec = alpha.fortran_vec (); | 519 P *a_fvec = alpha.fortran_vec (); |
520 | |
521 const octave_idx_type frame_stride = colour_stride * 3; | |
518 | 522 |
519 // Unlike the index for the other channels, this one won't need | 523 // Unlike the index for the other channels, this one won't need |
520 // to be reset on each frame since it's a separate matrix. | 524 // to be reset on each frame since it's a separate matrix. |
521 octave_idx_type a_idx = 0; | 525 octave_idx_type a_idx = 0; |
522 for (octave_idx_type frame = 0; frame < nFrames; frame++) | 526 for (octave_idx_type frame = 0; frame < nFrames; frame++) |
524 const Magick::PixelPacket *pix | 528 const Magick::PixelPacket *pix |
525 = imvec[frameidx(frame)].getConstPixels (col_start, row_start, | 529 = imvec[frameidx(frame)].getConstPixels (col_start, row_start, |
526 col_cache, row_cache); | 530 col_cache, row_cache); |
527 | 531 |
528 octave_idx_type idx = 0; | 532 octave_idx_type idx = 0; |
529 img_fvec += nRows * nCols * frame; | |
530 P *rbuf = img_fvec; | 533 P *rbuf = img_fvec; |
531 P *gbuf = img_fvec + nRows * nCols; | 534 P *gbuf = img_fvec + colour_stride; |
532 P *bbuf = img_fvec + nRows * nCols * 2; | 535 P *bbuf = img_fvec + colour_stride * 2; |
533 | 536 |
534 for (octave_idx_type col = 0; col < nCols; col++) | 537 for (octave_idx_type col = 0; col < nCols; col++) |
535 { | 538 { |
536 for (octave_idx_type row = 0; row < nRows; row++) | 539 for (octave_idx_type row = 0; row < nRows; row++) |
537 { | 540 { |
542 pix += row_shift; | 545 pix += row_shift; |
543 idx++; | 546 idx++; |
544 } | 547 } |
545 pix -= col_shift; | 548 pix -= col_shift; |
546 } | 549 } |
550 img_fvec += frame_stride; | |
547 } | 551 } |
548 retval(2) = alpha; | 552 retval(2) = alpha; |
549 break; | 553 break; |
550 } | 554 } |
551 | 555 |
552 case Magick::ColorSeparationType: // Cyan/Magenta/Yellow/Black (CMYK) image | 556 case Magick::ColorSeparationType: // Cyan/Magenta/Yellow/Black (CMYK) image |
553 { | 557 { |
554 img = T (dim_vector (nRows, nCols, 4, nFrames)); | 558 img = T (dim_vector (nRows, nCols, 4, nFrames)); |
555 P *img_fvec = img.fortran_vec (); | 559 P *img_fvec = img.fortran_vec (); |
556 | 560 |
561 const octave_idx_type frame_stride = colour_stride * 4; | |
557 for (octave_idx_type frame = 0; frame < nFrames; frame++) | 562 for (octave_idx_type frame = 0; frame < nFrames; frame++) |
558 { | 563 { |
559 const Magick::PixelPacket *pix | 564 const Magick::PixelPacket *pix |
560 = imvec[frameidx(frame)].getConstPixels (col_start, row_start, | 565 = imvec[frameidx(frame)].getConstPixels (col_start, row_start, |
561 col_cache, row_cache); | 566 col_cache, row_cache); |
562 | 567 |
563 octave_idx_type idx = 0; | 568 octave_idx_type idx = 0; |
564 img_fvec += nRows * nCols * frame; | |
565 P *cbuf = img_fvec; | 569 P *cbuf = img_fvec; |
566 P *mbuf = img_fvec + nRows * nCols; | 570 P *mbuf = img_fvec + colour_stride; |
567 P *ybuf = img_fvec + nRows * nCols * 2; | 571 P *ybuf = img_fvec + colour_stride * 2; |
568 P *kbuf = img_fvec + nRows * nCols * 3; | 572 P *kbuf = img_fvec + colour_stride * 3; |
569 | 573 |
570 for (octave_idx_type col = 0; col < nCols; col++) | 574 for (octave_idx_type col = 0; col < nCols; col++) |
571 { | 575 { |
572 for (octave_idx_type row = 0; row < nRows; row++) | 576 for (octave_idx_type row = 0; row < nRows; row++) |
573 { | 577 { |
578 pix += row_shift; | 582 pix += row_shift; |
579 idx++; | 583 idx++; |
580 } | 584 } |
581 pix -= col_shift; | 585 pix -= col_shift; |
582 } | 586 } |
587 img_fvec += frame_stride; | |
583 } | 588 } |
584 break; | 589 break; |
585 } | 590 } |
586 | 591 |
587 // Cyan, magenta, yellow, and black with alpha (opacity) channel | 592 // Cyan, magenta, yellow, and black with alpha (opacity) channel |
589 { | 594 { |
590 img = T (dim_vector (nRows, nCols, 4, nFrames)); | 595 img = T (dim_vector (nRows, nCols, 4, nFrames)); |
591 T alpha (dim_vector (nRows, nCols, 1, nFrames)); | 596 T alpha (dim_vector (nRows, nCols, 1, nFrames)); |
592 P *img_fvec = img.fortran_vec (); | 597 P *img_fvec = img.fortran_vec (); |
593 P *a_fvec = alpha.fortran_vec (); | 598 P *a_fvec = alpha.fortran_vec (); |
599 | |
600 const octave_idx_type frame_stride = colour_stride * 4; | |
594 | 601 |
595 // Unlike the index for the other channels, this one won't need | 602 // Unlike the index for the other channels, this one won't need |
596 // to be reset on each frame since it's a separate matrix. | 603 // to be reset on each frame since it's a separate matrix. |
597 octave_idx_type a_idx = 0; | 604 octave_idx_type a_idx = 0; |
598 for (octave_idx_type frame = 0; frame < nFrames; frame++) | 605 for (octave_idx_type frame = 0; frame < nFrames; frame++) |
604 // stored in the assocated IndexPacket. | 611 // stored in the assocated IndexPacket. |
605 const Magick::IndexPacket *apix | 612 const Magick::IndexPacket *apix |
606 = imvec[frameidx(frame)].getConstIndexes (); | 613 = imvec[frameidx(frame)].getConstIndexes (); |
607 | 614 |
608 octave_idx_type idx = 0; | 615 octave_idx_type idx = 0; |
609 img_fvec += nRows * nCols * frame; | |
610 P *cbuf = img_fvec; | 616 P *cbuf = img_fvec; |
611 P *mbuf = img_fvec + nRows * nCols; | 617 P *mbuf = img_fvec + colour_stride; |
612 P *ybuf = img_fvec + nRows * nCols * 2; | 618 P *ybuf = img_fvec + colour_stride * 2; |
613 P *kbuf = img_fvec + nRows * nCols * 3; | 619 P *kbuf = img_fvec + colour_stride * 3; |
614 | 620 |
615 for (octave_idx_type col = 0; col < nCols; col++) | 621 for (octave_idx_type col = 0; col < nCols; col++) |
616 { | 622 { |
617 for (octave_idx_type row = 0; row < nRows; row++) | 623 for (octave_idx_type row = 0; row < nRows; row++) |
618 { | 624 { |
624 pix += row_shift; | 630 pix += row_shift; |
625 idx++; | 631 idx++; |
626 } | 632 } |
627 pix -= col_shift; | 633 pix -= col_shift; |
628 } | 634 } |
635 img_fvec += frame_stride; | |
629 } | 636 } |
630 retval(2) = alpha; | 637 retval(2) = alpha; |
631 break; | 638 break; |
632 } | 639 } |
633 | 640 |
1060 const P *a_fvec = alpha.fortran_vec (); | 1067 const P *a_fvec = alpha.fortran_vec (); |
1061 switch (type) | 1068 switch (type) |
1062 { | 1069 { |
1063 case Magick::GrayscaleType: | 1070 case Magick::GrayscaleType: |
1064 { | 1071 { |
1065 octave_idx_type GM_idx = 0; | |
1066 for (octave_idx_type frame = 0; frame < nFrames; frame++) | 1072 for (octave_idx_type frame = 0; frame < nFrames; frame++) |
1067 { | 1073 { |
1068 Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth, | 1074 Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth, |
1069 type, | 1075 type, |
1070 Magick::DirectClass); | 1076 Magick::DirectClass); |
1071 | 1077 |
1072 Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows); | 1078 Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows); |
1079 octave_idx_type GM_idx = 0; | |
1073 for (octave_idx_type col = 0; col < nCols; col++) | 1080 for (octave_idx_type col = 0; col < nCols; col++) |
1074 { | 1081 { |
1075 for (octave_idx_type row = 0; row < nRows; row++) | 1082 for (octave_idx_type row = 0; row < nRows; row++) |
1076 { | 1083 { |
1077 Magick::Color c; | 1084 Magick::Color c; |
1089 break; | 1096 break; |
1090 } | 1097 } |
1091 | 1098 |
1092 case Magick::GrayscaleMatteType: | 1099 case Magick::GrayscaleMatteType: |
1093 { | 1100 { |
1094 octave_idx_type GM_idx = 0; | |
1095 for (octave_idx_type frame = 0; frame < nFrames; frame++) | 1101 for (octave_idx_type frame = 0; frame < nFrames; frame++) |
1096 { | 1102 { |
1097 Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth, | 1103 Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth, |
1098 type, | 1104 type, |
1099 Magick::DirectClass); | 1105 Magick::DirectClass); |
1100 | 1106 |
1101 Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows); | 1107 Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows); |
1108 octave_idx_type GM_idx = 0; | |
1102 for (octave_idx_type col = 0; col < nCols; col++) | 1109 for (octave_idx_type col = 0; col < nCols; col++) |
1103 { | 1110 { |
1104 for (octave_idx_type row = 0; row < nRows; row++) | 1111 for (octave_idx_type row = 0; row < nRows; row++) |
1105 { | 1112 { |
1106 Magick::Color c; | 1113 Magick::Color c; |
1123 case Magick::TrueColorType: | 1130 case Magick::TrueColorType: |
1124 { | 1131 { |
1125 // The fortran_vec offset for the green and blue channels | 1132 // The fortran_vec offset for the green and blue channels |
1126 const octave_idx_type G_offset = nCols * nRows; | 1133 const octave_idx_type G_offset = nCols * nRows; |
1127 const octave_idx_type B_offset = nCols * nRows * 2; | 1134 const octave_idx_type B_offset = nCols * nRows * 2; |
1128 octave_idx_type GM_idx = 0; | |
1129 for (octave_idx_type frame = 0; frame < nFrames; frame++) | 1135 for (octave_idx_type frame = 0; frame < nFrames; frame++) |
1130 { | 1136 { |
1131 Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth, | 1137 Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth, |
1132 type, | 1138 type, |
1133 Magick::DirectClass); | 1139 Magick::DirectClass); |
1134 | 1140 |
1135 Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows); | 1141 Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows); |
1142 octave_idx_type GM_idx = 0; | |
1136 for (octave_idx_type col = 0; col < nCols; col++) | 1143 for (octave_idx_type col = 0; col < nCols; col++) |
1137 { | 1144 { |
1138 for (octave_idx_type row = 0; row < nRows; row++) | 1145 for (octave_idx_type row = 0; row < nRows; row++) |
1139 { | 1146 { |
1140 Magick::Color c (double (*img_fvec) / divisor, | 1147 Magick::Color c (double (*img_fvec) / divisor, |
1147 GM_idx -= nCols * nRows - 1; | 1154 GM_idx -= nCols * nRows - 1; |
1148 } | 1155 } |
1149 // Save changes to underlying image. | 1156 // Save changes to underlying image. |
1150 m_img.syncPixels (); | 1157 m_img.syncPixels (); |
1151 imvec.push_back (m_img); | 1158 imvec.push_back (m_img); |
1159 img_fvec += B_offset; | |
1152 } | 1160 } |
1153 break; | 1161 break; |
1154 } | 1162 } |
1155 | 1163 |
1156 case Magick::TrueColorMatteType: | 1164 case Magick::TrueColorMatteType: |
1157 { | 1165 { |
1158 // The fortran_vec offset for the green and blue channels | 1166 // The fortran_vec offset for the green and blue channels |
1159 const octave_idx_type G_offset = nCols * nRows; | 1167 const octave_idx_type G_offset = nCols * nRows; |
1160 const octave_idx_type B_offset = nCols * nRows * 2; | 1168 const octave_idx_type B_offset = nCols * nRows * 2; |
1161 octave_idx_type GM_idx = 0; | |
1162 for (octave_idx_type frame = 0; frame < nFrames; frame++) | 1169 for (octave_idx_type frame = 0; frame < nFrames; frame++) |
1163 { | 1170 { |
1164 Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth, | 1171 Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth, |
1165 type, | 1172 type, |
1166 Magick::DirectClass); | 1173 Magick::DirectClass); |
1167 | 1174 |
1168 Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows); | 1175 Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows); |
1176 octave_idx_type GM_idx = 0; | |
1169 for (octave_idx_type col = 0; col < nCols; col++) | 1177 for (octave_idx_type col = 0; col < nCols; col++) |
1170 { | 1178 { |
1171 for (octave_idx_type row = 0; row < nRows; row++) | 1179 for (octave_idx_type row = 0; row < nRows; row++) |
1172 { | 1180 { |
1173 Magick::Color c (double (*img_fvec) / divisor, | 1181 Magick::Color c (double (*img_fvec) / divisor, |
1182 GM_idx -= nCols * nRows - 1; | 1190 GM_idx -= nCols * nRows - 1; |
1183 } | 1191 } |
1184 // Save changes to underlying image. | 1192 // Save changes to underlying image. |
1185 m_img.syncPixels (); | 1193 m_img.syncPixels (); |
1186 imvec.push_back (m_img); | 1194 imvec.push_back (m_img); |
1195 img_fvec += B_offset; | |
1187 } | 1196 } |
1188 break; | 1197 break; |
1189 } | 1198 } |
1190 | 1199 |
1191 case Magick::ColorSeparationType: | 1200 case Magick::ColorSeparationType: |
1192 { | 1201 { |
1193 // The fortran_vec offset for the Magenta, Yellow, and blacK channels | 1202 // The fortran_vec offset for the Magenta, Yellow, and blacK channels |
1194 const octave_idx_type M_offset = nCols * nRows; | 1203 const octave_idx_type M_offset = nCols * nRows; |
1195 const octave_idx_type Y_offset = nCols * nRows * 2; | 1204 const octave_idx_type Y_offset = nCols * nRows * 2; |
1196 const octave_idx_type K_offset = nCols * nRows * 3; | 1205 const octave_idx_type K_offset = nCols * nRows * 3; |
1197 octave_idx_type GM_idx = 0; | |
1198 for (octave_idx_type frame = 0; frame < nFrames; frame++) | 1206 for (octave_idx_type frame = 0; frame < nFrames; frame++) |
1199 { | 1207 { |
1200 Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth, | 1208 Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth, |
1201 type, | 1209 type, |
1202 Magick::DirectClass); | 1210 Magick::DirectClass); |
1203 | 1211 |
1204 Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows); | 1212 Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows); |
1213 octave_idx_type GM_idx = 0; | |
1205 for (octave_idx_type col = 0; col < nCols; col++) | 1214 for (octave_idx_type col = 0; col < nCols; col++) |
1206 { | 1215 { |
1207 for (octave_idx_type row = 0; row < nRows; row++) | 1216 for (octave_idx_type row = 0; row < nRows; row++) |
1208 { | 1217 { |
1209 Magick::Color c (double (*img_fvec) / divisor, | 1218 Magick::Color c (double (*img_fvec) / divisor, |
1217 GM_idx -= nCols * nRows - 1; | 1226 GM_idx -= nCols * nRows - 1; |
1218 } | 1227 } |
1219 // Save changes to underlying image. | 1228 // Save changes to underlying image. |
1220 m_img.syncPixels (); | 1229 m_img.syncPixels (); |
1221 imvec.push_back (m_img); | 1230 imvec.push_back (m_img); |
1231 img_fvec += K_offset; | |
1222 } | 1232 } |
1223 break; | 1233 break; |
1224 } | 1234 } |
1225 | 1235 |
1226 case Magick::ColorSeparationMatteType: | 1236 case Magick::ColorSeparationMatteType: |
1227 { | 1237 { |
1228 // The fortran_vec offset for the Magenta, Yellow, and blacK channels | 1238 // The fortran_vec offset for the Magenta, Yellow, and blacK channels |
1229 const octave_idx_type M_offset = nCols * nRows; | 1239 const octave_idx_type M_offset = nCols * nRows; |
1230 const octave_idx_type Y_offset = nCols * nRows * 2; | 1240 const octave_idx_type Y_offset = nCols * nRows * 2; |
1231 const octave_idx_type K_offset = nCols * nRows * 3; | 1241 const octave_idx_type K_offset = nCols * nRows * 3; |
1232 octave_idx_type GM_idx = 0; | |
1233 for (octave_idx_type frame = 0; frame < nFrames; frame++) | 1242 for (octave_idx_type frame = 0; frame < nFrames; frame++) |
1234 { | 1243 { |
1235 Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth, | 1244 Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth, |
1236 type, | 1245 type, |
1237 Magick::DirectClass); | 1246 Magick::DirectClass); |
1238 | 1247 |
1239 Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows); | 1248 Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows); |
1240 Magick::IndexPacket *ind = m_img.getIndexes (); | 1249 Magick::IndexPacket *ind = m_img.getIndexes (); |
1250 octave_idx_type GM_idx = 0; | |
1241 for (octave_idx_type col = 0; col < nCols; col++) | 1251 for (octave_idx_type col = 0; col < nCols; col++) |
1242 { | 1252 { |
1243 for (octave_idx_type row = 0; row < nRows; row++) | 1253 for (octave_idx_type row = 0; row < nRows; row++) |
1244 { | 1254 { |
1245 Magick::Color c (double (*img_fvec) / divisor, | 1255 Magick::Color c (double (*img_fvec) / divisor, |
1255 GM_idx -= nCols * nRows - 1; | 1265 GM_idx -= nCols * nRows - 1; |
1256 } | 1266 } |
1257 // Save changes to underlying image. | 1267 // Save changes to underlying image. |
1258 m_img.syncPixels (); | 1268 m_img.syncPixels (); |
1259 imvec.push_back (m_img); | 1269 imvec.push_back (m_img); |
1270 img_fvec += K_offset; | |
1260 } | 1271 } |
1261 break; | 1272 break; |
1262 } | 1273 } |
1263 | 1274 |
1264 default: | 1275 default: |