Mercurial > octave-dspies
comparison libinterp/dldfcn/__magick_read__.cc @ 17855:bfbe5dcc9943
imwrite: implement DisposalMethod option.
* __magick_read__.cc (F__magick_write__): set gifDisposeMethod() when
writing an image to implement the DisposalMethod option. Set all the
options in a single option rather than a loop per option.
(init_reverse_disposal_methods): new method to return a reversed std::map
of the disposal methods.
(init_disposal_methods): move up, to be closer to the new
init_reverse_disposal_methods()
* private/__imwrite__.m: input check for the new option DisposalMethod and
set its default.
* imwrite.m: document new option.
author | Carnë Draug <carandraug@octave.org> |
---|---|
date | Tue, 05 Nov 2013 07:05:30 +0000 |
parents | adb0ba0d0c13 |
children | 870f3e12e163 |
comparison
equal
deleted
inserted
replaced
17854:adb0ba0d0c13 | 17855:bfbe5dcc9943 |
---|---|
1250 error ("__magick_write__: unrecognized Magick::ImageType"); | 1250 error ("__magick_write__: unrecognized Magick::ImageType"); |
1251 return; | 1251 return; |
1252 } | 1252 } |
1253 } | 1253 } |
1254 return; | 1254 return; |
1255 } | |
1256 | |
1257 // Meant to be shared with both imfinfo and imwrite. | |
1258 static std::map<octave_idx_type, std::string> | |
1259 init_disposal_methods () | |
1260 { | |
1261 // GIF Specifications: | |
1262 // | |
1263 // Disposal Method - Indicates the way in which the graphic is to | |
1264 // be treated after being displayed. | |
1265 // | |
1266 // 0 - No disposal specified. The decoder is | |
1267 // not required to take any action. | |
1268 // 1 - Do not dispose. The graphic is to be left | |
1269 // in place. | |
1270 // 2 - Restore to background color. The area used by the | |
1271 // graphic must be restored to the background color. | |
1272 // 3 - Restore to previous. The decoder is required to | |
1273 // restore the area overwritten by the graphic with | |
1274 // what was there prior to rendering the graphic. | |
1275 // 4-7 - To be defined. | |
1276 static std::map<octave_idx_type, std::string> methods; | |
1277 if (methods.empty ()) | |
1278 { | |
1279 methods[0] = "doNotSpecify"; | |
1280 methods[1] = "leaveInPlace"; | |
1281 methods[2] = "restoreBG"; | |
1282 methods[3] = "restorePrevious"; | |
1283 } | |
1284 return methods; | |
1285 } | |
1286 static std::map<std::string, octave_idx_type> | |
1287 init_reverse_disposal_methods () | |
1288 { | |
1289 static std::map<std::string, octave_idx_type> methods; | |
1290 if (methods.empty ()) | |
1291 { | |
1292 methods["donotspecify"] = 0; | |
1293 methods["leaveinplace"] = 1; | |
1294 methods["restorebg"] = 2; | |
1295 methods["restoreprevious"] = 3; | |
1296 } | |
1297 return methods; | |
1255 } | 1298 } |
1256 | 1299 |
1257 void static | 1300 void static |
1258 write_file (const std::string& filename, | 1301 write_file (const std::string& filename, |
1259 const std::string& ext, | 1302 const std::string& ext, |
1382 { | 1425 { |
1383 error ("__magick_write__: indexed image must be uint8, uint16 or float."); | 1426 error ("__magick_write__: indexed image must be uint8, uint16 or float."); |
1384 return retval; | 1427 return retval; |
1385 } | 1428 } |
1386 } | 1429 } |
1430 static std::map<std::string, octave_idx_type> disposal_methods | |
1431 = init_reverse_disposal_methods (); | |
1387 | 1432 |
1388 const octave_idx_type nFrames = imvec.size (); | 1433 const octave_idx_type nFrames = imvec.size (); |
1389 | 1434 |
1390 const octave_idx_type quality = options.getfield ("quality").int_value (); | 1435 const octave_idx_type quality = options.getfield ("quality").int_value (); |
1436 const ColumnVector delaytime = options.getfield ("delaytime").column_vector_value (); | |
1437 const Array<std::string> disposalmethod = options.getfield ("disposalmethod").cellstr_value (); | |
1391 for (octave_idx_type i = 0; i < nFrames; i++) | 1438 for (octave_idx_type i = 0; i < nFrames; i++) |
1392 imvec[i].quality (quality); | 1439 { |
1393 | 1440 imvec[i].quality (quality); |
1394 const ColumnVector delaytime = options.getfield ("delaytime").column_vector_value (); | 1441 imvec[i].animationDelay (delaytime(i)); |
1395 for (octave_idx_type i = 0; i < nFrames; i++) | 1442 imvec[i].gifDisposeMethod (disposal_methods[disposalmethod(i)]); |
1396 imvec[i].animationDelay (delaytime(i)); | 1443 } |
1397 | 1444 |
1398 // If writemode is set to append, read the image and append to it. Even | 1445 // If writemode is set to append, read the image and append to it. Even |
1399 // if set to append, make sure that something was read at all. | 1446 // if set to append, make sure that something was read at all. |
1400 const std::string writemode = options.getfield ("writemode").string_value (); | 1447 const std::string writemode = options.getfield ("writemode").string_value (); |
1401 if (writemode == "append" && file_stat (filename).exists ()) | 1448 if (writemode == "append" && file_stat (filename).exists ()) |
1409 ini_imvec.insert (ini_imvec.end (), imvec.begin (), imvec.end ()); | 1456 ini_imvec.insert (ini_imvec.end (), imvec.begin (), imvec.end ()); |
1410 ini_imvec.swap (imvec); | 1457 ini_imvec.swap (imvec); |
1411 } | 1458 } |
1412 } | 1459 } |
1413 | 1460 |
1414 // FIXME - LoopCount or animationIterations | 1461 // FIXME - LoopCount or animationIterations |
1415 // How it should work: | 1462 // How it should work: |
1416 // | 1463 // |
1417 // This value is only set for the first image in the sequence. Trying | 1464 // This value is only set for the first image in the sequence. Trying |
1418 // to set this value with the append mode should have no effect, the | 1465 // to set this value with the append mode should have no effect, the |
1419 // value used with the first image is the one that counts (that would | 1466 // value used with the first image is the one that counts (that would |
1420 // also be Matlab compatible). Thus, the right way to do this would be | 1467 // also be Matlab compatible). Thus, the right way to do this would be |
1421 // to have an else block on the condition above, and set this only | 1468 // to have an else block on the condition above, and set this only |
1422 // when creating a new file. Since Matlab does not interpret a 4D | 1469 // when creating a new file. Since Matlab does not interpret a 4D |
1423 // matrix as sequence of images to write, its users need to use a for | 1470 // matrix as sequence of images to write, its users need to use a for |
1424 // loop and set LoopCount only on the first iteration (it actually | 1471 // loop and set LoopCount only on the first iteration (it actually |
1425 // throws warnings otherwise) | 1472 // throws warnings otherwise) |
1426 // | 1473 // |
1427 // Why is this not done the right way: | 1474 // Why is this not done the right way: |
1428 // | 1475 // |
1429 // When GM saves a single image, it discards the value if there is only | 1476 // When GM saves a single image, it discards the value if there is only |
1430 // a single image and sets it to "no loop". Since our default is an | 1477 // a single image and sets it to "no loop". Since our default is an |
1431 // infinite loop, if the user tries to do it the Matlab way (setting | 1478 // infinite loop, if the user tries to do it the Matlab way (setting |
1432 // LoopCount only on the first image) that value will go nowhere. | 1479 // LoopCount only on the first image) that value will go nowhere. |
1433 // See https://sourceforge.net/p/graphicsmagick/bugs/248/ | 1480 // See https://sourceforge.net/p/graphicsmagick/bugs/248/ |
1434 // Because of this, we document to set LoopCount on every iteration | 1481 // Because of this, we document to set LoopCount on every iteration |
1435 // (in Matlab will cause a lot of warnings), or pass a 4D matrix with | 1482 // (in Matlab will cause a lot of warnings), or pass a 4D matrix with |
1436 // all frames (won't work in Matlab at all). | 1483 // all frames (won't work in Matlab at all). |
1437 // Note that this only needs to be set on the first frame | 1484 // Note that this only needs to be set on the first frame |
1438 imvec[0].animationIterations (options.getfield ("loopcount").uint_value ()); | 1485 imvec[0].animationIterations (options.getfield ("loopcount").uint_value ()); |
1439 | 1486 |
1440 write_file (filename, ext, imvec); | 1487 write_file (filename, ext, imvec); |
1441 if (error_state) | 1488 if (error_state) |
1442 return retval; | 1489 return retval; |
1443 | 1490 |
1604 case Magick::PixelsPerCentimeterResolution: | 1651 case Magick::PixelsPerCentimeterResolution: |
1605 return octave_value ("Centimeter"); | 1652 return octave_value ("Centimeter"); |
1606 default: | 1653 default: |
1607 return octave_value ("undefined"); | 1654 return octave_value ("undefined"); |
1608 } | 1655 } |
1609 } | |
1610 | |
1611 // Meant to be shared with both imfinfo and imwrite. | |
1612 static std::map<octave_idx_type, std::string> | |
1613 init_disposal_methods () | |
1614 { | |
1615 // GIF Specifications: | |
1616 // | |
1617 // Disposal Method - Indicates the way in which the graphic is to | |
1618 // be treated after being displayed. | |
1619 // | |
1620 // 0 - No disposal specified. The decoder is | |
1621 // not required to take any action. | |
1622 // 1 - Do not dispose. The graphic is to be left | |
1623 // in place. | |
1624 // 2 - Restore to background color. The area used by the | |
1625 // graphic must be restored to the background color. | |
1626 // 3 - Restore to previous. The decoder is required to | |
1627 // restore the area overwritten by the graphic with | |
1628 // what was there prior to rendering the graphic. | |
1629 // 4-7 - To be defined. | |
1630 static std::map<octave_idx_type, std::string> methods; | |
1631 if (methods.empty ()) | |
1632 { | |
1633 methods[0] = "doNotSpecify"; | |
1634 methods[1] = "leaveInPlace"; | |
1635 methods[2] = "restoreBG"; | |
1636 methods[3] = "restorePrevious"; | |
1637 } | |
1638 return methods; | |
1639 } | 1656 } |
1640 | 1657 |
1641 static bool | 1658 static bool |
1642 is_valid_exif (const std::string& val) | 1659 is_valid_exif (const std::string& val) |
1643 { | 1660 { |