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: