19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% % 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% % 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% % 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% M M AAA TTTTT RRRR IIIII X X % 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% MM MM A A T R R I X X % 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% M M M AAAAA T RRRR I X % 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% M M A A T R R I X X % 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% M M A A T R R IIIII X X % 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% % 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% % 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% MagickCore Matrix Methods % 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% % 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% Software Design % 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% Cristy % 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% August 2007 % 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% % 19c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn% % 2089ad456ea49cb62615ebdcac83a2515743bbe5faDianne Hackborn% Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization % 2189ad456ea49cb62615ebdcac83a2515743bbe5faDianne Hackborn% dedicated to making software imaging solutions freely available. % 22d2932243e3313b59e7538641731aa98852bc5ac7Dianne Hackborn% % 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% You may not use this file except in compliance with the License. You may % 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% obtain a copy of the License at % 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% % 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% http://www.imagemagick.org/script/license.php % 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% % 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% Unless required by applicable law or agreed to in writing, software % 2980943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov% distributed under the License is distributed on an "AS IS" BASIS, % 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 31c68c913d357e2955d4bd7ca52829071e531c7825Dianne Hackborn% See the License for the specific language governing permissions and % 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% limitations under the License. % 33e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn% % 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% 36a0c283eac33dd2da72235751bbfa4f2d9898d5eaDianne Hackborn% 371ebccf531d1049853b3b0630035434619682c016Dianne Hackborn*/ 38f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn 39390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn/* 401655be46d2b7d45f071a6a1411ac8bd41c749c21Dianne Hackborn Include declarations. 411ebccf531d1049853b3b0630035434619682c016Dianne Hackborn*/ 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "MagickCore/studio.h" 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "MagickCore/blob.h" 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "MagickCore/blob-private.h" 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "MagickCore/cache.h" 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "MagickCore/exception.h" 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "MagickCore/exception-private.h" 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "MagickCore/image-private.h" 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "MagickCore/matrix.h" 50be4e6aaa0252dd7da28b7aa85beba982538efa46Dianne Hackborn#include "MagickCore/memory_.h" 512cd3fb5aa71cd32cd67ddfaafaca8f85a7ac13c6Adam Lesinski#include "MagickCore/pixel-accessor.h" 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "MagickCore/pixel-private.h" 53a0c283eac33dd2da72235751bbfa4f2d9898d5eaDianne Hackborn#include "MagickCore/resource_.h" 54a0c283eac33dd2da72235751bbfa4f2d9898d5eaDianne Hackborn#include "MagickCore/semaphore.h" 55a0c283eac33dd2da72235751bbfa4f2d9898d5eaDianne Hackborn#include "MagickCore/thread-private.h" 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "MagickCore/utility.h" 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 58f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn/* 59f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn Typedef declaration. 60fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn*/ 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct _MatrixInfo 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CacheType 64be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn type; 65099bc627c463d9941e23e480f25a78a154429c55Dianne Hackborn 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project columns, 68dd71fc8baeee0d09008d0fa67d6bf3d23cf21baaDianne Hackborn rows, 69f1cca18ae460b66242988a8a6204c4a42b6fa1c1Dianne Hackborn stride; 70f1cca18ae460b66242988a8a6204c4a42b6fa1c1Dianne Hackborn 71f1cca18ae460b66242988a8a6204c4a42b6fa1c1Dianne Hackborn MagickSizeType 7235f72be50b8a2d11bce591dcdac5dc3fa336dac0Dianne Hackborn length; 7335f72be50b8a2d11bce591dcdac5dc3fa336dac0Dianne Hackborn 743bc8f78d7a3d23a67c06221cc41292d04a2fd439Dianne Hackborn MagickBooleanType 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mapped, 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronize; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project path[MagickPathExtent]; 8006de2ea752171f52a4e6e6872cb3a0689e591dcbDianne Hackborn 8106de2ea752171f52a4e6e6872cb3a0689e591dcbDianne Hackborn int 82ce86ba86df61de8b34b226a4eb6c23ec33e866e0Dianne Hackborn file; 83a413dc06b2193442a2d956571b829aeb5fb97862Dianne Hackborn 84a413dc06b2193442a2d956571b829aeb5fb97862Dianne Hackborn void 85c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn *elements; 86f1cca18ae460b66242988a8a6204c4a42b6fa1c1Dianne Hackborn 87e02c88af7935c72fb90a478375e61e4a94465587Dianne Hackborn SemaphoreInfo 88cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn *semaphore; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9035f72be50b8a2d11bce591dcdac5dc3fa336dac0Dianne Hackborn size_t 91b12e1354f25f04e9c9a71da76c6fca858b7d39d0Dianne Hackborn signature; 922286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn}; 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 94d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey/* 95684bf34ee8acc41931fac23762b13e14a22011dbDianne Hackborn%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 96c68c913d357e2955d4bd7ca52829071e531c7825Dianne Hackborn% % 97f0754f5ba7a45b517cffcb3c2c96f2a32aeac06dDianne Hackborn% % 98c68c913d357e2955d4bd7ca52829071e531c7825Dianne Hackborn% % 99c68c913d357e2955d4bd7ca52829071e531c7825Dianne Hackborn% A c q u i r e M a t r i x I n f o % 100f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn% % 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% % 10235f72be50b8a2d11bce591dcdac5dc3fa336dac0Dianne Hackborn% % 103c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1049357b11a798b804b69907f93437229cac1d82468Dianne Hackborn% 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% AcquireMatrixInfo() allocates the ImageInfo structure. 106906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn% 107906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn% The format of the AcquireMatrixInfo method is: 1088ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn% 1091b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn% MatrixInfo *AcquireMatrixInfo(const size_t columns,const size_t rows, 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% const size_t stride,ExceptionInfo *exception) 1111655be46d2b7d45f071a6a1411ac8bd41c749c21Dianne Hackborn% 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% A description of each parameter follows: 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% 11480943d8daa6ab31ab5c486d57aea406aa0730d58Svetoslav Ganov% o columns: the matrix columns. 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% o rows: the matrix rows. 1173f9dd287b99340efaaa257759e71a8f81b2ed113Jeff Brown% 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% o stride: the matrix stride. 1199adb9c3b10991ef315c270993f4155709c8a232dDianne Hackborn% 120287952c35e148811c106bc0f5036eabf20f71562Dianne Hackborn% o exception: return any errors or warnings in this structure. 121287952c35e148811c106bc0f5036eabf20f71562Dianne Hackborn% 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/ 123fd12af4e768fec852c4c5dfee3b9bd7403b4b347Dianne Hackborn 124fd12af4e768fec852c4c5dfee3b9bd7403b4b347Dianne Hackborn#if defined(SIGBUS) 125dd71fc8baeee0d09008d0fa67d6bf3d23cf21baaDianne Hackbornstatic void MatrixSignalHandler(int status) 126be4e6aaa0252dd7da28b7aa85beba982538efa46Dianne Hackborn{ 127de42bb61ad0e4947a38bdedfba6a20b5292025c3Dianne Hackborn ThrowFatalException(CacheFatalError,"UnableToExtendMatrixCache"); 128dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn} 129de42bb61ad0e4947a38bdedfba6a20b5292025c3Dianne Hackborn#endif 130fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn 131de42bb61ad0e4947a38bdedfba6a20b5292025c3Dianne Hackbornstatic inline MagickOffsetType WriteMatrixElements( 132810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci const MatrixInfo *magick_restrict matrix_info,const MagickOffsetType offset, 133810c052d9b117217152c2a609ccec056a2a61d1ePrimiano Tucci const MagickSizeType length,const unsigned char *magick_restrict buffer) 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 13501e4cfc47d0a2c7e7ab383d2fb23224ec52c0301Dianne Hackborn register MagickOffsetType 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project i; 137c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ssize_t 139c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn count; 140c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if !defined(MAGICKCORE_HAVE_PWRITE) 142c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn LockSemaphoreInfo(matrix_info->semaphore); 143c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn if (lseek(matrix_info->file,offset,SEEK_SET) < 0) 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 145c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn UnlockSemaphoreInfo(matrix_info->semaphore); 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return((MagickOffsetType) -1); 147390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn } 148390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn#endif 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count=0; 1506ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn for (i=0; i < (MagickOffsetType) length; i+=count) 1516ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn { 152bf36ee2b0c49241e073da14ee1e1a08b8550f3b9Dianne Hackborn#if !defined(MAGICKCORE_HAVE_PWRITE) 153bf36ee2b0c49241e073da14ee1e1a08b8550f3b9Dianne Hackborn count=write(matrix_info->file,buffer+i,(size_t) MagickMin(length-i, 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (MagickSizeType) SSIZE_MAX)); 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count=pwrite(matrix_info->file,buffer+i,(size_t) MagickMin(length-i, 15758d380d2af8079075e4773a3e5ca6c2820760e3dChristopher Tate (MagickSizeType) SSIZE_MAX),(off_t) (offset+i)); 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count <= 0) 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count=0; 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (errno != EINTR) 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 165dd71fc8baeee0d09008d0fa67d6bf3d23cf21baaDianne Hackborn } 166f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn#if !defined(MAGICKCORE_HAVE_PWRITE) 167f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn UnlockSemaphoreInfo(matrix_info->semaphore); 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return(i); 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic MagickBooleanType SetMatrixExtent( 173f5b9c72022f574417862e064cc0fdd8ea2d846dcJacek Surazski MatrixInfo *magick_restrict matrix_info, 174f5b9c72022f574417862e064cc0fdd8ea2d846dcJacek Surazski MagickSizeType length) 175f5b9c72022f574417862e064cc0fdd8ea2d846dcJacek Surazski{ 176f5b9c72022f574417862e064cc0fdd8ea2d846dcJacek Surazski MagickOffsetType 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count, 1781ebccf531d1049853b3b0630035434619682c016Dianne Hackborn extent, 1791ebccf531d1049853b3b0630035434619682c016Dianne Hackborn offset; 180a0c283eac33dd2da72235751bbfa4f2d9898d5eaDianne Hackborn 181a0c283eac33dd2da72235751bbfa4f2d9898d5eaDianne Hackborn if (length != (MagickSizeType) ((MagickOffsetType) length)) 182a0c283eac33dd2da72235751bbfa4f2d9898d5eaDianne Hackborn return(MagickFalse); 183a0c283eac33dd2da72235751bbfa4f2d9898d5eaDianne Hackborn offset=(MagickOffsetType) lseek(matrix_info->file,0,SEEK_END); 184a0c283eac33dd2da72235751bbfa4f2d9898d5eaDianne Hackborn if (offset < 0) 185a0c283eac33dd2da72235751bbfa4f2d9898d5eaDianne Hackborn return(MagickFalse); 186f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn if ((MagickSizeType) offset >= length) 187f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn return(MagickTrue); 188f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn extent=(MagickOffsetType) length-1; 189f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn count=WriteMatrixElements(matrix_info,extent,1,(const unsigned char *) ""); 190f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn#if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE) 191f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn if (matrix_info->synchronize != MagickFalse) 192f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn (void) posix_fallocate(matrix_info->file,offset+1,extent-offset); 193f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn#endif 194f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn#if defined(SIGBUS) 195f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn (void) signal(SIGBUS,MatrixSignalHandler); 196cfc837f7fa43362b5049f648fe1bfdf5a010cc1cDianne Hackborn#endif 197cfc837f7fa43362b5049f648fe1bfdf5a010cc1cDianne Hackborn return(count != (MagickOffsetType) 1 ? MagickFalse : MagickTrue); 198cfc837f7fa43362b5049f648fe1bfdf5a010cc1cDianne Hackborn} 199cfc837f7fa43362b5049f648fe1bfdf5a010cc1cDianne Hackborn 200cfc837f7fa43362b5049f648fe1bfdf5a010cc1cDianne HackbornMagickExport MatrixInfo *AcquireMatrixInfo(const size_t columns, 201cfc837f7fa43362b5049f648fe1bfdf5a010cc1cDianne Hackborn const size_t rows,const size_t stride,ExceptionInfo *exception) 202fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn{ 203fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn char 204fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn *synchronize; 205fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn 206fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn MagickBooleanType 207fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn status; 208fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn 209fee756ff91ab4d8f0e09ddb050d22d88ebb66ae7Dianne Hackborn MatrixInfo 2108ea5e1d79eb1f05ee7628b0d45ea8fc8eea5330dDianne Hackborn *matrix_info; 211f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn 212f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn matrix_info=(MatrixInfo *) AcquireMagickMemory(sizeof(*matrix_info)); 213f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn if (matrix_info == (MatrixInfo *) NULL) 214f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn return((MatrixInfo *) NULL); 215f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn (void) ResetMagickMemory(matrix_info,0,sizeof(*matrix_info)); 216f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn matrix_info->signature=MagickCoreSignature; 217f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn matrix_info->columns=columns; 218f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn matrix_info->rows=rows; 2191655be46d2b7d45f071a6a1411ac8bd41c749c21Dianne Hackborn matrix_info->stride=stride; 2201655be46d2b7d45f071a6a1411ac8bd41c749c21Dianne Hackborn matrix_info->semaphore=AcquireSemaphoreInfo(); 2211655be46d2b7d45f071a6a1411ac8bd41c749c21Dianne Hackborn synchronize=GetEnvironmentValue("MAGICK_SYNCHRONIZE"); 2221655be46d2b7d45f071a6a1411ac8bd41c749c21Dianne Hackborn if (synchronize != (const char *) NULL) 2231655be46d2b7d45f071a6a1411ac8bd41c749c21Dianne Hackborn { 224f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn matrix_info->synchronize=IsStringTrue(synchronize); 225b12e1354f25f04e9c9a71da76c6fca858b7d39d0Dianne Hackborn synchronize=DestroyString(synchronize); 226f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn } 227cfc837f7fa43362b5049f648fe1bfdf5a010cc1cDianne Hackborn matrix_info->length=(MagickSizeType) columns*rows*stride; 2281ebccf531d1049853b3b0630035434619682c016Dianne Hackborn if (matrix_info->columns != (size_t) (matrix_info->length/rows/stride)) 2291ebccf531d1049853b3b0630035434619682c016Dianne Hackborn { 2303bc8f78d7a3d23a67c06221cc41292d04a2fd439Dianne Hackborn (void) ThrowMagickException(exception,GetMagickModule(),CacheError, 2313bc8f78d7a3d23a67c06221cc41292d04a2fd439Dianne Hackborn "CacheResourcesExhausted","`%s'","matrix cache"); 2323bc8f78d7a3d23a67c06221cc41292d04a2fd439Dianne Hackborn return(DestroyMatrixInfo(matrix_info)); 2333bc8f78d7a3d23a67c06221cc41292d04a2fd439Dianne Hackborn } 2343bc8f78d7a3d23a67c06221cc41292d04a2fd439Dianne Hackborn matrix_info->type=MemoryCache; 2353bc8f78d7a3d23a67c06221cc41292d04a2fd439Dianne Hackborn status=AcquireMagickResource(AreaResource,matrix_info->length); 2363bc8f78d7a3d23a67c06221cc41292d04a2fd439Dianne Hackborn if ((status != MagickFalse) && 2373bc8f78d7a3d23a67c06221cc41292d04a2fd439Dianne Hackborn (matrix_info->length == (MagickSizeType) ((size_t) matrix_info->length))) 2383bc8f78d7a3d23a67c06221cc41292d04a2fd439Dianne Hackborn { 239fdb1956ff71ff57fcdaafaaeb7f42c19de3d7c2fDianne Hackborn status=AcquireMagickResource(MemoryResource,matrix_info->length); 240dd71fc8baeee0d09008d0fa67d6bf3d23cf21baaDianne Hackborn if (status != MagickFalse) 241cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn { 242cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn matrix_info->mapped=MagickFalse; 243cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn matrix_info->elements=AcquireMagickMemory((size_t) 244cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn matrix_info->length); 24535f72be50b8a2d11bce591dcdac5dc3fa336dac0Dianne Hackborn if (matrix_info->elements == NULL) 24635f72be50b8a2d11bce591dcdac5dc3fa336dac0Dianne Hackborn { 2473bc8f78d7a3d23a67c06221cc41292d04a2fd439Dianne Hackborn matrix_info->mapped=MagickTrue; 24835f72be50b8a2d11bce591dcdac5dc3fa336dac0Dianne Hackborn matrix_info->elements=MapBlob(-1,IOMode,0,(size_t) 249f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn matrix_info->length); 250f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn } 251f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn if (matrix_info->elements == (unsigned short *) NULL) 252f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn RelinquishMagickResource(MemoryResource,matrix_info->length); 253f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn } 25406de2ea752171f52a4e6e6872cb3a0689e591dcbDianne Hackborn } 255ce86ba86df61de8b34b226a4eb6c23ec33e866e0Dianne Hackborn matrix_info->file=(-1); 256c68c913d357e2955d4bd7ca52829071e531c7825Dianne Hackborn if (matrix_info->elements == (unsigned short *) NULL) 257ce86ba86df61de8b34b226a4eb6c23ec33e866e0Dianne Hackborn { 258a413dc06b2193442a2d956571b829aeb5fb97862Dianne Hackborn status=AcquireMagickResource(DiskResource,matrix_info->length); 259c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn if (status == MagickFalse) 260f1cca18ae460b66242988a8a6204c4a42b6fa1c1Dianne Hackborn { 261f1cca18ae460b66242988a8a6204c4a42b6fa1c1Dianne Hackborn (void) ThrowMagickException(exception,GetMagickModule(),CacheError, 262f1cca18ae460b66242988a8a6204c4a42b6fa1c1Dianne Hackborn "CacheResourcesExhausted","`%s'","matrix cache"); 263f1cca18ae460b66242988a8a6204c4a42b6fa1c1Dianne Hackborn return(DestroyMatrixInfo(matrix_info)); 264f1cca18ae460b66242988a8a6204c4a42b6fa1c1Dianne Hackborn } 265f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn matrix_info->type=DiskCache; 266b12e1354f25f04e9c9a71da76c6fca858b7d39d0Dianne Hackborn (void) AcquireMagickResource(MemoryResource,matrix_info->length); 267b12e1354f25f04e9c9a71da76c6fca858b7d39d0Dianne Hackborn matrix_info->file=AcquireUniqueFileResource(matrix_info->path); 268f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn if (matrix_info->file == -1) 269f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn return(DestroyMatrixInfo(matrix_info)); 270b12e1354f25f04e9c9a71da76c6fca858b7d39d0Dianne Hackborn status=AcquireMagickResource(MapResource,matrix_info->length); 271b12e1354f25f04e9c9a71da76c6fca858b7d39d0Dianne Hackborn if (status != MagickFalse) 272b12e1354f25f04e9c9a71da76c6fca858b7d39d0Dianne Hackborn { 273b12e1354f25f04e9c9a71da76c6fca858b7d39d0Dianne Hackborn status=SetMatrixExtent(matrix_info,matrix_info->length); 274b12e1354f25f04e9c9a71da76c6fca858b7d39d0Dianne Hackborn if (status != MagickFalse) 275b12e1354f25f04e9c9a71da76c6fca858b7d39d0Dianne Hackborn { 276b12e1354f25f04e9c9a71da76c6fca858b7d39d0Dianne Hackborn matrix_info->elements=(void *) MapBlob(matrix_info->file,IOMode,0, 277b12e1354f25f04e9c9a71da76c6fca858b7d39d0Dianne Hackborn (size_t) matrix_info->length); 278b12e1354f25f04e9c9a71da76c6fca858b7d39d0Dianne Hackborn if (matrix_info->elements != NULL) 279b12e1354f25f04e9c9a71da76c6fca858b7d39d0Dianne Hackborn matrix_info->type=MapCache; 280684bf34ee8acc41931fac23762b13e14a22011dbDianne Hackborn else 281db92608de9b4acccee1e3232264c9830ad300c4fDianne Hackborn RelinquishMagickResource(MapResource,matrix_info->length); 282684bf34ee8acc41931fac23762b13e14a22011dbDianne Hackborn } 283684bf34ee8acc41931fac23762b13e14a22011dbDianne Hackborn } 284b12e1354f25f04e9c9a71da76c6fca858b7d39d0Dianne Hackborn } 2852286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn return(matrix_info); 2862286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn} 2872286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn 288fdb1956ff71ff57fcdaafaaeb7f42c19de3d7c2fDianne Hackborn/* 289287952c35e148811c106bc0f5036eabf20f71562Dianne Hackborn%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2902cd3fb5aa71cd32cd67ddfaafaca8f85a7ac13c6Adam Lesinski% % 2912cd3fb5aa71cd32cd67ddfaafaca8f85a7ac13c6Adam Lesinski% % 292287952c35e148811c106bc0f5036eabf20f71562Dianne Hackborn% % 293287952c35e148811c106bc0f5036eabf20f71562Dianne Hackborn% A c q u i r e M a g i c k M a t r i x % 294287952c35e148811c106bc0f5036eabf20f71562Dianne Hackborn% % 295b12e1354f25f04e9c9a71da76c6fca858b7d39d0Dianne Hackborn% % 296fdb1956ff71ff57fcdaafaaeb7f42c19de3d7c2fDianne Hackborn% % 297287952c35e148811c106bc0f5036eabf20f71562Dianne Hackborn%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 298b12e1354f25f04e9c9a71da76c6fca858b7d39d0Dianne Hackborn% 299287952c35e148811c106bc0f5036eabf20f71562Dianne Hackborn% AcquireMagickMatrix() allocates and returns a matrix in the form of an 300287952c35e148811c106bc0f5036eabf20f71562Dianne Hackborn% array of pointers to an array of doubles, with all values pre-set to zero. 3010d903a84d04d241a648ec429e3a0e82c712677fdDianne Hackborn% 3021ebccf531d1049853b3b0630035434619682c016Dianne Hackborn% This used to generate the two dimensional matrix, and vectors required 3031ebccf531d1049853b3b0630035434619682c016Dianne Hackborn% for the GaussJordanElimination() method below, solving some system of 3041ebccf531d1049853b3b0630035434619682c016Dianne Hackborn% simultanious equations. 3059adb9c3b10991ef315c270993f4155709c8a232dDianne Hackborn% 30635f72be50b8a2d11bce591dcdac5dc3fa336dac0Dianne Hackborn% The format of the AcquireMagickMatrix method is: 30735f72be50b8a2d11bce591dcdac5dc3fa336dac0Dianne Hackborn% 3080c5001d776d56bae02a5cc2663286a125d99bc5eDianne Hackborn% double **AcquireMagickMatrix(const size_t number_rows, 309149427cd903f2100e3cc39bda41b831cd68bc553Dianne Hackborn% const size_t size) 310f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn% 311f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn% A description of each parameter follows: 312f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn% 313f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn% o number_rows: the number pointers for the array of pointers 314f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn% (first dimension). 315f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn% 316f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn% o size: the size of the array of doubles each pointer points to 317f5b9c72022f574417862e064cc0fdd8ea2d846dcJacek Surazski% (second dimension). 318f5b9c72022f574417862e064cc0fdd8ea2d846dcJacek Surazski% 319f5b9c72022f574417862e064cc0fdd8ea2d846dcJacek Surazski*/ 320f5b9c72022f574417862e064cc0fdd8ea2d846dcJacek SurazskiMagickExport double **AcquireMagickMatrix(const size_t number_rows, 321f5b9c72022f574417862e064cc0fdd8ea2d846dcJacek Surazski const size_t size) 322f5b9c72022f574417862e064cc0fdd8ea2d846dcJacek Surazski{ 323f5b9c72022f574417862e064cc0fdd8ea2d846dcJacek Surazski double 324f5b9c72022f574417862e064cc0fdd8ea2d846dcJacek Surazski **matrix; 325f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn 326f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn register ssize_t 3276ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn i, 3286ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn j; 3296ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn 3306ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn matrix=(double **) AcquireQuantumMemory(number_rows,sizeof(*matrix)); 331f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn if (matrix == (double **) NULL) 332f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn return((double **) NULL); 3336ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn for (i=0; i < (ssize_t) number_rows; i++) 334c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn { 335c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn matrix[i]=(double *) AcquireQuantumMemory(size,sizeof(*matrix[i])); 3366ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn if (matrix[i] == (double *) NULL) 337f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn { 338f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn for (j=0; j < i; j++) 339bf36ee2b0c49241e073da14ee1e1a08b8550f3b9Dianne Hackborn matrix[j]=(double *) RelinquishMagickMemory(matrix[j]); 340bf36ee2b0c49241e073da14ee1e1a08b8550f3b9Dianne Hackborn matrix=(double **) RelinquishMagickMemory(matrix); 341c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn return((double **) NULL); 342c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn } 3436ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn for (j=0; j < (ssize_t) size; j++) 344f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn matrix[i][j]=0.0; 345f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn } 3466ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn return(matrix); 347c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn} 348c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn 3496ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn/* 350f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 351f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn% % 3526ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn% % 353390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn% % 354390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn% D e s t r o y M a t r i x I n f o % 355390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn% % 3566ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn% % 357f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn% % 358f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3596ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn% 3606ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn% DestroyMatrixInfo() dereferences a matrix, deallocating memory associated 3616ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn% with the matrix. 3626ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn% 363f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn% The format of the DestroyImage method is: 364b12e1354f25f04e9c9a71da76c6fca858b7d39d0Dianne Hackborn% 365b12e1354f25f04e9c9a71da76c6fca858b7d39d0Dianne Hackborn% MatrixInfo *DestroyMatrixInfo(MatrixInfo *matrix_info) 366b12e1354f25f04e9c9a71da76c6fca858b7d39d0Dianne Hackborn% 367f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn% A description of each parameter follows: 3686ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn% 369c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn% o matrix_info: the matrix. 370c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn% 3716ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn*/ 372f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne HackbornMagickExport MatrixInfo *DestroyMatrixInfo(MatrixInfo *matrix_info) 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project assert(matrix_info != (MatrixInfo *) NULL); 3752cd3fb5aa71cd32cd67ddfaafaca8f85a7ac13c6Adam Lesinski assert(matrix_info->signature == MagickCoreSignature); 376be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn LockSemaphoreInfo(matrix_info->semaphore); 3772cd3fb5aa71cd32cd67ddfaafaca8f85a7ac13c6Adam Lesinski switch (matrix_info->type) 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 379a0c283eac33dd2da72235751bbfa4f2d9898d5eaDianne Hackborn case MemoryCache: 380a0c283eac33dd2da72235751bbfa4f2d9898d5eaDianne Hackborn { 381f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn if (matrix_info->mapped == MagickFalse) 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project matrix_info->elements=RelinquishMagickMemory(matrix_info->elements); 383f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn else 384c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn { 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void) UnmapBlob(matrix_info->elements,(size_t) matrix_info->length); 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project matrix_info->elements=(unsigned short *) NULL; 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project RelinquishMagickResource(MemoryResource,matrix_info->length); 389f1cca18ae460b66242988a8a6204c4a42b6fa1c1Dianne Hackborn break; 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MapCache: 392f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn { 393f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn (void) UnmapBlob(matrix_info->elements,(size_t) matrix_info->length); 394dd71fc8baeee0d09008d0fa67d6bf3d23cf21baaDianne Hackborn matrix_info->elements=NULL; 395f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn RelinquishMagickResource(MapResource,matrix_info->length); 396f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn } 397be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn case DiskCache: 398be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn { 399be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn if (matrix_info->file != -1) 400be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn (void) close(matrix_info->file); 401be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn (void) RelinquishUniqueFileResource(matrix_info->path); 402be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn RelinquishMagickResource(DiskResource,matrix_info->length); 403be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn break; 404be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn } 405be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn default: 406be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn break; 4078472e6189cd4e0520c047bdb28457abc728b373fDianne Hackborn } 408be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn UnlockSemaphoreInfo(matrix_info->semaphore); 409be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn RelinquishSemaphoreInfo(&matrix_info->semaphore); 410f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn return((MatrixInfo *) RelinquishMagickMemory(matrix_info)); 411f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn} 412f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn 413be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn/* 414f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4158472e6189cd4e0520c047bdb28457abc728b373fDianne Hackborn% % 416f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn% % 417f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn% % 418be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn+ G a u s s J o r d a n E l i m i n a t i o n % 419be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn% % 420be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn% % 421be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn% % 422be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 423be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn% 424be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn% GaussJordanElimination() returns a matrix in reduced row echelon form, 42553459a7020dbcd036e2d3418e35ebb96fadc29e3Dianne Hackborn% while simultaneously reducing and thus solving the augumented results 42653459a7020dbcd036e2d3418e35ebb96fadc29e3Dianne Hackborn% matrix. 42753459a7020dbcd036e2d3418e35ebb96fadc29e3Dianne Hackborn% 428be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn% See also http://en.wikipedia.org/wiki/Gauss-Jordan_elimination 429be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn% 430be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn% The format of the GaussJordanElimination method is: 431be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn% 432be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn% MagickBooleanType GaussJordanElimination(double **matrix, 433be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn% double **vectors,const size_t rank,const size_t number_vectors) 434be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn% 435f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn% A description of each parameter follows: 436f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn% 437f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn% o matrix: the matrix to be reduced, as an 'array of row pointers'. 438be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn% 439f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn% o vectors: the additional matrix argumenting the matrix for row reduction. 440be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn% Producing an 'array of column vectors'. 441be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn% 442be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn% o rank: The size of the matrix (both rows and columns). 443be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn% Also represents the number terms that need to be solved. 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% o number_vectors: Number of vectors columns, argumenting the above matrix. 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% Usally 1, but can be more for more complex equation solving. 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% Note that the 'matrix' is given as a 'array of row pointers' of rank size. 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% That is values can be assigned as matrix[row][column] where 'row' is 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% typically the equation, and 'column' is the term of the equation. 45101e4cfc47d0a2c7e7ab383d2fb23224ec52c0301Dianne Hackborn% That is the matrix is in the form of a 'row first array'. 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% However 'vectors' is a 'array of column pointers' which can have any number 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% of columns, with each column array the same 'rank' size as 'matrix'. 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% This allows for simpler handling of the results, especially is only one 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% column 'vector' is all that is required to produce the desired solution. 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% For example, the 'vectors' can consist of a pointer to a simple array of 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% doubles. when only one set of simultanious equations is to be solved from 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% the given set of coefficient weighted terms. 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% 463860755faa6bdd3c2aeae49c05b87b5bc080ae60cDianne Hackborn% double **matrix = AcquireMagickMatrix(8UL,8UL); 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% double coefficents[8]; 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% ... 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% GaussJordanElimination(matrix, &coefficents, 8UL, 1UL); 4671b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn% 4681b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn% However by specifing more 'columns' (as an 'array of vector columns', 4691b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn% you can use this function to solve a set of 'separable' equations. 4701b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn% 4711b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn% For example a distortion function where u = U(x,y) v = V(x,y) 4721b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn% And the functions U() and V() have separate coefficents, but are being 4731b64e0d8657463c0f7ce9b068a16a522cdfe7d28Dianne Hackborn% generated from a common x,y->u,v data set. 474c68c913d357e2955d4bd7ca52829071e531c7825Dianne Hackborn% 475c68c913d357e2955d4bd7ca52829071e531c7825Dianne Hackborn% Another example is generation of a color gradient from a set of colors at 476c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn% specific coordients, such as a list x,y -> r,g,b,a. 477c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn% 478c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn% You can also use the 'vectors' to generate an inverse of the given 'matrix' 479c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn% though as a 'column first array' rather than a 'row first array'. For 480c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn% details see http://en.wikipedia.org/wiki/Gauss-Jordan_elimination 481c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn% 482c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn*/ 483c8230519728b14065effd3b7d4eca273ff86160cDianne HackbornMagickPrivate MagickBooleanType GaussJordanElimination(double **matrix, 484c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn double **vectors,const size_t rank,const size_t number_vectors) 485c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn{ 486c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn#define GaussJordanSwap(x,y) \ 487c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn{ \ 488c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn if ((x) != (y)) \ 489c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn { \ 490c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn (x)+=(y); \ 491c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn (y)=(x)-(y); \ 492c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn (x)=(x)-(y); \ 493c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn } \ 494c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn} 495c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn 496c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn double 497c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn max, 498c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn scale; 499c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn 500c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn register ssize_t 501c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn i, 502c68c913d357e2955d4bd7ca52829071e531c7825Dianne Hackborn j, 503c68c913d357e2955d4bd7ca52829071e531c7825Dianne Hackborn k; 504c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn 505c68c913d357e2955d4bd7ca52829071e531c7825Dianne Hackborn ssize_t 506c68c913d357e2955d4bd7ca52829071e531c7825Dianne Hackborn column, 50789ad456ea49cb62615ebdcac83a2515743bbe5faDianne Hackborn *columns, 50889ad456ea49cb62615ebdcac83a2515743bbe5faDianne Hackborn *pivots, 50989ad456ea49cb62615ebdcac83a2515743bbe5faDianne Hackborn row, 51089ad456ea49cb62615ebdcac83a2515743bbe5faDianne Hackborn *rows; 51189ad456ea49cb62615ebdcac83a2515743bbe5faDianne Hackborn 51289ad456ea49cb62615ebdcac83a2515743bbe5faDianne Hackborn columns=(ssize_t *) AcquireQuantumMemory(rank,sizeof(*columns)); 51389ad456ea49cb62615ebdcac83a2515743bbe5faDianne Hackborn rows=(ssize_t *) AcquireQuantumMemory(rank,sizeof(*rows)); 51489ad456ea49cb62615ebdcac83a2515743bbe5faDianne Hackborn pivots=(ssize_t *) AcquireQuantumMemory(rank,sizeof(*pivots)); 51589ad456ea49cb62615ebdcac83a2515743bbe5faDianne Hackborn if ((rows == (ssize_t *) NULL) || (columns == (ssize_t *) NULL) || 51689ad456ea49cb62615ebdcac83a2515743bbe5faDianne Hackborn (pivots == (ssize_t *) NULL)) 51789ad456ea49cb62615ebdcac83a2515743bbe5faDianne Hackborn { 51889ad456ea49cb62615ebdcac83a2515743bbe5faDianne Hackborn if (pivots != (ssize_t *) NULL) 51989ad456ea49cb62615ebdcac83a2515743bbe5faDianne Hackborn pivots=(ssize_t *) RelinquishMagickMemory(pivots); 52089ad456ea49cb62615ebdcac83a2515743bbe5faDianne Hackborn if (columns != (ssize_t *) NULL) 52189ad456ea49cb62615ebdcac83a2515743bbe5faDianne Hackborn columns=(ssize_t *) RelinquishMagickMemory(columns); 522dd71fc8baeee0d09008d0fa67d6bf3d23cf21baaDianne Hackborn if (rows != (ssize_t *) NULL) 523dd71fc8baeee0d09008d0fa67d6bf3d23cf21baaDianne Hackborn rows=(ssize_t *) RelinquishMagickMemory(rows); 524dd71fc8baeee0d09008d0fa67d6bf3d23cf21baaDianne Hackborn return(MagickFalse); 525f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn } 526f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn (void) ResetMagickMemory(columns,0,rank*sizeof(*columns)); 527dd71fc8baeee0d09008d0fa67d6bf3d23cf21baaDianne Hackborn (void) ResetMagickMemory(rows,0,rank*sizeof(*rows)); 528dd71fc8baeee0d09008d0fa67d6bf3d23cf21baaDianne Hackborn (void) ResetMagickMemory(pivots,0,rank*sizeof(*pivots)); 529dd71fc8baeee0d09008d0fa67d6bf3d23cf21baaDianne Hackborn column=0; 530dd71fc8baeee0d09008d0fa67d6bf3d23cf21baaDianne Hackborn row=0; 531dd71fc8baeee0d09008d0fa67d6bf3d23cf21baaDianne Hackborn for (i=0; i < (ssize_t) rank; i++) 532f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn { 533f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn max=0.0; 534f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn for (j=0; j < (ssize_t) rank; j++) 535f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn if (pivots[j] != 1) 536a0c283eac33dd2da72235751bbfa4f2d9898d5eaDianne Hackborn { 537a0c283eac33dd2da72235751bbfa4f2d9898d5eaDianne Hackborn for (k=0; k < (ssize_t) rank; k++) 538a0c283eac33dd2da72235751bbfa4f2d9898d5eaDianne Hackborn if (pivots[k] != 0) 539a0c283eac33dd2da72235751bbfa4f2d9898d5eaDianne Hackborn { 540a0c283eac33dd2da72235751bbfa4f2d9898d5eaDianne Hackborn if (pivots[k] > 1) 541a4cc205ee840a5374a96c9635dc5121d82a3eaf9Dianne Hackborn return(MagickFalse); 542a4cc205ee840a5374a96c9635dc5121d82a3eaf9Dianne Hackborn } 543a4cc205ee840a5374a96c9635dc5121d82a3eaf9Dianne Hackborn else 544a4cc205ee840a5374a96c9635dc5121d82a3eaf9Dianne Hackborn if (fabs(matrix[j][k]) >= max) 545a4cc205ee840a5374a96c9635dc5121d82a3eaf9Dianne Hackborn { 546a4cc205ee840a5374a96c9635dc5121d82a3eaf9Dianne Hackborn max=fabs(matrix[j][k]); 547a4cc205ee840a5374a96c9635dc5121d82a3eaf9Dianne Hackborn row=j; 548a4cc205ee840a5374a96c9635dc5121d82a3eaf9Dianne Hackborn column=k; 549a0c283eac33dd2da72235751bbfa4f2d9898d5eaDianne Hackborn } 550a0c283eac33dd2da72235751bbfa4f2d9898d5eaDianne Hackborn } 551f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn pivots[column]++; 552a0c283eac33dd2da72235751bbfa4f2d9898d5eaDianne Hackborn if (row != column) 553a0c283eac33dd2da72235751bbfa4f2d9898d5eaDianne Hackborn { 554dd71fc8baeee0d09008d0fa67d6bf3d23cf21baaDianne Hackborn for (k=0; k < (ssize_t) rank; k++) 555dd71fc8baeee0d09008d0fa67d6bf3d23cf21baaDianne Hackborn GaussJordanSwap(matrix[row][k],matrix[column][k]); 556dd71fc8baeee0d09008d0fa67d6bf3d23cf21baaDianne Hackborn for (k=0; k < (ssize_t) number_vectors; k++) 557dd71fc8baeee0d09008d0fa67d6bf3d23cf21baaDianne Hackborn GaussJordanSwap(vectors[k][row],vectors[k][column]); 558dd71fc8baeee0d09008d0fa67d6bf3d23cf21baaDianne Hackborn } 559dd71fc8baeee0d09008d0fa67d6bf3d23cf21baaDianne Hackborn rows[i]=row; 560dd71fc8baeee0d09008d0fa67d6bf3d23cf21baaDianne Hackborn columns[i]=column; 561dd71fc8baeee0d09008d0fa67d6bf3d23cf21baaDianne Hackborn if (matrix[column][column] == 0.0) 562ce86ba86df61de8b34b226a4eb6c23ec33e866e0Dianne Hackborn return(MagickFalse); /* sigularity */ 563ce86ba86df61de8b34b226a4eb6c23ec33e866e0Dianne Hackborn scale=PerceptibleReciprocal(matrix[column][column]); 564dd71fc8baeee0d09008d0fa67d6bf3d23cf21baaDianne Hackborn matrix[column][column]=1.0; 565f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn for (j=0; j < (ssize_t) rank; j++) 566f210d6b75e2c0fe60b90c074ff9f615c1137f23eDianne Hackborn matrix[column][j]*=scale; 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (j=0; j < (ssize_t) number_vectors; j++) 5689210bc85545f31973c957b5179e6a82d05f473c6Dianne Hackborn vectors[j][column]*=scale; 5699210bc85545f31973c957b5179e6a82d05f473c6Dianne Hackborn for (j=0; j < (ssize_t) rank; j++) 5709210bc85545f31973c957b5179e6a82d05f473c6Dianne Hackborn if (j != column) 5718e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn { 5729210bc85545f31973c957b5179e6a82d05f473c6Dianne Hackborn scale=matrix[j][column]; 5739210bc85545f31973c957b5179e6a82d05f473c6Dianne Hackborn matrix[j][column]=0.0; 5749210bc85545f31973c957b5179e6a82d05f473c6Dianne Hackborn for (k=0; k < (ssize_t) rank; k++) 5759210bc85545f31973c957b5179e6a82d05f473c6Dianne Hackborn matrix[j][k]-=scale*matrix[column][k]; 5769210bc85545f31973c957b5179e6a82d05f473c6Dianne Hackborn for (k=0; k < (ssize_t) number_vectors; k++) 5779210bc85545f31973c957b5179e6a82d05f473c6Dianne Hackborn vectors[k][j]-=scale*vectors[k][column]; 5789210bc85545f31973c957b5179e6a82d05f473c6Dianne Hackborn } 5799210bc85545f31973c957b5179e6a82d05f473c6Dianne Hackborn } 5809210bc85545f31973c957b5179e6a82d05f473c6Dianne Hackborn for (j=(ssize_t) rank-1; j >= 0; j--) 5819210bc85545f31973c957b5179e6a82d05f473c6Dianne Hackborn if (columns[j] != rows[j]) 5829210bc85545f31973c957b5179e6a82d05f473c6Dianne Hackborn for (i=0; i < (ssize_t) rank; i++) 5839210bc85545f31973c957b5179e6a82d05f473c6Dianne Hackborn GaussJordanSwap(matrix[i][rows[j]],matrix[i][columns[j]]); 5849210bc85545f31973c957b5179e6a82d05f473c6Dianne Hackborn pivots=(ssize_t *) RelinquishMagickMemory(pivots); 5859210bc85545f31973c957b5179e6a82d05f473c6Dianne Hackborn rows=(ssize_t *) RelinquishMagickMemory(rows); 5869210bc85545f31973c957b5179e6a82d05f473c6Dianne Hackborn columns=(ssize_t *) RelinquishMagickMemory(columns); 5879210bc85545f31973c957b5179e6a82d05f473c6Dianne Hackborn return(MagickTrue); 5889210bc85545f31973c957b5179e6a82d05f473c6Dianne Hackborn} 5899210bc85545f31973c957b5179e6a82d05f473c6Dianne Hackborn 5908e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn/* 5919210bc85545f31973c957b5179e6a82d05f473c6Dianne Hackborn%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5928e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn% % 5939210bc85545f31973c957b5179e6a82d05f473c6Dianne Hackborn% % 5949210bc85545f31973c957b5179e6a82d05f473c6Dianne Hackborn% % 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% G e t M a t r i x C o l u m n s % 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% % 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% % 598f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn% % 59978a369c90f61981c9d0ddd5fcbc77202bfbe74f6Dianne Hackborn%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6003251b9075246841a7b1ddecf10859b1abd858f33Dianne Hackborn% 6013251b9075246841a7b1ddecf10859b1abd858f33Dianne Hackborn% GetMatrixColumns() returns the number of columns in the matrix. 60253459a7020dbcd036e2d3418e35ebb96fadc29e3Dianne Hackborn% 603f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn% The format of the GetMatrixColumns method is: 604f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn% 605f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn% size_t GetMatrixColumns(const MatrixInfo *matrix_info) 606f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn% 607f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn% A description of each parameter follows: 60853459a7020dbcd036e2d3418e35ebb96fadc29e3Dianne Hackborn% 60953459a7020dbcd036e2d3418e35ebb96fadc29e3Dianne Hackborn% o matrix_info: the matrix. 6103251b9075246841a7b1ddecf10859b1abd858f33Dianne Hackborn% 61153459a7020dbcd036e2d3418e35ebb96fadc29e3Dianne Hackborn*/ 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectMagickExport size_t GetMatrixColumns(const MatrixInfo *matrix_info) 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project assert(matrix_info != (MatrixInfo *) NULL); 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project assert(matrix_info->signature == MagickCoreSignature); 61678a369c90f61981c9d0ddd5fcbc77202bfbe74f6Dianne Hackborn return(matrix_info->columns); 6172286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn} 61820cdcee47d10986969e7e2a53a40a6ecabae3827Dianne Hackborn 61920cdcee47d10986969e7e2a53a40a6ecabae3827Dianne Hackborn/* 62020cdcee47d10986969e7e2a53a40a6ecabae3827Dianne Hackborn%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 62120cdcee47d10986969e7e2a53a40a6ecabae3827Dianne Hackborn% % 6222286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn% % 6232286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn% % 6242286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn% G e t M a t r i x E l e m e n t % 6252286cdc0cab77e61b75e6fe9a45b91f6e57cd46dDianne Hackborn% % 626a413dc06b2193442a2d956571b829aeb5fb97862Dianne Hackborn% % 627a413dc06b2193442a2d956571b829aeb5fb97862Dianne Hackborn% % 628a413dc06b2193442a2d956571b829aeb5fb97862Dianne Hackborn%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 629a413dc06b2193442a2d956571b829aeb5fb97862Dianne Hackborn% 630a413dc06b2193442a2d956571b829aeb5fb97862Dianne Hackborn% GetMatrixElement() returns the specifed element in the matrix. 631a413dc06b2193442a2d956571b829aeb5fb97862Dianne Hackborn% 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% The format of the GetMatrixElement method is: 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project% MagickBooleanType GetMatrixElement(const MatrixInfo *matrix_info, 635d2932243e3313b59e7538641731aa98852bc5ac7Dianne Hackborn% const ssize_t x,const ssize_t y,void *value) 636be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn% 637e56c2c3f059b24c968a3f28f701b6b6cf5883fd9Dianne Hackborn% A description of each parameter follows: 638e56c2c3f059b24c968a3f28f701b6b6cf5883fd9Dianne Hackborn% 639e56c2c3f059b24c968a3f28f701b6b6cf5883fd9Dianne Hackborn% o matrix_info: the matrix columns. 640e56c2c3f059b24c968a3f28f701b6b6cf5883fd9Dianne Hackborn% 641e56c2c3f059b24c968a3f28f701b6b6cf5883fd9Dianne Hackborn% o x: the matrix x-offset. 642e56c2c3f059b24c968a3f28f701b6b6cf5883fd9Dianne Hackborn% 643f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn% o y: the matrix y-offset. 644f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn% 645f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn% o value: return the matrix element in this buffer. 646e56c2c3f059b24c968a3f28f701b6b6cf5883fd9Dianne Hackborn% 647be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn*/ 648e56c2c3f059b24c968a3f28f701b6b6cf5883fd9Dianne Hackborn 649e56c2c3f059b24c968a3f28f701b6b6cf5883fd9Dianne Hackbornstatic inline ssize_t EdgeX(const ssize_t x,const size_t columns) 650e56c2c3f059b24c968a3f28f701b6b6cf5883fd9Dianne Hackborn{ 6518472e6189cd4e0520c047bdb28457abc728b373fDianne Hackborn if (x < 0L) 652f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn return(0L); 653f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn if (x >= (ssize_t) columns) 654f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn return((ssize_t) (columns-1)); 655f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn return(x); 65653459a7020dbcd036e2d3418e35ebb96fadc29e3Dianne Hackborn} 657e56c2c3f059b24c968a3f28f701b6b6cf5883fd9Dianne Hackborn 658e56c2c3f059b24c968a3f28f701b6b6cf5883fd9Dianne Hackbornstatic inline ssize_t EdgeY(const ssize_t y,const size_t rows) 659be4c1d74a758f40de25e796a991ccfd1fe356857Dianne Hackborn{ 660e56c2c3f059b24c968a3f28f701b6b6cf5883fd9Dianne Hackborn if (y < 0L) 661cfc837f7fa43362b5049f648fe1bfdf5a010cc1cDianne Hackborn return(0L); 662f7097a5b697fedb6976774e55a51471405a23c0eDianne Hackborn if (y >= (ssize_t) rows) 66378a369c90f61981c9d0ddd5fcbc77202bfbe74f6Dianne Hackborn return((ssize_t) (rows-1)); 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return(y); 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic inline MagickOffsetType ReadMatrixElements( 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const MatrixInfo *magick_restrict matrix_info,const MagickOffsetType offset, 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const MagickSizeType length,unsigned char *magick_restrict buffer) 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project register MagickOffsetType 67278a369c90f61981c9d0ddd5fcbc77202bfbe74f6Dianne Hackborn i; 67378a369c90f61981c9d0ddd5fcbc77202bfbe74f6Dianne Hackborn 67478a369c90f61981c9d0ddd5fcbc77202bfbe74f6Dianne Hackborn ssize_t 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count; 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if !defined(MAGICKCORE_HAVE_PREAD) 678 LockSemaphoreInfo(matrix_info->semaphore); 679 if (lseek(matrix_info->file,offset,SEEK_SET) < 0) 680 { 681 UnlockSemaphoreInfo(matrix_info->semaphore); 682 return((MagickOffsetType) -1); 683 } 684#endif 685 count=0; 686 for (i=0; i < (MagickOffsetType) length; i+=count) 687 { 688#if !defined(MAGICKCORE_HAVE_PREAD) 689 count=read(matrix_info->file,buffer+i,(size_t) MagickMin(length-i, 690 (MagickSizeType) SSIZE_MAX)); 691#else 692 count=pread(matrix_info->file,buffer+i,(size_t) MagickMin(length-i, 693 (MagickSizeType) SSIZE_MAX),(off_t) (offset+i)); 694#endif 695 if (count <= 0) 696 { 697 count=0; 698 if (errno != EINTR) 699 break; 700 } 701 } 702#if !defined(MAGICKCORE_HAVE_PREAD) 703 UnlockSemaphoreInfo(matrix_info->semaphore); 704#endif 705 return(i); 706} 707 708MagickExport MagickBooleanType GetMatrixElement(const MatrixInfo *matrix_info, 709 const ssize_t x,const ssize_t y,void *value) 710{ 711 MagickOffsetType 712 count, 713 i; 714 715 assert(matrix_info != (const MatrixInfo *) NULL); 716 assert(matrix_info->signature == MagickCoreSignature); 717 i=(MagickOffsetType) EdgeY(y,matrix_info->rows)*matrix_info->columns+ 718 EdgeX(x,matrix_info->columns); 719 if (matrix_info->type != DiskCache) 720 { 721 (void) memcpy(value,(unsigned char *) matrix_info->elements+i* 722 matrix_info->stride,matrix_info->stride); 723 return(MagickTrue); 724 } 725 count=ReadMatrixElements(matrix_info,i*matrix_info->stride, 726 matrix_info->stride,(unsigned char *) value); 727 if (count != (MagickOffsetType) matrix_info->stride) 728 return(MagickFalse); 729 return(MagickTrue); 730} 731 732/* 733%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 734% % 735% % 736% % 737% G e t M a t r i x R o w s % 738% % 739% % 740% % 741%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 742% 743% GetMatrixRows() returns the number of rows in the matrix. 744% 745% The format of the GetMatrixRows method is: 746% 747% size_t GetMatrixRows(const MatrixInfo *matrix_info) 748% 749% A description of each parameter follows: 750% 751% o matrix_info: the matrix. 752% 753*/ 754MagickExport size_t GetMatrixRows(const MatrixInfo *matrix_info) 755{ 756 assert(matrix_info != (const MatrixInfo *) NULL); 757 assert(matrix_info->signature == MagickCoreSignature); 758 return(matrix_info->rows); 759} 760 761/* 762%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 763% % 764% % 765% % 766+ L e a s t S q u a r e s A d d T e r m s % 767% % 768% % 769% % 770%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 771% 772% LeastSquaresAddTerms() adds one set of terms and associate results to the 773% given matrix and vectors for solving using least-squares function fitting. 774% 775% The format of the AcquireMagickMatrix method is: 776% 777% void LeastSquaresAddTerms(double **matrix,double **vectors, 778% const double *terms,const double *results,const size_t rank, 779% const size_t number_vectors); 780% 781% A description of each parameter follows: 782% 783% o matrix: the square matrix to add given terms/results to. 784% 785% o vectors: the result vectors to add terms/results to. 786% 787% o terms: the pre-calculated terms (without the unknown coefficent 788% weights) that forms the equation being added. 789% 790% o results: the result(s) that should be generated from the given terms 791% weighted by the yet-to-be-solved coefficents. 792% 793% o rank: the rank or size of the dimensions of the square matrix. 794% Also the length of vectors, and number of terms being added. 795% 796% o number_vectors: Number of result vectors, and number or results being 797% added. Also represents the number of separable systems of equations 798% that is being solved. 799% 800% Example of use... 801% 802% 2 dimensional Affine Equations (which are separable) 803% c0*x + c2*y + c4*1 => u 804% c1*x + c3*y + c5*1 => v 805% 806% double **matrix = AcquireMagickMatrix(3UL,3UL); 807% double **vectors = AcquireMagickMatrix(2UL,3UL); 808% double terms[3], results[2]; 809% ... 810% for each given x,y -> u,v 811% terms[0] = x; 812% terms[1] = y; 813% terms[2] = 1; 814% results[0] = u; 815% results[1] = v; 816% LeastSquaresAddTerms(matrix,vectors,terms,results,3UL,2UL); 817% ... 818% if ( GaussJordanElimination(matrix,vectors,3UL,2UL) ) { 819% c0 = vectors[0][0]; 820% c2 = vectors[0][1]; 821% c4 = vectors[0][2]; 822% c1 = vectors[1][0]; 823% c3 = vectors[1][1]; 824% c5 = vectors[1][2]; 825% } 826% else 827% printf("Matrix unsolvable\n); 828% RelinquishMagickMatrix(matrix,3UL); 829% RelinquishMagickMatrix(vectors,2UL); 830% 831*/ 832MagickPrivate void LeastSquaresAddTerms(double **matrix,double **vectors, 833 const double *terms,const double *results,const size_t rank, 834 const size_t number_vectors) 835{ 836 register ssize_t 837 i, 838 j; 839 840 for (j=0; j < (ssize_t) rank; j++) 841 { 842 for (i=0; i < (ssize_t) rank; i++) 843 matrix[i][j]+=terms[i]*terms[j]; 844 for (i=0; i < (ssize_t) number_vectors; i++) 845 vectors[i][j]+=results[i]*terms[j]; 846 } 847} 848 849/* 850%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 851% % 852% % 853% % 854% M a t r i x T o I m a g e % 855% % 856% % 857% % 858%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 859% 860% MatrixToImage() returns a matrix as an image. The matrix elements must be 861% of type double otherwise nonsense is returned. 862% 863% The format of the MatrixToImage method is: 864% 865% Image *MatrixToImage(const MatrixInfo *matrix_info, 866% ExceptionInfo *exception) 867% 868% A description of each parameter follows: 869% 870% o matrix_info: the matrix. 871% 872% o exception: return any errors or warnings in this structure. 873% 874*/ 875MagickExport Image *MatrixToImage(const MatrixInfo *matrix_info, 876 ExceptionInfo *exception) 877{ 878 CacheView 879 *image_view; 880 881 double 882 max_value, 883 min_value, 884 scale_factor, 885 value; 886 887 Image 888 *image; 889 890 MagickBooleanType 891 status; 892 893 ssize_t 894 y; 895 896 assert(matrix_info != (const MatrixInfo *) NULL); 897 assert(matrix_info->signature == MagickCoreSignature); 898 assert(exception != (ExceptionInfo *) NULL); 899 assert(exception->signature == MagickCoreSignature); 900 if (matrix_info->stride < sizeof(double)) 901 return((Image *) NULL); 902 /* 903 Determine range of matrix. 904 */ 905 (void) GetMatrixElement(matrix_info,0,0,&value); 906 min_value=value; 907 max_value=value; 908 for (y=0; y < (ssize_t) matrix_info->rows; y++) 909 { 910 register ssize_t 911 x; 912 913 for (x=0; x < (ssize_t) matrix_info->columns; x++) 914 { 915 if (GetMatrixElement(matrix_info,x,y,&value) == MagickFalse) 916 continue; 917 if (value < min_value) 918 min_value=value; 919 else 920 if (value > max_value) 921 max_value=value; 922 } 923 } 924 if ((min_value == 0.0) && (max_value == 0.0)) 925 scale_factor=0; 926 else 927 if (min_value == max_value) 928 { 929 scale_factor=(double) QuantumRange/min_value; 930 min_value=0; 931 } 932 else 933 scale_factor=(double) QuantumRange/(max_value-min_value); 934 /* 935 Convert matrix to image. 936 */ 937 image=AcquireImage((ImageInfo *) NULL,exception); 938 image->columns=matrix_info->columns; 939 image->rows=matrix_info->rows; 940 image->colorspace=GRAYColorspace; 941 status=MagickTrue; 942 image_view=AcquireAuthenticCacheView(image,exception); 943#if defined(MAGICKCORE_OPENMP_SUPPORT) 944 #pragma omp parallel for schedule(static,4) shared(status) \ 945 magick_threads(image,image,image->rows,1) 946#endif 947 for (y=0; y < (ssize_t) image->rows; y++) 948 { 949 double 950 value; 951 952 register Quantum 953 *q; 954 955 register ssize_t 956 x; 957 958 if (status == MagickFalse) 959 continue; 960 q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 961 if (q == (Quantum *) NULL) 962 { 963 status=MagickFalse; 964 continue; 965 } 966 for (x=0; x < (ssize_t) image->columns; x++) 967 { 968 if (GetMatrixElement(matrix_info,x,y,&value) == MagickFalse) 969 continue; 970 value=scale_factor*(value-min_value); 971 *q=ClampToQuantum(value); 972 q+=GetPixelChannels(image); 973 } 974 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 975 status=MagickFalse; 976 } 977 image_view=DestroyCacheView(image_view); 978 if (status == MagickFalse) 979 image=DestroyImage(image); 980 return(image); 981} 982 983/* 984%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 985% % 986% % 987% % 988% N u l l M a t r i x % 989% % 990% % 991% % 992%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 993% 994% NullMatrix() sets all elements of the matrix to zero. 995% 996% The format of the ResetMagickMemory method is: 997% 998% MagickBooleanType *NullMatrix(MatrixInfo *matrix_info) 999% 1000% A description of each parameter follows: 1001% 1002% o matrix_info: the matrix. 1003% 1004*/ 1005MagickExport MagickBooleanType NullMatrix(MatrixInfo *matrix_info) 1006{ 1007 register ssize_t 1008 x; 1009 1010 ssize_t 1011 count, 1012 y; 1013 1014 unsigned char 1015 value; 1016 1017 assert(matrix_info != (const MatrixInfo *) NULL); 1018 assert(matrix_info->signature == MagickCoreSignature); 1019 if (matrix_info->type != DiskCache) 1020 { 1021 (void) ResetMagickMemory(matrix_info->elements,0,(size_t) 1022 matrix_info->length); 1023 return(MagickTrue); 1024 } 1025 value=0; 1026 (void) lseek(matrix_info->file,0,SEEK_SET); 1027 for (y=0; y < (ssize_t) matrix_info->rows; y++) 1028 { 1029 for (x=0; x < (ssize_t) matrix_info->length; x++) 1030 { 1031 count=write(matrix_info->file,&value,sizeof(value)); 1032 if (count != (ssize_t) sizeof(value)) 1033 break; 1034 } 1035 if (x < (ssize_t) matrix_info->length) 1036 break; 1037 } 1038 return(y < (ssize_t) matrix_info->rows ? MagickFalse : MagickTrue); 1039} 1040 1041/* 1042%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1043% % 1044% % 1045% % 1046% R e l i n q u i s h M a g i c k M a t r i x % 1047% % 1048% % 1049% % 1050%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1051% 1052% RelinquishMagickMatrix() frees the previously acquired matrix (array of 1053% pointers to arrays of doubles). 1054% 1055% The format of the RelinquishMagickMatrix method is: 1056% 1057% double **RelinquishMagickMatrix(double **matrix, 1058% const size_t number_rows) 1059% 1060% A description of each parameter follows: 1061% 1062% o matrix: the matrix to relinquish 1063% 1064% o number_rows: the first dimension of the acquired matrix (number of 1065% pointers) 1066% 1067*/ 1068MagickExport double **RelinquishMagickMatrix(double **matrix, 1069 const size_t number_rows) 1070{ 1071 register ssize_t 1072 i; 1073 1074 if (matrix == (double **) NULL ) 1075 return(matrix); 1076 for (i=0; i < (ssize_t) number_rows; i++) 1077 matrix[i]=(double *) RelinquishMagickMemory(matrix[i]); 1078 matrix=(double **) RelinquishMagickMemory(matrix); 1079 return(matrix); 1080} 1081 1082/* 1083%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1084% % 1085% % 1086% % 1087% S e t M a t r i x E l e m e n t % 1088% % 1089% % 1090% % 1091%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1092% 1093% SetMatrixElement() sets the specifed element in the matrix. 1094% 1095% The format of the SetMatrixElement method is: 1096% 1097% MagickBooleanType SetMatrixElement(const MatrixInfo *matrix_info, 1098% const ssize_t x,const ssize_t y,void *value) 1099% 1100% A description of each parameter follows: 1101% 1102% o matrix_info: the matrix columns. 1103% 1104% o x: the matrix x-offset. 1105% 1106% o y: the matrix y-offset. 1107% 1108% o value: set the matrix element to this value. 1109% 1110*/ 1111 1112MagickExport MagickBooleanType SetMatrixElement(const MatrixInfo *matrix_info, 1113 const ssize_t x,const ssize_t y,const void *value) 1114{ 1115 MagickOffsetType 1116 count, 1117 i; 1118 1119 assert(matrix_info != (const MatrixInfo *) NULL); 1120 assert(matrix_info->signature == MagickCoreSignature); 1121 i=(MagickOffsetType) y*matrix_info->columns+x; 1122 if ((i < 0) || 1123 ((MagickSizeType) (i*matrix_info->stride) >= matrix_info->length)) 1124 return(MagickFalse); 1125 if (matrix_info->type != DiskCache) 1126 { 1127 (void) memcpy((unsigned char *) matrix_info->elements+i* 1128 matrix_info->stride,value,matrix_info->stride); 1129 return(MagickTrue); 1130 } 1131 count=WriteMatrixElements(matrix_info,i*matrix_info->stride, 1132 matrix_info->stride,(unsigned char *) value); 1133 if (count != (MagickOffsetType) matrix_info->stride) 1134 return(MagickFalse); 1135 return(MagickTrue); 1136} 1137