cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1 | /* |
| 2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| 3 | % % |
| 4 | % % |
| 5 | % M M AAA TTTTT L AAA BBBB % |
| 6 | % MM MM A A T L A A B B % |
| 7 | % M M M AAAAA T L AAAAA BBBB % |
| 8 | % M M A A T L A A B B % |
| 9 | % M M A A T LLLLL A A BBBB % |
| 10 | % % |
| 11 | % % |
| 12 | % Read MATLAB Image Format % |
| 13 | % % |
| 14 | % Software Design % |
| 15 | % Jaroslav Fojtik % |
| 16 | % 2001-2008 % |
| 17 | % % |
| 18 | % % |
| 19 | % Permission is hereby granted, free of charge, to any person obtaining a % |
| 20 | % copy of this software and associated documentation files ("ImageMagick"), % |
| 21 | % to deal in ImageMagick without restriction, including without limitation % |
| 22 | % the rights to use, copy, modify, merge, publish, distribute, sublicense, % |
| 23 | % and/or sell copies of ImageMagick, and to permit persons to whom the % |
| 24 | % ImageMagick is furnished to do so, subject to the following conditions: % |
| 25 | % % |
| 26 | % The above copyright notice and this permission notice shall be included in % |
| 27 | % all copies or substantial portions of ImageMagick. % |
| 28 | % % |
| 29 | % The software is provided "as is", without warranty of any kind, express or % |
| 30 | % implied, including but not limited to the warranties of merchantability, % |
| 31 | % fitness for a particular purpose and noninfringement. In no event shall % |
| 32 | % ImageMagick Studio be liable for any claim, damages or other liability, % |
| 33 | % whether in an action of contract, tort or otherwise, arising from, out of % |
| 34 | % or in connection with ImageMagick or the use or other dealings in % |
| 35 | % ImageMagick. % |
| 36 | % % |
| 37 | % Except as contained in this notice, the name of the ImageMagick Studio % |
| 38 | % shall not be used in advertising or otherwise to promote the sale, use or % |
| 39 | % other dealings in ImageMagick without prior written authorization from the % |
| 40 | % ImageMagick Studio. % |
| 41 | % % |
| 42 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| 43 | % |
| 44 | % |
| 45 | */ |
| 46 | |
| 47 | /* |
| 48 | Include declarations. |
| 49 | */ |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 50 | #include "MagickCore/studio.h" |
| 51 | #include "MagickCore/attribute.h" |
| 52 | #include "MagickCore/blob.h" |
| 53 | #include "MagickCore/blob-private.h" |
| 54 | #include "MagickCore/cache.h" |
| 55 | #include "MagickCore/color-private.h" |
| 56 | #include "MagickCore/colormap.h" |
cristy | 510d06a | 2011-07-06 23:43:54 +0000 | [diff] [blame] | 57 | #include "MagickCore/colorspace-private.h" |
cristy | c53413d | 2011-11-17 13:04:26 +0000 | [diff] [blame] | 58 | #include "MagickCore/distort.h" |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 59 | #include "MagickCore/exception.h" |
| 60 | #include "MagickCore/exception-private.h" |
| 61 | #include "MagickCore/image.h" |
| 62 | #include "MagickCore/image-private.h" |
| 63 | #include "MagickCore/list.h" |
| 64 | #include "MagickCore/magick.h" |
| 65 | #include "MagickCore/memory_.h" |
| 66 | #include "MagickCore/monitor.h" |
| 67 | #include "MagickCore/monitor-private.h" |
| 68 | #include "MagickCore/pixel-accessor.h" |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 69 | #include "MagickCore/quantum.h" |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 70 | #include "MagickCore/quantum-private.h" |
| 71 | #include "MagickCore/option.h" |
| 72 | #include "MagickCore/pixel.h" |
| 73 | #include "MagickCore/resource_.h" |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 74 | #include "MagickCore/static.h" |
| 75 | #include "MagickCore/string_.h" |
| 76 | #include "MagickCore/module.h" |
| 77 | #include "MagickCore/transform.h" |
cristy | 18c6c27 | 2011-09-23 14:40:37 +0000 | [diff] [blame] | 78 | #include "MagickCore/utility-private.h" |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 79 | #if defined(MAGICKCORE_ZLIB_DELEGATE) |
| 80 | #include "zlib.h" |
| 81 | #endif |
| 82 | |
| 83 | /* |
| 84 | Forward declaration. |
| 85 | */ |
| 86 | static MagickBooleanType |
cristy | 1e178e7 | 2011-08-28 19:44:34 +0000 | [diff] [blame] | 87 | WriteMATImage(const ImageInfo *,Image *,ExceptionInfo *); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 88 | |
| 89 | |
| 90 | /* Auto coloring method, sorry this creates some artefact inside data |
| 91 | MinReal+j*MaxComplex = red MaxReal+j*MaxComplex = black |
| 92 | MinReal+j*0 = white MaxReal+j*0 = black |
| 93 | MinReal+j*MinComplex = blue MaxReal+j*MinComplex = black |
| 94 | */ |
| 95 | |
| 96 | typedef struct |
| 97 | { |
| 98 | char identific[124]; |
| 99 | unsigned short Version; |
| 100 | char EndianIndicator[2]; |
cristy | f6fe0a1 | 2010-05-30 00:44:47 +0000 | [diff] [blame] | 101 | unsigned long DataType; |
Cristy | 67ea75f | 2017-07-03 19:36:27 -0400 | [diff] [blame] | 102 | unsigned int ObjectSize; |
cristy | f6fe0a1 | 2010-05-30 00:44:47 +0000 | [diff] [blame] | 103 | unsigned long unknown1; |
| 104 | unsigned long unknown2; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 105 | |
| 106 | unsigned short unknown5; |
| 107 | unsigned char StructureFlag; |
| 108 | unsigned char StructureClass; |
cristy | f6fe0a1 | 2010-05-30 00:44:47 +0000 | [diff] [blame] | 109 | unsigned long unknown3; |
| 110 | unsigned long unknown4; |
| 111 | unsigned long DimFlag; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 112 | |
cristy | f6fe0a1 | 2010-05-30 00:44:47 +0000 | [diff] [blame] | 113 | unsigned long SizeX; |
| 114 | unsigned long SizeY; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 115 | unsigned short Flag1; |
| 116 | unsigned short NameFlag; |
| 117 | } |
| 118 | MATHeader; |
| 119 | |
Cristy | 66d1345 | 2015-09-20 09:56:47 -0400 | [diff] [blame] | 120 | static const char *MonthsTab[12]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; |
| 121 | static const char *DayOfWTab[7]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 122 | static const char *OsDesc= |
Cristy | bf69730 | 2016-04-08 19:52:52 -0400 | [diff] [blame] | 123 | #if defined(MAGICKCORE_WINDOWS_SUPPORT) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 124 | "PCWIN"; |
| 125 | #else |
| 126 | #ifdef __APPLE__ |
| 127 | "MAC"; |
| 128 | #else |
| 129 | "LNX86"; |
| 130 | #endif |
| 131 | #endif |
| 132 | |
| 133 | typedef enum |
| 134 | { |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 135 | miINT8 = 1, /* 8 bit signed */ |
| 136 | miUINT8, /* 8 bit unsigned */ |
| 137 | miINT16, /* 16 bit signed */ |
| 138 | miUINT16, /* 16 bit unsigned */ |
| 139 | miINT32, /* 32 bit signed */ |
| 140 | miUINT32, /* 32 bit unsigned */ |
| 141 | miSINGLE, /* IEEE 754 single precision float */ |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 142 | miRESERVE1, |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 143 | miDOUBLE, /* IEEE 754 double precision float */ |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 144 | miRESERVE2, |
| 145 | miRESERVE3, |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 146 | miINT64, /* 64 bit signed */ |
| 147 | miUINT64, /* 64 bit unsigned */ |
| 148 | miMATRIX, /* MATLAB array */ |
| 149 | miCOMPRESSED, /* Compressed Data */ |
| 150 | miUTF8, /* Unicode UTF-8 Encoded Character Data */ |
| 151 | miUTF16, /* Unicode UTF-16 Encoded Character Data */ |
| 152 | miUTF32 /* Unicode UTF-32 Encoded Character Data */ |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 153 | } mat5_data_type; |
| 154 | |
| 155 | typedef enum |
| 156 | { |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 157 | mxCELL_CLASS=1, /* cell array */ |
| 158 | mxSTRUCT_CLASS, /* structure */ |
| 159 | mxOBJECT_CLASS, /* object */ |
| 160 | mxCHAR_CLASS, /* character array */ |
| 161 | mxSPARSE_CLASS, /* sparse array */ |
| 162 | mxDOUBLE_CLASS, /* double precision array */ |
| 163 | mxSINGLE_CLASS, /* single precision floating point */ |
| 164 | mxINT8_CLASS, /* 8 bit signed integer */ |
| 165 | mxUINT8_CLASS, /* 8 bit unsigned integer */ |
| 166 | mxINT16_CLASS, /* 16 bit signed integer */ |
| 167 | mxUINT16_CLASS, /* 16 bit unsigned integer */ |
| 168 | mxINT32_CLASS, /* 32 bit signed integer */ |
| 169 | mxUINT32_CLASS, /* 32 bit unsigned integer */ |
| 170 | mxINT64_CLASS, /* 64 bit signed integer */ |
| 171 | mxUINT64_CLASS, /* 64 bit unsigned integer */ |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 172 | mxFUNCTION_CLASS /* Function handle */ |
| 173 | } arrayclasstype; |
| 174 | |
| 175 | #define FLAG_COMPLEX 0x8 |
| 176 | #define FLAG_GLOBAL 0x4 |
| 177 | #define FLAG_LOGICAL 0x2 |
| 178 | |
| 179 | static const QuantumType z2qtype[4] = {GrayQuantum, BlueQuantum, GreenQuantum, RedQuantum}; |
| 180 | |
| 181 | |
cristy | c82a27b | 2011-10-21 01:07:16 +0000 | [diff] [blame] | 182 | static void InsertComplexDoubleRow(Image *image,double *p,int y,double MinVal, |
| 183 | double MaxVal,ExceptionInfo *exception) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 184 | { |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 185 | |
| 186 | double f; |
| 187 | int x; |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 188 | register Quantum *q; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 189 | |
| 190 | if (MinVal == 0) |
| 191 | MinVal = -1; |
| 192 | if (MaxVal == 0) |
| 193 | MaxVal = 1; |
| 194 | |
cristy | 524222d | 2011-04-25 00:37:06 +0000 | [diff] [blame] | 195 | q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); |
cristy | acd2ed2 | 2011-08-30 01:44:23 +0000 | [diff] [blame] | 196 | if (q == (Quantum *) NULL) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 197 | return; |
cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 198 | for (x = 0; x < (ssize_t) image->columns; x++) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 199 | { |
| 200 | if (*p > 0) |
| 201 | { |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 202 | f = (*p / MaxVal) * (QuantumRange-GetPixelRed(image,q)); |
| 203 | if (f + GetPixelRed(image,q) > QuantumRange) |
| 204 | SetPixelRed(image,QuantumRange,q); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 205 | else |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 206 | SetPixelRed(image,GetPixelRed(image,q)+(int) f,q); |
| 207 | if ((int) f / 2.0 > GetPixelGreen(image,q)) |
cristy | 524222d | 2011-04-25 00:37:06 +0000 | [diff] [blame] | 208 | { |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 209 | SetPixelGreen(image,0,q); |
| 210 | SetPixelBlue(image,0,q); |
cristy | 524222d | 2011-04-25 00:37:06 +0000 | [diff] [blame] | 211 | } |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 212 | else |
cristy | 524222d | 2011-04-25 00:37:06 +0000 | [diff] [blame] | 213 | { |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 214 | SetPixelBlue(image,GetPixelBlue(image,q)-(int) (f/2.0),q); |
| 215 | SetPixelGreen(image,GetPixelBlue(image,q),q); |
cristy | 524222d | 2011-04-25 00:37:06 +0000 | [diff] [blame] | 216 | } |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 217 | } |
| 218 | if (*p < 0) |
| 219 | { |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 220 | f = (*p / MaxVal) * (QuantumRange-GetPixelBlue(image,q)); |
| 221 | if (f+GetPixelBlue(image,q) > QuantumRange) |
| 222 | SetPixelBlue(image,QuantumRange,q); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 223 | else |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 224 | SetPixelBlue(image,GetPixelBlue(image,q)+(int) f,q); |
| 225 | if ((int) f / 2.0 > GetPixelGreen(image,q)) |
cristy | 524222d | 2011-04-25 00:37:06 +0000 | [diff] [blame] | 226 | { |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 227 | SetPixelRed(image,0,q); |
| 228 | SetPixelGreen(image,0,q); |
cristy | 524222d | 2011-04-25 00:37:06 +0000 | [diff] [blame] | 229 | } |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 230 | else |
cristy | 524222d | 2011-04-25 00:37:06 +0000 | [diff] [blame] | 231 | { |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 232 | SetPixelRed(image,GetPixelRed(image,q)-(int) (f/2.0),q); |
| 233 | SetPixelGreen(image,GetPixelRed(image,q),q); |
cristy | 524222d | 2011-04-25 00:37:06 +0000 | [diff] [blame] | 234 | } |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 235 | } |
| 236 | p++; |
cristy | ed23157 | 2011-07-14 02:18:59 +0000 | [diff] [blame] | 237 | q+=GetPixelChannels(image); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 238 | } |
| 239 | if (!SyncAuthenticPixels(image,exception)) |
| 240 | return; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 241 | return; |
| 242 | } |
| 243 | |
| 244 | |
cristy | c82a27b | 2011-10-21 01:07:16 +0000 | [diff] [blame] | 245 | static void InsertComplexFloatRow(Image *image,float *p,int y,double MinVal, |
| 246 | double MaxVal,ExceptionInfo *exception) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 247 | { |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 248 | double f; |
| 249 | int x; |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 250 | register Quantum *q; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 251 | |
| 252 | if (MinVal == 0) |
| 253 | MinVal = -1; |
| 254 | if (MaxVal == 0) |
| 255 | MaxVal = 1; |
| 256 | |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 257 | q = QueueAuthenticPixels(image, 0, y, image->columns, 1,exception); |
cristy | acd2ed2 | 2011-08-30 01:44:23 +0000 | [diff] [blame] | 258 | if (q == (Quantum *) NULL) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 259 | return; |
cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 260 | for (x = 0; x < (ssize_t) image->columns; x++) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 261 | { |
| 262 | if (*p > 0) |
| 263 | { |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 264 | f = (*p / MaxVal) * (QuantumRange-GetPixelRed(image,q)); |
| 265 | if (f+GetPixelRed(image,q) > QuantumRange) |
| 266 | SetPixelRed(image,QuantumRange,q); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 267 | else |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 268 | SetPixelRed(image,GetPixelRed(image,q)+(int) f,q); |
| 269 | if ((int) f / 2.0 > GetPixelGreen(image,q)) |
cristy | 524222d | 2011-04-25 00:37:06 +0000 | [diff] [blame] | 270 | { |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 271 | SetPixelGreen(image,0,q); |
| 272 | SetPixelBlue(image,0,q); |
cristy | 524222d | 2011-04-25 00:37:06 +0000 | [diff] [blame] | 273 | } |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 274 | else |
cristy | 524222d | 2011-04-25 00:37:06 +0000 | [diff] [blame] | 275 | { |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 276 | SetPixelBlue(image,GetPixelBlue(image,q)-(int) (f/2.0),q); |
| 277 | SetPixelGreen(image,GetPixelBlue(image,q),q); |
cristy | 524222d | 2011-04-25 00:37:06 +0000 | [diff] [blame] | 278 | } |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 279 | } |
| 280 | if (*p < 0) |
| 281 | { |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 282 | f = (*p / MaxVal) * (QuantumRange - GetPixelBlue(image,q)); |
| 283 | if (f + GetPixelBlue(image,q) > QuantumRange) |
| 284 | SetPixelBlue(image,QuantumRange,q); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 285 | else |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 286 | SetPixelBlue(image,GetPixelBlue(image,q)+ |
| 287 | (int) f,q); |
| 288 | if ((int) f / 2.0 > GetPixelGreen(image,q)) |
cristy | 524222d | 2011-04-25 00:37:06 +0000 | [diff] [blame] | 289 | { |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 290 | SetPixelGreen(image,0,q); |
| 291 | SetPixelRed(image,0,q); |
cristy | 524222d | 2011-04-25 00:37:06 +0000 | [diff] [blame] | 292 | } |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 293 | else |
cristy | 524222d | 2011-04-25 00:37:06 +0000 | [diff] [blame] | 294 | { |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 295 | SetPixelRed(image,GetPixelRed(image,q)-(int) (f/2.0),q); |
| 296 | SetPixelGreen(image,GetPixelRed(image,q),q); |
cristy | 524222d | 2011-04-25 00:37:06 +0000 | [diff] [blame] | 297 | } |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 298 | } |
| 299 | p++; |
| 300 | q++; |
| 301 | } |
| 302 | if (!SyncAuthenticPixels(image,exception)) |
| 303 | return; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 304 | return; |
| 305 | } |
| 306 | |
| 307 | |
| 308 | /************** READERS ******************/ |
| 309 | |
| 310 | /* This function reads one block of floats*/ |
| 311 | static void ReadBlobFloatsLSB(Image * image, size_t len, float *data) |
| 312 | { |
| 313 | while (len >= 4) |
| 314 | { |
| 315 | *data++ = ReadBlobFloat(image); |
| 316 | len -= sizeof(float); |
| 317 | } |
| 318 | if (len > 0) |
| 319 | (void) SeekBlob(image, len, SEEK_CUR); |
| 320 | } |
| 321 | |
| 322 | static void ReadBlobFloatsMSB(Image * image, size_t len, float *data) |
| 323 | { |
| 324 | while (len >= 4) |
| 325 | { |
| 326 | *data++ = ReadBlobFloat(image); |
| 327 | len -= sizeof(float); |
| 328 | } |
| 329 | if (len > 0) |
| 330 | (void) SeekBlob(image, len, SEEK_CUR); |
| 331 | } |
| 332 | |
| 333 | /* This function reads one block of doubles*/ |
| 334 | static void ReadBlobDoublesLSB(Image * image, size_t len, double *data) |
| 335 | { |
| 336 | while (len >= 8) |
| 337 | { |
| 338 | *data++ = ReadBlobDouble(image); |
| 339 | len -= sizeof(double); |
| 340 | } |
| 341 | if (len > 0) |
| 342 | (void) SeekBlob(image, len, SEEK_CUR); |
| 343 | } |
| 344 | |
| 345 | static void ReadBlobDoublesMSB(Image * image, size_t len, double *data) |
| 346 | { |
| 347 | while (len >= 8) |
| 348 | { |
| 349 | *data++ = ReadBlobDouble(image); |
| 350 | len -= sizeof(double); |
| 351 | } |
| 352 | if (len > 0) |
| 353 | (void) SeekBlob(image, len, SEEK_CUR); |
| 354 | } |
| 355 | |
| 356 | /* Calculate minimum and maximum from a given block of data */ |
cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 357 | static void CalcMinMax(Image *image, int endian_indicator, int SizeX, int SizeY, size_t CellType, unsigned ldblk, void *BImgBuff, double *Min, double *Max) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 358 | { |
| 359 | MagickOffsetType filepos; |
| 360 | int i, x; |
| 361 | void (*ReadBlobDoublesXXX)(Image * image, size_t len, double *data); |
| 362 | void (*ReadBlobFloatsXXX)(Image * image, size_t len, float *data); |
| 363 | double *dblrow; |
| 364 | float *fltrow; |
| 365 | |
| 366 | if (endian_indicator == LSBEndian) |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 367 | { |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 368 | ReadBlobDoublesXXX = ReadBlobDoublesLSB; |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 369 | ReadBlobFloatsXXX = ReadBlobFloatsLSB; |
| 370 | } |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 371 | else /* MI */ |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 372 | { |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 373 | ReadBlobDoublesXXX = ReadBlobDoublesMSB; |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 374 | ReadBlobFloatsXXX = ReadBlobFloatsMSB; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 375 | } |
| 376 | |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 377 | filepos = TellBlob(image); /* Please note that file seeking occurs only in the case of doubles */ |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 378 | for (i = 0; i < SizeY; i++) |
| 379 | { |
| 380 | if (CellType==miDOUBLE) |
| 381 | { |
| 382 | ReadBlobDoublesXXX(image, ldblk, (double *)BImgBuff); |
| 383 | dblrow = (double *)BImgBuff; |
| 384 | if (i == 0) |
| 385 | { |
| 386 | *Min = *Max = *dblrow; |
| 387 | } |
| 388 | for (x = 0; x < SizeX; x++) |
| 389 | { |
| 390 | if (*Min > *dblrow) |
| 391 | *Min = *dblrow; |
| 392 | if (*Max < *dblrow) |
| 393 | *Max = *dblrow; |
| 394 | dblrow++; |
| 395 | } |
| 396 | } |
| 397 | if (CellType==miSINGLE) |
| 398 | { |
| 399 | ReadBlobFloatsXXX(image, ldblk, (float *)BImgBuff); |
| 400 | fltrow = (float *)BImgBuff; |
| 401 | if (i == 0) |
| 402 | { |
| 403 | *Min = *Max = *fltrow; |
| 404 | } |
cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 405 | for (x = 0; x < (ssize_t) SizeX; x++) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 406 | { |
| 407 | if (*Min > *fltrow) |
| 408 | *Min = *fltrow; |
| 409 | if (*Max < *fltrow) |
| 410 | *Max = *fltrow; |
| 411 | fltrow++; |
| 412 | } |
| 413 | } |
| 414 | } |
| 415 | (void) SeekBlob(image, filepos, SEEK_SET); |
| 416 | } |
| 417 | |
| 418 | |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 419 | static void FixSignedValues(const Image *image,Quantum *q, int y) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 420 | { |
| 421 | while(y-->0) |
| 422 | { |
| 423 | /* Please note that negative values will overflow |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 424 | Q=8; QuantumRange=255: <0;127> + 127+1 = <128; 255> |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 425 | <-1;-128> + 127+1 = <0; 127> */ |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 426 | SetPixelRed(image,GetPixelRed(image,q)+QuantumRange/2+1,q); |
| 427 | SetPixelGreen(image,GetPixelGreen(image,q)+QuantumRange/2+1,q); |
| 428 | SetPixelBlue(image,GetPixelBlue(image,q)+QuantumRange/2+1,q); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 429 | q++; |
| 430 | } |
| 431 | } |
| 432 | |
| 433 | |
| 434 | /** Fix whole row of logical/binary data. It means pack it. */ |
| 435 | static void FixLogical(unsigned char *Buff,int ldblk) |
| 436 | { |
| 437 | unsigned char mask=128; |
| 438 | unsigned char *BuffL = Buff; |
| 439 | unsigned char val = 0; |
| 440 | |
| 441 | while(ldblk-->0) |
| 442 | { |
| 443 | if(*Buff++ != 0) |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 444 | val |= mask; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 445 | |
| 446 | mask >>= 1; |
| 447 | if(mask==0) |
| 448 | { |
| 449 | *BuffL++ = val; |
| 450 | val = 0; |
| 451 | mask = 128; |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 452 | } |
| 453 | |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 454 | } |
| 455 | *BuffL = val; |
| 456 | } |
| 457 | |
| 458 | #if defined(MAGICKCORE_ZLIB_DELEGATE) |
| 459 | static voidpf AcquireZIPMemory(voidpf context,unsigned int items, |
| 460 | unsigned int size) |
| 461 | { |
| 462 | (void) context; |
| 463 | return((voidpf) AcquireQuantumMemory(items,size)); |
| 464 | } |
| 465 | |
| 466 | static void RelinquishZIPMemory(voidpf context,voidpf memory) |
| 467 | { |
| 468 | (void) context; |
| 469 | memory=RelinquishMagickMemory(memory); |
| 470 | } |
| 471 | #endif |
| 472 | |
cristy | 0906b14 | 2011-02-21 01:10:00 +0000 | [diff] [blame] | 473 | #if defined(MAGICKCORE_ZLIB_DELEGATE) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 474 | /** This procedure decompreses an image block for a new MATLAB format. */ |
Cristy | 7d2e159 | 2017-07-03 20:26:21 -0400 | [diff] [blame] | 475 | static Image *decompress_block(Image *orig, unsigned int *Size, ImageInfo *clone_info, ExceptionInfo *exception) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 476 | { |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 477 | |
| 478 | Image *image2; |
Cristy | 7d2e159 | 2017-07-03 20:26:21 -0400 | [diff] [blame] | 479 | void *cache_block, *decompress_block; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 480 | z_stream zip_info; |
| 481 | FILE *mat_file; |
| 482 | size_t magick_size; |
cristy | 95236b5 | 2009-12-30 21:56:45 +0000 | [diff] [blame] | 483 | size_t extent; |
dirk | 96c0d68 | 2014-05-03 14:03:02 +0000 | [diff] [blame] | 484 | int file; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 485 | |
| 486 | int status; |
Cristy | 892e4e5 | 2016-05-08 12:26:06 -0400 | [diff] [blame] | 487 | int zip_status; |
Cristy | 67ea75f | 2017-07-03 19:36:27 -0400 | [diff] [blame] | 488 | ssize_t TotalSize = 0; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 489 | |
| 490 | if(clone_info==NULL) return NULL; |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 491 | if(clone_info->file) /* Close file opened from previous transaction. */ |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 492 | { |
| 493 | fclose(clone_info->file); |
| 494 | clone_info->file = NULL; |
cristy | 18c6c27 | 2011-09-23 14:40:37 +0000 | [diff] [blame] | 495 | (void) remove_utf8(clone_info->filename); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 496 | } |
| 497 | |
Cristy | 7d2e159 | 2017-07-03 20:26:21 -0400 | [diff] [blame] | 498 | cache_block = AcquireQuantumMemory((size_t)(*Size < 16384) ? *Size: 16384,sizeof(unsigned char *)); |
| 499 | if(cache_block==NULL) return NULL; |
| 500 | decompress_block = AcquireQuantumMemory((size_t)(4096),sizeof(unsigned char *)); |
| 501 | if(decompress_block==NULL) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 502 | { |
Cristy | 7d2e159 | 2017-07-03 20:26:21 -0400 | [diff] [blame] | 503 | RelinquishMagickMemory(cache_block); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 504 | return NULL; |
| 505 | } |
| 506 | |
cristy | 4d0ca34 | 2014-05-01 00:42:09 +0000 | [diff] [blame] | 507 | mat_file=0; |
| 508 | file = AcquireUniqueFileResource(clone_info->filename); |
| 509 | if (file != -1) |
| 510 | mat_file = fdopen(file,"w"); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 511 | if(!mat_file) |
| 512 | { |
Cristy | 7d2e159 | 2017-07-03 20:26:21 -0400 | [diff] [blame] | 513 | RelinquishMagickMemory(cache_block); |
| 514 | RelinquishMagickMemory(decompress_block); |
Cristy | 0c3417c | 2016-05-09 07:12:51 -0400 | [diff] [blame] | 515 | (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Cannot create file stream for decompressed image"); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 516 | return NULL; |
| 517 | } |
| 518 | |
| 519 | zip_info.zalloc=AcquireZIPMemory; |
| 520 | zip_info.zfree=RelinquishZIPMemory; |
| 521 | zip_info.opaque = (voidpf) NULL; |
Cristy | 892e4e5 | 2016-05-08 12:26:06 -0400 | [diff] [blame] | 522 | zip_status = inflateInit(&zip_info); |
| 523 | if (zip_status != Z_OK) |
| 524 | { |
Cristy | 7d2e159 | 2017-07-03 20:26:21 -0400 | [diff] [blame] | 525 | RelinquishMagickMemory(cache_block); |
| 526 | RelinquishMagickMemory(decompress_block); |
Cristy | 892e4e5 | 2016-05-08 12:26:06 -0400 | [diff] [blame] | 527 | (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError, |
| 528 | "UnableToUncompressImage","`%s'",clone_info->filename); |
Cristy | fcd84b4 | 2016-05-11 19:28:33 -0400 | [diff] [blame] | 529 | (void) fclose(mat_file); |
| 530 | RelinquishUniqueFileResource(clone_info->filename); |
Cristy | 892e4e5 | 2016-05-08 12:26:06 -0400 | [diff] [blame] | 531 | return NULL; |
| 532 | } |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 533 | /* zip_info.next_out = 8*4;*/ |
| 534 | |
| 535 | zip_info.avail_in = 0; |
| 536 | zip_info.total_out = 0; |
Cristy | 67ea75f | 2017-07-03 19:36:27 -0400 | [diff] [blame] | 537 | while(*Size>0 && !EOFBlob(orig)) |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 538 | { |
Cristy | 7d2e159 | 2017-07-03 20:26:21 -0400 | [diff] [blame] | 539 | magick_size = ReadBlob(orig, (*Size < 16384) ? *Size : 16384, (unsigned char *) cache_block); |
| 540 | zip_info.next_in = (Bytef *) cache_block; |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 541 | zip_info.avail_in = (uInt) magick_size; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 542 | |
| 543 | while(zip_info.avail_in>0) |
| 544 | { |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 545 | zip_info.avail_out = 4096; |
Cristy | 7d2e159 | 2017-07-03 20:26:21 -0400 | [diff] [blame] | 546 | zip_info.next_out = (Bytef *) decompress_block; |
Cristy | 892e4e5 | 2016-05-08 12:26:06 -0400 | [diff] [blame] | 547 | zip_status = inflate(&zip_info,Z_NO_FLUSH); |
| 548 | if ((zip_status != Z_OK) && (zip_status != Z_STREAM_END)) |
| 549 | break; |
Cristy | 7d2e159 | 2017-07-03 20:26:21 -0400 | [diff] [blame] | 550 | extent=fwrite(decompress_block, 4096-zip_info.avail_out, 1, mat_file); |
cristy | da16f16 | 2011-02-19 23:52:17 +0000 | [diff] [blame] | 551 | (void) extent; |
Cristy | 67ea75f | 2017-07-03 19:36:27 -0400 | [diff] [blame] | 552 | TotalSize += 4096-zip_info.avail_out; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 553 | |
Cristy | 892e4e5 | 2016-05-08 12:26:06 -0400 | [diff] [blame] | 554 | if(zip_status == Z_STREAM_END) goto DblBreak; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 555 | } |
Cristy | 892e4e5 | 2016-05-08 12:26:06 -0400 | [diff] [blame] | 556 | if ((zip_status != Z_OK) && (zip_status != Z_STREAM_END)) |
| 557 | break; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 558 | |
Cristy | 67ea75f | 2017-07-03 19:36:27 -0400 | [diff] [blame] | 559 | *Size -= magick_size; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 560 | } |
| 561 | DblBreak: |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 562 | |
cristy | 166daeb | 2015-01-15 12:18:07 +0000 | [diff] [blame] | 563 | inflateEnd(&zip_info); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 564 | (void)fclose(mat_file); |
Cristy | 7d2e159 | 2017-07-03 20:26:21 -0400 | [diff] [blame] | 565 | RelinquishMagickMemory(cache_block); |
| 566 | RelinquishMagickMemory(decompress_block); |
Cristy | 67ea75f | 2017-07-03 19:36:27 -0400 | [diff] [blame] | 567 | *Size = TotalSize; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 568 | |
| 569 | if((clone_info->file=fopen(clone_info->filename,"rb"))==NULL) goto UnlinkFile; |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 570 | if( (image2 = AcquireImage(clone_info,exception))==NULL ) goto EraseFile; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 571 | status = OpenBlob(clone_info,image2,ReadBinaryBlobMode,exception); |
| 572 | if (status == MagickFalse) |
| 573 | { |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 574 | DeleteImageFromList(&image2); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 575 | EraseFile: |
| 576 | fclose(clone_info->file); |
| 577 | clone_info->file = NULL; |
| 578 | UnlinkFile: |
Cristy | fcd84b4 | 2016-05-11 19:28:33 -0400 | [diff] [blame] | 579 | RelinquishUniqueFileResource(clone_info->filename); |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 580 | return NULL; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 581 | } |
| 582 | |
| 583 | return image2; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 584 | } |
cristy | 0906b14 | 2011-02-21 01:10:00 +0000 | [diff] [blame] | 585 | #endif |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 586 | |
| 587 | static Image *ReadMATImageV4(const ImageInfo *image_info,Image *image, |
| 588 | ExceptionInfo *exception) |
| 589 | { |
| 590 | typedef struct { |
| 591 | unsigned char Type[4]; |
| 592 | unsigned int nRows; |
| 593 | unsigned int nCols; |
| 594 | unsigned int imagf; |
| 595 | unsigned int nameLen; |
| 596 | } MAT4_HDR; |
| 597 | |
| 598 | long |
| 599 | ldblk; |
| 600 | |
| 601 | EndianType |
| 602 | endian; |
| 603 | |
| 604 | Image |
| 605 | *rotate_image; |
| 606 | |
| 607 | MagickBooleanType |
| 608 | status; |
| 609 | |
| 610 | MAT4_HDR |
| 611 | HDR; |
| 612 | |
| 613 | QuantumInfo |
| 614 | *quantum_info; |
| 615 | |
| 616 | QuantumFormatType |
| 617 | format_type; |
| 618 | |
| 619 | register ssize_t |
| 620 | i; |
| 621 | |
| 622 | ssize_t |
Cristy | 78a72f5 | 2016-05-29 14:57:07 -0400 | [diff] [blame] | 623 | count, |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 624 | y; |
| 625 | |
| 626 | unsigned char |
| 627 | *pixels; |
| 628 | |
| 629 | unsigned int |
| 630 | depth; |
| 631 | |
Cristy | a1936a7 | 2016-11-13 19:39:22 -0500 | [diff] [blame] | 632 | |
Cristy | 79e5dbc | 2017-04-27 07:45:09 -0400 | [diff] [blame] | 633 | quantum_info=(QuantumInfo *) NULL; |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 634 | (void) SeekBlob(image,0,SEEK_SET); |
Cristy | a1936a7 | 2016-11-13 19:39:22 -0500 | [diff] [blame] | 635 | while (EOFBlob(image) != MagickFalse) |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 636 | { |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 637 | /* |
Cristy | a1936a7 | 2016-11-13 19:39:22 -0500 | [diff] [blame] | 638 | Object parser loop. |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 639 | */ |
Cristy | a1936a7 | 2016-11-13 19:39:22 -0500 | [diff] [blame] | 640 | ldblk=ReadBlobLSBLong(image); |
| 641 | if ((ldblk > 9999) || (ldblk < 0)) |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 642 | break; |
Cristy | a1936a7 | 2016-11-13 19:39:22 -0500 | [diff] [blame] | 643 | HDR.Type[3]=ldblk % 10; ldblk /= 10; /* T digit */ |
| 644 | HDR.Type[2]=ldblk % 10; ldblk /= 10; /* P digit */ |
| 645 | HDR.Type[1]=ldblk % 10; ldblk /= 10; /* O digit */ |
| 646 | HDR.Type[0]=ldblk; /* M digit */ |
| 647 | if (HDR.Type[3] != 0) |
| 648 | break; /* Data format */ |
| 649 | if (HDR.Type[2] != 0) |
| 650 | break; /* Always 0 */ |
| 651 | if (HDR.Type[0] == 0) |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 652 | { |
Cristy | a1936a7 | 2016-11-13 19:39:22 -0500 | [diff] [blame] | 653 | HDR.nRows=ReadBlobLSBLong(image); |
| 654 | HDR.nCols=ReadBlobLSBLong(image); |
| 655 | HDR.imagf=ReadBlobLSBLong(image); |
| 656 | HDR.nameLen=ReadBlobLSBLong(image); |
| 657 | endian=LSBEndian; |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 658 | } |
Cristy | a1936a7 | 2016-11-13 19:39:22 -0500 | [diff] [blame] | 659 | else |
| 660 | { |
| 661 | HDR.nRows=ReadBlobMSBLong(image); |
| 662 | HDR.nCols=ReadBlobMSBLong(image); |
| 663 | HDR.imagf=ReadBlobMSBLong(image); |
| 664 | HDR.nameLen=ReadBlobMSBLong(image); |
| 665 | endian=MSBEndian; |
| 666 | } |
| 667 | if ((HDR.imagf != 0) && (HDR.imagf != 1)) |
| 668 | break; |
| 669 | if (HDR.nameLen > 0xFFFF) |
| 670 | return((Image *) NULL); |
| 671 | for (i=0; i < (ssize_t) HDR.nameLen; i++) |
| 672 | { |
| 673 | int |
| 674 | byte; |
| 675 | |
| 676 | /* |
| 677 | Skip matrix name. |
| 678 | */ |
| 679 | byte=ReadBlobByte(image); |
| 680 | if (byte == EOF) |
| 681 | { |
| 682 | ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", |
| 683 | image->filename); |
| 684 | break; |
| 685 | } |
| 686 | } |
| 687 | image->columns=(size_t) HDR.nRows; |
| 688 | image->rows=(size_t) HDR.nCols; |
| 689 | SetImageColorspace(image,GRAYColorspace,exception); |
| 690 | if (image_info->ping != MagickFalse) |
| 691 | { |
| 692 | Swap(image->columns,image->rows); |
Cristy | e8f0cc6 | 2017-08-20 08:09:32 -0400 | [diff] [blame] | 693 | if(HDR.imagf==1) ldblk *= 2; |
| 694 | SeekBlob(image, HDR.nCols*ldblk, SEEK_CUR); |
| 695 | goto skip_reading_current; |
Cristy | a1936a7 | 2016-11-13 19:39:22 -0500 | [diff] [blame] | 696 | } |
| 697 | status=SetImageExtent(image,image->columns,image->rows,exception); |
| 698 | if (status == MagickFalse) |
| 699 | return((Image *) NULL); |
| 700 | quantum_info=AcquireQuantumInfo(image_info,image); |
| 701 | if (quantum_info == (QuantumInfo *) NULL) |
| 702 | return((Image *) NULL); |
| 703 | switch(HDR.Type[1]) |
| 704 | { |
| 705 | case 0: |
| 706 | format_type=FloatingPointQuantumFormat; |
| 707 | depth=64; |
| 708 | break; |
| 709 | case 1: |
| 710 | format_type=FloatingPointQuantumFormat; |
| 711 | depth=32; |
| 712 | break; |
| 713 | case 2: |
| 714 | format_type=UnsignedQuantumFormat; |
| 715 | depth=16; |
| 716 | break; |
| 717 | case 3: |
| 718 | format_type=SignedQuantumFormat; |
| 719 | depth=16; |
Cristy | 0ea5f58 | 2016-12-24 13:19:56 -0500 | [diff] [blame] | 720 | break; |
Cristy | a1936a7 | 2016-11-13 19:39:22 -0500 | [diff] [blame] | 721 | case 4: |
| 722 | format_type=UnsignedQuantumFormat; |
| 723 | depth=8; |
| 724 | break; |
| 725 | default: |
| 726 | format_type=UnsignedQuantumFormat; |
| 727 | depth=8; |
| 728 | break; |
| 729 | } |
| 730 | image->depth=depth; |
| 731 | if (HDR.Type[0] != 0) |
| 732 | SetQuantumEndian(image,quantum_info,MSBEndian); |
| 733 | status=SetQuantumFormat(image,quantum_info,format_type); |
| 734 | status=SetQuantumDepth(image,quantum_info,depth); |
| 735 | status=SetQuantumEndian(image,quantum_info,endian); |
| 736 | SetQuantumScale(quantum_info,1.0); |
| 737 | pixels=(unsigned char *) GetQuantumPixels(quantum_info); |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 738 | for (y=0; y < (ssize_t) image->rows; y++) |
| 739 | { |
Cristy | a1936a7 | 2016-11-13 19:39:22 -0500 | [diff] [blame] | 740 | register Quantum |
| 741 | *magick_restrict q; |
| 742 | |
Cristy | a672d4c | 2016-05-16 14:02:19 -0400 | [diff] [blame] | 743 | count=ReadBlob(image,depth/8*image->columns,(char *) pixels); |
| 744 | if (count == -1) |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 745 | break; |
Cristy | a1936a7 | 2016-11-13 19:39:22 -0500 | [diff] [blame] | 746 | q=QueueAuthenticPixels(image,0,image->rows-y-1,image->columns,1, |
| 747 | exception); |
| 748 | if (q == (Quantum *) NULL) |
| 749 | break; |
| 750 | (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info, |
| 751 | GrayQuantum,pixels,exception); |
| 752 | if ((HDR.Type[1] == 2) || (HDR.Type[1] == 3)) |
| 753 | FixSignedValues(image,q,(int) image->columns); |
| 754 | if (SyncAuthenticPixels(image,exception) == MagickFalse) |
| 755 | break; |
| 756 | if (image->previous == (Image *) NULL) |
| 757 | { |
| 758 | status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, |
| 759 | image->rows); |
| 760 | if (status == MagickFalse) |
| 761 | break; |
| 762 | } |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 763 | } |
Cristy | a1936a7 | 2016-11-13 19:39:22 -0500 | [diff] [blame] | 764 | if (HDR.imagf == 1) |
| 765 | for (y=0; y < (ssize_t) image->rows; y++) |
| 766 | { |
| 767 | /* |
| 768 | Read complex pixels. |
| 769 | */ |
| 770 | count=ReadBlob(image,depth/8*image->columns,(char *) pixels); |
| 771 | if (count == -1) |
| 772 | break; |
| 773 | if (HDR.Type[1] == 0) |
| 774 | InsertComplexDoubleRow(image,(double *) pixels,y,0,0,exception); |
| 775 | else |
| 776 | InsertComplexFloatRow(image,(float *) pixels,y,0,0,exception); |
| 777 | } |
Cristy | 79e5dbc | 2017-04-27 07:45:09 -0400 | [diff] [blame] | 778 | if (quantum_info != (QuantumInfo *) NULL) |
| 779 | quantum_info=DestroyQuantumInfo(quantum_info); |
Cristy | a1936a7 | 2016-11-13 19:39:22 -0500 | [diff] [blame] | 780 | rotate_image=RotateImage(image,90.0,exception); |
| 781 | if (rotate_image != (Image *) NULL) |
| 782 | { |
| 783 | image=DestroyImage(image); |
| 784 | image=rotate_image; |
| 785 | } |
| 786 | if (EOFBlob(image) != MagickFalse) |
| 787 | { |
| 788 | ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", |
| 789 | image->filename); |
| 790 | break; |
| 791 | } |
| 792 | /* |
| 793 | Proceed to next image. |
| 794 | */ |
| 795 | if (image_info->number_scenes != 0) |
| 796 | if (image->scene >= (image_info->scene+image_info->number_scenes-1)) |
| 797 | break; |
| 798 | /* |
| 799 | Allocate next image structure. |
| 800 | */ |
Cristy | e8f0cc6 | 2017-08-20 08:09:32 -0400 | [diff] [blame] | 801 | skip_reading_current: |
Cristy | a1936a7 | 2016-11-13 19:39:22 -0500 | [diff] [blame] | 802 | AcquireNextImage(image_info,image,exception); |
| 803 | if (GetNextImageInList(image) == (Image *) NULL) |
| 804 | { |
| 805 | image=DestroyImageList(image); |
| 806 | return((Image *) NULL); |
| 807 | } |
| 808 | image=SyncNextImageInList(image); |
| 809 | status=SetImageProgress(image,LoadImagesTag,TellBlob(image), |
| 810 | GetBlobSize(image)); |
| 811 | if (status == MagickFalse) |
| 812 | break; |
| 813 | } |
| 814 | (void) CloseBlob(image); |
| 815 | return(GetFirstImageInList(image)); |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 816 | } |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 817 | |
| 818 | /* |
| 819 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| 820 | % % |
| 821 | % % |
| 822 | % % |
| 823 | % R e a d M A T L A B i m a g e % |
| 824 | % % |
| 825 | % % |
| 826 | % % |
| 827 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| 828 | % |
| 829 | % ReadMATImage() reads an MAT X image file and returns it. It |
| 830 | % allocates the memory necessary for the new Image structure and returns a |
| 831 | % pointer to the new image. |
| 832 | % |
| 833 | % The format of the ReadMATImage method is: |
| 834 | % |
| 835 | % Image *ReadMATImage(const ImageInfo *image_info,ExceptionInfo *exception) |
| 836 | % |
| 837 | % A description of each parameter follows: |
| 838 | % |
| 839 | % o image: Method ReadMATImage returns a pointer to the image after |
| 840 | % reading. A null image is returned if there is a memory shortage or if |
| 841 | % the image cannot be read. |
| 842 | % |
| 843 | % o image_info: Specifies a pointer to a ImageInfo structure. |
| 844 | % |
| 845 | % o exception: return any errors or warnings in this structure. |
| 846 | % |
| 847 | */ |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 848 | static Image *ReadMATImage(const ImageInfo *image_info,ExceptionInfo *exception) |
| 849 | { |
| 850 | Image *image, *image2=NULL, |
| 851 | *rotated_image; |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 852 | register Quantum *q; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 853 | |
| 854 | unsigned int status; |
| 855 | MATHeader MATLAB_HDR; |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 856 | size_t size; |
cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 857 | size_t CellType; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 858 | QuantumInfo *quantum_info; |
| 859 | ImageInfo *clone_info; |
| 860 | int i; |
cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 861 | ssize_t ldblk; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 862 | unsigned char *BImgBuff = NULL; |
| 863 | double MinVal, MaxVal; |
cristy | f5e4a81 | 2012-05-01 16:40:19 +0000 | [diff] [blame] | 864 | unsigned z, z2; |
| 865 | unsigned Frames; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 866 | int logging; |
| 867 | int sample_size; |
| 868 | MagickOffsetType filepos=0x80; |
| 869 | BlobInfo *blob; |
cristy | eaedf06 | 2010-05-29 22:36:02 +0000 | [diff] [blame] | 870 | size_t one; |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 871 | |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 872 | unsigned int (*ReadBlobXXXLong)(Image *image); |
| 873 | unsigned short (*ReadBlobXXXShort)(Image *image); |
| 874 | void (*ReadBlobDoublesXXX)(Image * image, size_t len, double *data); |
| 875 | void (*ReadBlobFloatsXXX)(Image * image, size_t len, float *data); |
| 876 | |
| 877 | |
| 878 | assert(image_info != (const ImageInfo *) NULL); |
cristy | e1c94d9 | 2015-06-28 12:16:33 +0000 | [diff] [blame] | 879 | assert(image_info->signature == MagickCoreSignature); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 880 | assert(exception != (ExceptionInfo *) NULL); |
cristy | e1c94d9 | 2015-06-28 12:16:33 +0000 | [diff] [blame] | 881 | assert(exception->signature == MagickCoreSignature); |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 882 | logging = LogMagickEvent(CoderEvent,GetMagickModule(),"enter"); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 883 | |
| 884 | /* |
| 885 | Open image file. |
| 886 | */ |
cristy | 9950d57 | 2011-10-01 18:22:35 +0000 | [diff] [blame] | 887 | image = AcquireImage(image_info,exception); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 888 | |
| 889 | status = OpenBlob(image_info, image, ReadBinaryBlobMode, exception); |
| 890 | if (status == MagickFalse) |
| 891 | { |
| 892 | image=DestroyImageList(image); |
| 893 | return((Image *) NULL); |
| 894 | } |
| 895 | /* |
| 896 | Read MATLAB image. |
| 897 | */ |
Cristy | 79e5dbc | 2017-04-27 07:45:09 -0400 | [diff] [blame] | 898 | quantum_info=(QuantumInfo *) NULL; |
Cristy | a678ee7 | 2017-06-24 10:42:26 -0400 | [diff] [blame] | 899 | clone_info=(ImageInfo *) NULL; |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 900 | if (ReadBlob(image,124,(unsigned char *) &MATLAB_HDR.identific) != 124) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 901 | ThrowReaderException(CorruptImageError,"ImproperImageHeader"); |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 902 | if (strncmp(MATLAB_HDR.identific,"MATLAB",6) != 0) |
| 903 | { |
| 904 | image2=ReadMATImageV4(image_info,image,exception); |
| 905 | if (image2 == NULL) |
| 906 | goto MATLAB_KO; |
| 907 | image=image2; |
| 908 | goto END_OF_READING; |
| 909 | } |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 910 | MATLAB_HDR.Version = ReadBlobLSBShort(image); |
| 911 | if(ReadBlob(image,2,(unsigned char *) &MATLAB_HDR.EndianIndicator) != 2) |
| 912 | ThrowReaderException(CorruptImageError,"ImproperImageHeader"); |
| 913 | |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 914 | if (logging) |
| 915 | (void) LogMagickEvent(CoderEvent,GetMagickModule()," Endian %c%c", |
| 916 | MATLAB_HDR.EndianIndicator[0],MATLAB_HDR.EndianIndicator[1]); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 917 | if (!strncmp(MATLAB_HDR.EndianIndicator, "IM", 2)) |
| 918 | { |
| 919 | ReadBlobXXXLong = ReadBlobLSBLong; |
| 920 | ReadBlobXXXShort = ReadBlobLSBShort; |
| 921 | ReadBlobDoublesXXX = ReadBlobDoublesLSB; |
| 922 | ReadBlobFloatsXXX = ReadBlobFloatsLSB; |
| 923 | image->endian = LSBEndian; |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 924 | } |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 925 | else if (!strncmp(MATLAB_HDR.EndianIndicator, "MI", 2)) |
| 926 | { |
| 927 | ReadBlobXXXLong = ReadBlobMSBLong; |
| 928 | ReadBlobXXXShort = ReadBlobMSBShort; |
| 929 | ReadBlobDoublesXXX = ReadBlobDoublesMSB; |
| 930 | ReadBlobFloatsXXX = ReadBlobFloatsMSB; |
| 931 | image->endian = MSBEndian; |
| 932 | } |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 933 | else |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 934 | goto MATLAB_KO; /* unsupported endian */ |
| 935 | |
| 936 | if (strncmp(MATLAB_HDR.identific, "MATLAB", 6)) |
Cristy | bfb7915 | 2017-07-09 08:24:18 -0400 | [diff] [blame] | 937 | { |
| 938 | MATLAB_KO: |
Cristy | fc65823 | 2017-07-25 08:23:35 -0400 | [diff] [blame] | 939 | if ((image != image2) && (image2 != (Image *) NULL)) |
| 940 | image2=DestroyImage(image2); |
Cristy | ac38f52 | 2017-07-23 10:40:17 -0400 | [diff] [blame] | 941 | if (clone_info != (ImageInfo *) NULL) |
| 942 | clone_info=DestroyImageInfo(clone_info); |
Cristy | bfb7915 | 2017-07-09 08:24:18 -0400 | [diff] [blame] | 943 | ThrowReaderException(CorruptImageError,"ImproperImageHeader"); |
| 944 | } |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 945 | |
| 946 | filepos = TellBlob(image); |
| 947 | while(!EOFBlob(image)) /* object parser loop */ |
| 948 | { |
cristy | f5e4a81 | 2012-05-01 16:40:19 +0000 | [diff] [blame] | 949 | Frames = 1; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 950 | (void) SeekBlob(image,filepos,SEEK_SET); |
| 951 | /* printf("pos=%X\n",TellBlob(image)); */ |
| 952 | |
| 953 | MATLAB_HDR.DataType = ReadBlobXXXLong(image); |
| 954 | if(EOFBlob(image)) break; |
| 955 | MATLAB_HDR.ObjectSize = ReadBlobXXXLong(image); |
| 956 | if(EOFBlob(image)) break; |
Cristy | 32fa22a | 2017-07-09 14:36:16 -0400 | [diff] [blame] | 957 | if((MagickSizeType) (MATLAB_HDR.ObjectSize+filepos) > GetBlobSize(image)) |
Cristy | 7d2e159 | 2017-07-03 20:26:21 -0400 | [diff] [blame] | 958 | goto MATLAB_KO; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 959 | filepos += MATLAB_HDR.ObjectSize + 4 + 4; |
| 960 | |
Cristy | a678ee7 | 2017-06-24 10:42:26 -0400 | [diff] [blame] | 961 | clone_info=CloneImageInfo(image_info); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 962 | image2 = image; |
| 963 | #if defined(MAGICKCORE_ZLIB_DELEGATE) |
| 964 | if(MATLAB_HDR.DataType == miCOMPRESSED) |
| 965 | { |
Cristy | 7d2e159 | 2017-07-03 20:26:21 -0400 | [diff] [blame] | 966 | image2 = decompress_block(image,&MATLAB_HDR.ObjectSize,clone_info,exception); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 967 | if(image2==NULL) continue; |
| 968 | MATLAB_HDR.DataType = ReadBlobXXXLong(image2); /* replace compressed object type. */ |
| 969 | } |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 970 | #endif |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 971 | |
Cristy | f1f2089 | 2017-08-07 15:40:27 -0400 | [diff] [blame] | 972 | if (MATLAB_HDR.DataType!=miMATRIX) |
| 973 | { |
| 974 | clone_info=DestroyImageInfo(clone_info); |
| 975 | continue; /* skip another objects. */ |
| 976 | } |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 977 | |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 978 | MATLAB_HDR.unknown1 = ReadBlobXXXLong(image2); |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 979 | MATLAB_HDR.unknown2 = ReadBlobXXXLong(image2); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 980 | |
| 981 | MATLAB_HDR.unknown5 = ReadBlobXXXLong(image2); |
| 982 | MATLAB_HDR.StructureClass = MATLAB_HDR.unknown5 & 0xFF; |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 983 | MATLAB_HDR.StructureFlag = (MATLAB_HDR.unknown5>>8) & 0xFF; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 984 | |
| 985 | MATLAB_HDR.unknown3 = ReadBlobXXXLong(image2); |
| 986 | if(image!=image2) |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 987 | MATLAB_HDR.unknown4 = ReadBlobXXXLong(image2); /* ??? don't understand why ?? */ |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 988 | MATLAB_HDR.unknown4 = ReadBlobXXXLong(image2); |
| 989 | MATLAB_HDR.DimFlag = ReadBlobXXXLong(image2); |
| 990 | MATLAB_HDR.SizeX = ReadBlobXXXLong(image2); |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 991 | MATLAB_HDR.SizeY = ReadBlobXXXLong(image2); |
| 992 | |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 993 | |
| 994 | switch(MATLAB_HDR.DimFlag) |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 995 | { |
cristy | f5e4a81 | 2012-05-01 16:40:19 +0000 | [diff] [blame] | 996 | case 8: z2=z=1; break; /* 2D matrix*/ |
| 997 | case 12: z2=z = ReadBlobXXXLong(image2); /* 3D matrix RGB*/ |
| 998 | (void) ReadBlobXXXLong(image2); |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 999 | if(z!=3) ThrowReaderException(CoderError, "MultidimensionalMatricesAreNotSupported"); |
| 1000 | break; |
cristy | f5e4a81 | 2012-05-01 16:40:19 +0000 | [diff] [blame] | 1001 | case 16: z2=z = ReadBlobXXXLong(image2); /* 4D matrix animation */ |
| 1002 | if(z!=3 && z!=1) |
| 1003 | ThrowReaderException(CoderError, "MultidimensionalMatricesAreNotSupported"); |
dirk | 94c2e0b | 2016-05-29 08:15:20 +0200 | [diff] [blame] | 1004 | Frames = ReadBlobXXXLong(image2); |
| 1005 | if (Frames == 0) |
| 1006 | ThrowReaderException(CorruptImageError,"ImproperImageHeader"); |
cristy | f5e4a81 | 2012-05-01 16:40:19 +0000 | [diff] [blame] | 1007 | break; |
Cristy | 7a020ac | 2017-07-25 08:31:17 -0400 | [diff] [blame] | 1008 | default: |
| 1009 | if (clone_info != (ImageInfo *) NULL) |
| 1010 | clone_info=DestroyImageInfo(clone_info); |
| 1011 | if ((image != image2) && (image2 != (Image *) NULL)) |
| 1012 | image2=DestroyImage(image2); |
| 1013 | ThrowReaderException(CoderError, "MultidimensionalMatricesAreNotSupported"); |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1014 | } |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1015 | |
| 1016 | MATLAB_HDR.Flag1 = ReadBlobXXXShort(image2); |
| 1017 | MATLAB_HDR.NameFlag = ReadBlobXXXShort(image2); |
| 1018 | |
| 1019 | if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(), |
| 1020 | "MATLAB_HDR.StructureClass %d",MATLAB_HDR.StructureClass); |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1021 | if (MATLAB_HDR.StructureClass != mxCHAR_CLASS && |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1022 | MATLAB_HDR.StructureClass != mxSINGLE_CLASS && /* float + complex float */ |
| 1023 | MATLAB_HDR.StructureClass != mxDOUBLE_CLASS && /* double + complex double */ |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1024 | MATLAB_HDR.StructureClass != mxINT8_CLASS && |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1025 | MATLAB_HDR.StructureClass != mxUINT8_CLASS && /* uint8 + uint8 3D */ |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1026 | MATLAB_HDR.StructureClass != mxINT16_CLASS && |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1027 | MATLAB_HDR.StructureClass != mxUINT16_CLASS && /* uint16 + uint16 3D */ |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1028 | MATLAB_HDR.StructureClass != mxINT32_CLASS && |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1029 | MATLAB_HDR.StructureClass != mxUINT32_CLASS && /* uint32 + uint32 3D */ |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1030 | MATLAB_HDR.StructureClass != mxINT64_CLASS && |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1031 | MATLAB_HDR.StructureClass != mxUINT64_CLASS) /* uint64 + uint64 3D */ |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1032 | ThrowReaderException(CoderError,"UnsupportedCellTypeInTheMatrix"); |
| 1033 | |
| 1034 | switch (MATLAB_HDR.NameFlag) |
| 1035 | { |
| 1036 | case 0: |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1037 | size = ReadBlobXXXLong(image2); /* Object name string size */ |
cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 1038 | size = 4 * (ssize_t) ((size + 3 + 1) / 4); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1039 | (void) SeekBlob(image2, size, SEEK_CUR); |
| 1040 | break; |
| 1041 | case 1: |
| 1042 | case 2: |
| 1043 | case 3: |
| 1044 | case 4: |
| 1045 | (void) ReadBlob(image2, 4, (unsigned char *) &size); /* Object name string */ |
| 1046 | break; |
| 1047 | default: |
| 1048 | goto MATLAB_KO; |
| 1049 | } |
| 1050 | |
| 1051 | CellType = ReadBlobXXXLong(image2); /* Additional object type */ |
cristy | f2faecf | 2010-05-28 19:19:36 +0000 | [diff] [blame] | 1052 | if (logging) |
| 1053 | (void) LogMagickEvent(CoderEvent,GetMagickModule(), |
cristy | e8c25f9 | 2010-06-03 00:53:06 +0000 | [diff] [blame] | 1054 | "MATLAB_HDR.CellType: %.20g",(double) CellType); |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1055 | |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1056 | (void) ReadBlob(image2, 4, (unsigned char *) &size); /* data size */ |
| 1057 | |
cristy | f5e4a81 | 2012-05-01 16:40:19 +0000 | [diff] [blame] | 1058 | NEXT_FRAME: |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1059 | switch (CellType) |
| 1060 | { |
| 1061 | case miINT8: |
| 1062 | case miUINT8: |
| 1063 | sample_size = 8; |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1064 | if(MATLAB_HDR.StructureFlag & FLAG_LOGICAL) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1065 | image->depth = 1; |
| 1066 | else |
| 1067 | image->depth = 8; /* Byte type cell */ |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1068 | ldblk = (ssize_t) MATLAB_HDR.SizeX; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1069 | break; |
| 1070 | case miINT16: |
| 1071 | case miUINT16: |
| 1072 | sample_size = 16; |
| 1073 | image->depth = 16; /* Word type cell */ |
cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 1074 | ldblk = (ssize_t) (2 * MATLAB_HDR.SizeX); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1075 | break; |
| 1076 | case miINT32: |
| 1077 | case miUINT32: |
| 1078 | sample_size = 32; |
| 1079 | image->depth = 32; /* Dword type cell */ |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1080 | ldblk = (ssize_t) (4 * MATLAB_HDR.SizeX); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1081 | break; |
| 1082 | case miINT64: |
| 1083 | case miUINT64: |
| 1084 | sample_size = 64; |
| 1085 | image->depth = 64; /* Qword type cell */ |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1086 | ldblk = (ssize_t) (8 * MATLAB_HDR.SizeX); |
| 1087 | break; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1088 | case miSINGLE: |
| 1089 | sample_size = 32; |
| 1090 | image->depth = 32; /* double type cell */ |
| 1091 | (void) SetImageOption(clone_info,"quantum:format","floating-point"); |
| 1092 | if (MATLAB_HDR.StructureFlag & FLAG_COMPLEX) |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1093 | { /* complex float type cell */ |
| 1094 | } |
cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 1095 | ldblk = (ssize_t) (4 * MATLAB_HDR.SizeX); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1096 | break; |
| 1097 | case miDOUBLE: |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1098 | sample_size = 64; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1099 | image->depth = 64; /* double type cell */ |
| 1100 | (void) SetImageOption(clone_info,"quantum:format","floating-point"); |
dirk | 93b02b7 | 2013-11-16 16:03:36 +0000 | [diff] [blame] | 1101 | DisableMSCWarning(4127) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1102 | if (sizeof(double) != 8) |
dirk | 93b02b7 | 2013-11-16 16:03:36 +0000 | [diff] [blame] | 1103 | RestoreMSCWarning |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1104 | ThrowReaderException(CoderError, "IncompatibleSizeOfDouble"); |
| 1105 | if (MATLAB_HDR.StructureFlag & FLAG_COMPLEX) |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1106 | { /* complex double type cell */ |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1107 | } |
cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 1108 | ldblk = (ssize_t) (8 * MATLAB_HDR.SizeX); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1109 | break; |
| 1110 | default: |
Cristy | ff3faa3 | 2017-07-23 10:35:56 -0400 | [diff] [blame] | 1111 | if ((image != image2) && (image2 != (Image *) NULL)) |
| 1112 | image2=DestroyImage(image2); |
| 1113 | if (clone_info) |
| 1114 | clone_info=DestroyImageInfo(clone_info); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1115 | ThrowReaderException(CoderError, "UnsupportedCellTypeInTheMatrix"); |
| 1116 | } |
cristy | da16f16 | 2011-02-19 23:52:17 +0000 | [diff] [blame] | 1117 | (void) sample_size; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1118 | image->columns = MATLAB_HDR.SizeX; |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1119 | image->rows = MATLAB_HDR.SizeY; |
cristy | eaedf06 | 2010-05-29 22:36:02 +0000 | [diff] [blame] | 1120 | one=1; |
| 1121 | image->colors = one << image->depth; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1122 | if (image->columns == 0 || image->rows == 0) |
| 1123 | goto MATLAB_KO; |
Cristy | 7d2e159 | 2017-07-03 20:26:21 -0400 | [diff] [blame] | 1124 | if((unsigned long)ldblk*MATLAB_HDR.SizeY > MATLAB_HDR.ObjectSize) |
| 1125 | goto MATLAB_KO; |
cristy | dfc9c53 | 2012-05-12 23:45:48 +0000 | [diff] [blame] | 1126 | /* Image is gray when no complex flag is set and 2D Matrix */ |
| 1127 | if ((MATLAB_HDR.DimFlag == 8) && |
| 1128 | ((MATLAB_HDR.StructureFlag & FLAG_COMPLEX) == 0)) |
| 1129 | { |
| 1130 | image->type=GrayscaleType; |
| 1131 | SetImageColorspace(image,GRAYColorspace,exception); |
| 1132 | } |
| 1133 | |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1134 | |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1135 | /* |
| 1136 | If ping is true, then only set image size and colors without |
| 1137 | reading any image data. |
| 1138 | */ |
| 1139 | if (image_info->ping) |
| 1140 | { |
cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 1141 | size_t temp = image->columns; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1142 | image->columns = image->rows; |
| 1143 | image->rows = temp; |
| 1144 | goto done_reading; /* !!!!!! BAD !!!! */ |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1145 | } |
cristy | acabb84 | 2014-12-14 23:36:33 +0000 | [diff] [blame] | 1146 | status=SetImageExtent(image,image->columns,image->rows,exception); |
| 1147 | if (status == MagickFalse) |
Cristy | 8ac5376 | 2017-08-04 07:14:09 -0400 | [diff] [blame] | 1148 | { |
| 1149 | if ((image != image2) && (image2 != (Image *) NULL)) |
| 1150 | image2=DestroyImage(image2); |
| 1151 | return(DestroyImageList(image)); |
| 1152 | } |
Dirk Lemstra | cdafbc7 | 2017-05-07 09:53:16 +0200 | [diff] [blame] | 1153 | quantum_info=AcquireQuantumInfo(clone_info,image); |
| 1154 | if (quantum_info == (QuantumInfo *) NULL) |
| 1155 | ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1156 | |
| 1157 | /* ----- Load raster data ----- */ |
Cristy | 1bc1fd0 | 2016-02-14 09:23:34 -0500 | [diff] [blame] | 1158 | BImgBuff = (unsigned char *) AcquireQuantumMemory((size_t) (ldblk),sizeof(double)); /* Ldblk was set in the check phase */ |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1159 | if (BImgBuff == NULL) |
cristy | d9e30a4 | 2012-12-19 15:37:07 +0000 | [diff] [blame] | 1160 | ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); |
Cristy | 51b0ae0 | 2017-01-26 11:22:42 -0500 | [diff] [blame] | 1161 | (void) ResetMagickMemory(BImgBuff,0,ldblk*sizeof(double)); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1162 | |
| 1163 | MinVal = 0; |
| 1164 | MaxVal = 0; |
| 1165 | if (CellType==miDOUBLE || CellType==miSINGLE) /* Find Min and Max Values for floats */ |
| 1166 | { |
| 1167 | CalcMinMax(image2, image_info->endian, MATLAB_HDR.SizeX, MATLAB_HDR.SizeY, CellType, ldblk, BImgBuff, &quantum_info->minimum, &quantum_info->maximum); |
| 1168 | } |
| 1169 | |
| 1170 | /* Main loop for reading all scanlines */ |
| 1171 | if(z==1) z=0; /* read grey scanlines */ |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1172 | /* else read color scanlines */ |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1173 | do |
| 1174 | { |
cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 1175 | for (i = 0; i < (ssize_t) MATLAB_HDR.SizeY; i++) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1176 | { |
cristy | 9572202 | 2013-01-15 12:58:21 +0000 | [diff] [blame] | 1177 | q=GetAuthenticPixels(image,0,MATLAB_HDR.SizeY-i-1,image->columns,1,exception); |
cristy | f432c63 | 2014-12-07 15:11:28 +0000 | [diff] [blame] | 1178 | if (q == (Quantum *) NULL) |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1179 | { |
| 1180 | if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(), |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1181 | " MAT set image pixels returns unexpected NULL on a row %u.", (unsigned)(MATLAB_HDR.SizeY-i-1)); |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1182 | goto done_reading; /* Skip image rotation, when cannot set image pixels */ |
| 1183 | } |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1184 | if(ReadBlob(image2,ldblk,(unsigned char *)BImgBuff) != (ssize_t) ldblk) |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1185 | { |
| 1186 | if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(), |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1187 | " MAT cannot read scanrow %u from a file.", (unsigned)(MATLAB_HDR.SizeY-i-1)); |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1188 | goto ExitLoop; |
| 1189 | } |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1190 | if((CellType==miINT8 || CellType==miUINT8) && (MATLAB_HDR.StructureFlag & FLAG_LOGICAL)) |
| 1191 | { |
| 1192 | FixLogical((unsigned char *)BImgBuff,ldblk); |
| 1193 | if(ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,z2qtype[z],BImgBuff,exception) <= 0) |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1194 | { |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1195 | ImportQuantumPixelsFailed: |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1196 | if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(), |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1197 | " MAT failed to ImportQuantumPixels for a row %u", (unsigned)(MATLAB_HDR.SizeY-i-1)); |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1198 | break; |
| 1199 | } |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1200 | } |
| 1201 | else |
| 1202 | { |
| 1203 | if(ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,z2qtype[z],BImgBuff,exception) <= 0) |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1204 | goto ImportQuantumPixelsFailed; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1205 | |
| 1206 | |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1207 | if (z<=1 && /* fix only during a last pass z==0 || z==1 */ |
| 1208 | (CellType==miINT8 || CellType==miINT16 || CellType==miINT32 || CellType==miINT64)) |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 1209 | FixSignedValues(image,q,MATLAB_HDR.SizeX); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1210 | } |
| 1211 | |
| 1212 | if (!SyncAuthenticPixels(image,exception)) |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1213 | { |
| 1214 | if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(), |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1215 | " MAT failed to sync image pixels for a row %u", (unsigned)(MATLAB_HDR.SizeY-i-1)); |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1216 | goto ExitLoop; |
| 1217 | } |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1218 | } |
| 1219 | } while(z-- >= 2); |
| 1220 | ExitLoop: |
| 1221 | |
| 1222 | |
| 1223 | /* Read complex part of numbers here */ |
| 1224 | if (MATLAB_HDR.StructureFlag & FLAG_COMPLEX) |
| 1225 | { /* Find Min and Max Values for complex parts of floats */ |
| 1226 | CellType = ReadBlobXXXLong(image2); /* Additional object type */ |
| 1227 | i = ReadBlobXXXLong(image2); /* size of a complex part - toss away*/ |
| 1228 | |
| 1229 | if (CellType==miDOUBLE || CellType==miSINGLE) |
| 1230 | { |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1231 | CalcMinMax(image2, image_info->endian, MATLAB_HDR.SizeX, MATLAB_HDR.SizeY, CellType, ldblk, BImgBuff, &MinVal, &MaxVal); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1232 | } |
| 1233 | |
| 1234 | if (CellType==miDOUBLE) |
cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 1235 | for (i = 0; i < (ssize_t) MATLAB_HDR.SizeY; i++) |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1236 | { |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1237 | ReadBlobDoublesXXX(image2, ldblk, (double *)BImgBuff); |
cristy | c82a27b | 2011-10-21 01:07:16 +0000 | [diff] [blame] | 1238 | InsertComplexDoubleRow(image, (double *)BImgBuff, i, MinVal, MaxVal, |
| 1239 | exception); |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1240 | } |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1241 | |
| 1242 | if (CellType==miSINGLE) |
cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 1243 | for (i = 0; i < (ssize_t) MATLAB_HDR.SizeY; i++) |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1244 | { |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1245 | ReadBlobFloatsXXX(image2, ldblk, (float *)BImgBuff); |
cristy | c82a27b | 2011-10-21 01:07:16 +0000 | [diff] [blame] | 1246 | InsertComplexFloatRow(image,(float *)BImgBuff,i,MinVal,MaxVal, |
| 1247 | exception); |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1248 | } |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1249 | } |
| 1250 | |
| 1251 | /* Image is gray when no complex flag is set and 2D Matrix AGAIN!!! */ |
| 1252 | if ((MATLAB_HDR.DimFlag == 8) && |
| 1253 | ((MATLAB_HDR.StructureFlag & FLAG_COMPLEX) == 0)) |
| 1254 | image->type=GrayscaleType; |
| 1255 | if (image->depth == 1) |
| 1256 | image->type=BilevelType; |
| 1257 | |
| 1258 | if(image2==image) |
| 1259 | image2 = NULL; /* Remove shadow copy to an image before rotation. */ |
| 1260 | |
| 1261 | /* Rotate image. */ |
| 1262 | rotated_image = RotateImage(image, 90.0, exception); |
| 1263 | if (rotated_image != (Image *) NULL) |
| 1264 | { |
| 1265 | /* Remove page offsets added by RotateImage */ |
| 1266 | rotated_image->page.x=0; |
| 1267 | rotated_image->page.y=0; |
| 1268 | |
| 1269 | blob = rotated_image->blob; |
| 1270 | rotated_image->blob = image->blob; |
| 1271 | rotated_image->colors = image->colors; |
| 1272 | image->blob = blob; |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1273 | AppendImageToList(&image,rotated_image); |
| 1274 | DeleteImageFromList(&image); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1275 | } |
| 1276 | |
| 1277 | done_reading: |
| 1278 | |
| 1279 | if(image2!=NULL) |
| 1280 | if(image2!=image) |
| 1281 | { |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1282 | DeleteImageFromList(&image2); |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1283 | if(clone_info) |
| 1284 | { |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1285 | if(clone_info->file) |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1286 | { |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1287 | fclose(clone_info->file); |
| 1288 | clone_info->file = NULL; |
cristy | 18c6c27 | 2011-09-23 14:40:37 +0000 | [diff] [blame] | 1289 | (void) remove_utf8(clone_info->filename); |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1290 | } |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1291 | } |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1292 | } |
| 1293 | |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1294 | /* Allocate next image structure. */ |
cristy | 9950d57 | 2011-10-01 18:22:35 +0000 | [diff] [blame] | 1295 | AcquireNextImage(image_info,image,exception); |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1296 | if (image->next == (Image *) NULL) break; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1297 | image=SyncNextImageInList(image); |
| 1298 | image->columns=image->rows=0; |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1299 | image->colors=0; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1300 | |
cristy | a03e799 | 2010-06-25 12:18:06 +0000 | [diff] [blame] | 1301 | /* row scan buffer is no longer needed */ |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1302 | RelinquishMagickMemory(BImgBuff); |
| 1303 | BImgBuff = NULL; |
cristy | f5e4a81 | 2012-05-01 16:40:19 +0000 | [diff] [blame] | 1304 | |
| 1305 | if(--Frames>0) |
| 1306 | { |
| 1307 | z = z2; |
| 1308 | if(image2==NULL) image2 = image; |
| 1309 | goto NEXT_FRAME; |
| 1310 | } |
| 1311 | if ((image2!=NULL) && (image2!=image)) /* Does shadow temporary decompressed image exist? */ |
| 1312 | { |
| 1313 | /* CloseBlob(image2); */ |
| 1314 | DeleteImageFromList(&image2); |
| 1315 | if(clone_info) |
| 1316 | { |
| 1317 | if(clone_info->file) |
| 1318 | { |
| 1319 | fclose(clone_info->file); |
| 1320 | clone_info->file = NULL; |
| 1321 | (void) remove_utf8(clone_info->filename); |
| 1322 | } |
| 1323 | } |
| 1324 | } |
Cristy | 4b9eeff | 2017-07-27 12:41:05 -0400 | [diff] [blame] | 1325 | |
| 1326 | if (quantum_info != (QuantumInfo *) NULL) |
| 1327 | quantum_info=DestroyQuantumInfo(quantum_info); |
| 1328 | if (clone_info) |
| 1329 | clone_info=DestroyImageInfo(clone_info); |
cristy | f5e4a81 | 2012-05-01 16:40:19 +0000 | [diff] [blame] | 1330 | } |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1331 | |
| 1332 | RelinquishMagickMemory(BImgBuff); |
Cristy | 79e5dbc | 2017-04-27 07:45:09 -0400 | [diff] [blame] | 1333 | if (quantum_info != (QuantumInfo *) NULL) |
| 1334 | quantum_info=DestroyQuantumInfo(quantum_info); |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1335 | END_OF_READING: |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1336 | CloseBlob(image); |
| 1337 | |
| 1338 | |
| 1339 | { |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1340 | Image *p; |
cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 1341 | ssize_t scene=0; |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1342 | |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1343 | /* |
| 1344 | Rewind list, removing any empty images while rewinding. |
| 1345 | */ |
| 1346 | p=image; |
| 1347 | image=NULL; |
cristy | f432c63 | 2014-12-07 15:11:28 +0000 | [diff] [blame] | 1348 | while (p != (Image *) NULL) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1349 | { |
| 1350 | Image *tmp=p; |
| 1351 | if ((p->rows == 0) || (p->columns == 0)) { |
| 1352 | p=p->previous; |
Cristy | 04178de | 2017-08-09 08:01:38 -0400 | [diff] [blame] | 1353 | if (tmp == image2) |
| 1354 | image2=(Image *) NULL; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1355 | DeleteImageFromList(&tmp); |
| 1356 | } else { |
| 1357 | image=p; |
| 1358 | p=p->previous; |
| 1359 | } |
| 1360 | } |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1361 | |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1362 | /* |
| 1363 | Fix scene numbers |
| 1364 | */ |
| 1365 | for (p=image; p != (Image *) NULL; p=p->next) |
| 1366 | p->scene=scene++; |
| 1367 | } |
| 1368 | |
cristy | c5de699 | 2009-10-06 19:19:48 +0000 | [diff] [blame] | 1369 | if(clone_info != NULL) /* cleanup garbage file from compression */ |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1370 | { |
| 1371 | if(clone_info->file) |
| 1372 | { |
| 1373 | fclose(clone_info->file); |
| 1374 | clone_info->file = NULL; |
cristy | 18c6c27 | 2011-09-23 14:40:37 +0000 | [diff] [blame] | 1375 | (void) remove_utf8(clone_info->filename); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1376 | } |
| 1377 | DestroyImageInfo(clone_info); |
| 1378 | clone_info = NULL; |
| 1379 | } |
| 1380 | if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),"return"); |
Cristy | de8cdec | 2017-07-24 09:21:49 -0400 | [diff] [blame] | 1381 | if (image==NULL) |
| 1382 | ThrowReaderException(CorruptImageError,"ImproperImageHeader") |
Cristy | d9f1a91 | 2017-07-24 08:43:01 -0400 | [diff] [blame] | 1383 | else |
| 1384 | if ((image != image2) && (image2 != (Image *) NULL)) |
| 1385 | image2=DestroyImage(image2); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1386 | return (image); |
| 1387 | } |
| 1388 | |
| 1389 | /* |
| 1390 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| 1391 | % % |
| 1392 | % % |
| 1393 | % % |
| 1394 | % R e g i s t e r M A T I m a g e % |
| 1395 | % % |
| 1396 | % % |
| 1397 | % % |
| 1398 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| 1399 | % |
| 1400 | % Method RegisterMATImage adds attributes for the MAT image format to |
| 1401 | % the list of supported formats. The attributes include the image format |
| 1402 | % tag, a method to read and/or write the format, whether the format |
| 1403 | % supports the saving of more than one frame to the same file or blob, |
| 1404 | % whether the format supports native in-memory I/O, and a brief |
| 1405 | % description of the format. |
| 1406 | % |
| 1407 | % The format of the RegisterMATImage method is: |
| 1408 | % |
cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 1409 | % size_t RegisterMATImage(void) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1410 | % |
| 1411 | */ |
cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 1412 | ModuleExport size_t RegisterMATImage(void) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1413 | { |
| 1414 | MagickInfo |
| 1415 | *entry; |
| 1416 | |
dirk | 06b627a | 2015-04-06 18:59:17 +0000 | [diff] [blame] | 1417 | entry=AcquireMagickInfo("MAT","MAT","MATLAB level 5 image format"); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1418 | entry->decoder=(DecodeImageHandler *) ReadMATImage; |
| 1419 | entry->encoder=(EncodeImageHandler *) WriteMATImage; |
dirk | 08e9a11 | 2015-02-22 01:51:41 +0000 | [diff] [blame] | 1420 | entry->flags^=CoderBlobSupportFlag; |
Dirk Lemstra | 8974d77 | 2017-01-22 03:19:27 +0100 | [diff] [blame] | 1421 | entry->flags|=CoderDecoderSeekableStreamFlag; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1422 | (void) RegisterMagickInfo(entry); |
| 1423 | return(MagickImageCoderSignature); |
| 1424 | } |
| 1425 | |
| 1426 | /* |
| 1427 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| 1428 | % % |
| 1429 | % % |
| 1430 | % % |
| 1431 | % U n r e g i s t e r M A T I m a g e % |
| 1432 | % % |
| 1433 | % % |
| 1434 | % % |
| 1435 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| 1436 | % |
| 1437 | % Method UnregisterMATImage removes format registrations made by the |
| 1438 | % MAT module from the list of supported formats. |
| 1439 | % |
| 1440 | % The format of the UnregisterMATImage method is: |
| 1441 | % |
| 1442 | % UnregisterMATImage(void) |
| 1443 | % |
| 1444 | */ |
| 1445 | ModuleExport void UnregisterMATImage(void) |
| 1446 | { |
| 1447 | (void) UnregisterMagickInfo("MAT"); |
| 1448 | } |
| 1449 | |
| 1450 | /* |
| 1451 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| 1452 | % % |
| 1453 | % % |
| 1454 | % % |
| 1455 | % W r i t e M A T L A B I m a g e % |
| 1456 | % % |
| 1457 | % % |
| 1458 | % % |
| 1459 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| 1460 | % |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1461 | % Function WriteMATImage writes an Matlab matrix to a file. |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1462 | % |
| 1463 | % The format of the WriteMATImage method is: |
| 1464 | % |
cristy | 1e178e7 | 2011-08-28 19:44:34 +0000 | [diff] [blame] | 1465 | % MagickBooleanType WriteMATImage(const ImageInfo *image_info, |
| 1466 | % Image *image,ExceptionInfo *exception) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1467 | % |
| 1468 | % A description of each parameter follows. |
| 1469 | % |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1470 | % o image_info: Specifies a pointer to a ImageInfo structure. |
| 1471 | % |
| 1472 | % o image: A pointer to an Image structure. |
| 1473 | % |
cristy | 1e178e7 | 2011-08-28 19:44:34 +0000 | [diff] [blame] | 1474 | % o exception: return any errors or warnings in this structure. |
| 1475 | % |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1476 | */ |
cristy | 1e178e7 | 2011-08-28 19:44:34 +0000 | [diff] [blame] | 1477 | static MagickBooleanType WriteMATImage(const ImageInfo *image_info,Image *image, |
| 1478 | ExceptionInfo *exception) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1479 | { |
Dirk Lemstra | 4feca79 | 2017-05-07 11:54:08 +0200 | [diff] [blame] | 1480 | char |
| 1481 | MATLAB_HDR[0x80]; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1482 | |
Dirk Lemstra | 4feca79 | 2017-05-07 11:54:08 +0200 | [diff] [blame] | 1483 | MagickBooleanType |
| 1484 | status; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1485 | |
| 1486 | MagickOffsetType |
| 1487 | scene; |
| 1488 | |
Dirk Lemstra | 4feca79 | 2017-05-07 11:54:08 +0200 | [diff] [blame] | 1489 | struct tm |
| 1490 | local_time; |
| 1491 | |
| 1492 | time_t |
| 1493 | current_time; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1494 | |
| 1495 | /* |
| 1496 | Open output image file. |
| 1497 | */ |
| 1498 | assert(image_info != (const ImageInfo *) NULL); |
cristy | e1c94d9 | 2015-06-28 12:16:33 +0000 | [diff] [blame] | 1499 | assert(image_info->signature == MagickCoreSignature); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1500 | assert(image != (Image *) NULL); |
cristy | e1c94d9 | 2015-06-28 12:16:33 +0000 | [diff] [blame] | 1501 | assert(image->signature == MagickCoreSignature); |
Dirk Lemstra | 4feca79 | 2017-05-07 11:54:08 +0200 | [diff] [blame] | 1502 | (void) LogMagickEvent(CoderEvent,GetMagickModule(),"enter MAT"); |
cristy | 3a37efd | 2011-08-28 20:31:03 +0000 | [diff] [blame] | 1503 | assert(exception != (ExceptionInfo *) NULL); |
cristy | e1c94d9 | 2015-06-28 12:16:33 +0000 | [diff] [blame] | 1504 | assert(exception->signature == MagickCoreSignature); |
cristy | 1e178e7 | 2011-08-28 19:44:34 +0000 | [diff] [blame] | 1505 | status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1506 | if (status == MagickFalse) |
| 1507 | return(MagickFalse); |
| 1508 | image->depth=8; |
| 1509 | |
| 1510 | current_time=time((time_t *) NULL); |
| 1511 | #if defined(MAGICKCORE_HAVE_LOCALTIME_R) |
| 1512 | (void) localtime_r(¤t_time,&local_time); |
| 1513 | #else |
| 1514 | (void) memcpy(&local_time,localtime(¤t_time),sizeof(local_time)); |
| 1515 | #endif |
| 1516 | (void) memset(MATLAB_HDR,' ',MagickMin(sizeof(MATLAB_HDR),124)); |
cristy | 100a056 | 2014-04-18 01:27:37 +0000 | [diff] [blame] | 1517 | FormatLocaleString(MATLAB_HDR,sizeof(MATLAB_HDR), |
| 1518 | "MATLAB 5.0 MAT-file, Platform: %s, Created on: %s %s %2d %2d:%2d:%2d %d", |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1519 | OsDesc,DayOfWTab[local_time.tm_wday],MonthsTab[local_time.tm_mon], |
| 1520 | local_time.tm_mday,local_time.tm_hour,local_time.tm_min, |
| 1521 | local_time.tm_sec,local_time.tm_year+1900); |
| 1522 | MATLAB_HDR[0x7C]=0; |
| 1523 | MATLAB_HDR[0x7D]=1; |
| 1524 | MATLAB_HDR[0x7E]='I'; |
| 1525 | MATLAB_HDR[0x7F]='M'; |
| 1526 | (void) WriteBlob(image,sizeof(MATLAB_HDR),(unsigned char *) MATLAB_HDR); |
| 1527 | scene=0; |
| 1528 | do |
| 1529 | { |
Dirk Lemstra | 4feca79 | 2017-05-07 11:54:08 +0200 | [diff] [blame] | 1530 | char |
| 1531 | padding; |
| 1532 | |
| 1533 | MagickBooleanType |
| 1534 | is_gray; |
| 1535 | |
| 1536 | QuantumInfo |
| 1537 | *quantum_info; |
| 1538 | |
| 1539 | size_t |
| 1540 | data_size; |
| 1541 | |
| 1542 | unsigned char |
| 1543 | *pixels; |
| 1544 | |
| 1545 | unsigned int |
| 1546 | z; |
| 1547 | |
cristy | af8d391 | 2014-02-21 14:50:33 +0000 | [diff] [blame] | 1548 | (void) TransformImageColorspace(image,sRGBColorspace,exception); |
Dirk Lemstra | 4feca79 | 2017-05-07 11:54:08 +0200 | [diff] [blame] | 1549 | is_gray=SetImageGray(image,exception); |
| 1550 | z=(is_gray != MagickFalse) ? 0 : 3; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1551 | |
| 1552 | /* |
| 1553 | Store MAT header. |
| 1554 | */ |
Dirk Lemstra | 4feca79 | 2017-05-07 11:54:08 +0200 | [diff] [blame] | 1555 | data_size = image->rows * image->columns; |
| 1556 | if (is_gray == MagickFalse) |
| 1557 | data_size*=3; |
| 1558 | padding=((unsigned char)(data_size-1) & 0x7) ^ 0x7; |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1559 | |
Dirk Lemstra | 4feca79 | 2017-05-07 11:54:08 +0200 | [diff] [blame] | 1560 | (void) WriteBlobLSBLong(image,miMATRIX); |
| 1561 | (void) WriteBlobLSBLong(image,(unsigned int) data_size+padding+ |
| 1562 | ((is_gray != MagickFalse) ? 48 : 56)); |
| 1563 | (void) WriteBlobLSBLong(image,0x6); /* 0x88 */ |
| 1564 | (void) WriteBlobLSBLong(image,0x8); /* 0x8C */ |
| 1565 | (void) WriteBlobLSBLong(image,0x6); /* 0x90 */ |
| 1566 | (void) WriteBlobLSBLong(image,0); |
| 1567 | (void) WriteBlobLSBLong(image,0x5); /* 0x98 */ |
| 1568 | (void) WriteBlobLSBLong(image,(is_gray != MagickFalse) ? 0x8 : 0xC); /* 0x9C - DimFlag */ |
| 1569 | (void) WriteBlobLSBLong(image,(unsigned int) image->rows); /* x: 0xA0 */ |
| 1570 | (void) WriteBlobLSBLong(image,(unsigned int) image->columns); /* y: 0xA4 */ |
| 1571 | if (is_gray == MagickFalse) |
| 1572 | { |
| 1573 | (void) WriteBlobLSBLong(image,3); /* z: 0xA8 */ |
| 1574 | (void) WriteBlobLSBLong(image,0); |
| 1575 | } |
| 1576 | (void) WriteBlobLSBShort(image,1); /* 0xB0 */ |
| 1577 | (void) WriteBlobLSBShort(image,1); /* 0xB2 */ |
| 1578 | (void) WriteBlobLSBLong(image,'M'); /* 0xB4 */ |
| 1579 | (void) WriteBlobLSBLong(image,0x2); /* 0xB8 */ |
| 1580 | (void) WriteBlobLSBLong(image,(unsigned int) data_size); /* 0xBC */ |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1581 | |
| 1582 | /* |
| 1583 | Store image data. |
| 1584 | */ |
cristy | 5f766ef | 2014-12-14 21:12:47 +0000 | [diff] [blame] | 1585 | quantum_info=AcquireQuantumInfo(image_info,image); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1586 | if (quantum_info == (QuantumInfo *) NULL) |
| 1587 | ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); |
cristy | b3f97ae | 2015-05-18 12:29:32 +0000 | [diff] [blame] | 1588 | pixels=(unsigned char *) GetQuantumPixels(quantum_info); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1589 | do |
| 1590 | { |
Dirk Lemstra | 4feca79 | 2017-05-07 11:54:08 +0200 | [diff] [blame] | 1591 | const Quantum |
| 1592 | *p; |
| 1593 | |
| 1594 | ssize_t |
| 1595 | y; |
| 1596 | |
cristy | bb50337 | 2010-05-27 20:51:26 +0000 | [diff] [blame] | 1597 | for (y=0; y < (ssize_t)image->columns; y++) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1598 | { |
cristy | 1e178e7 | 2011-08-28 19:44:34 +0000 | [diff] [blame] | 1599 | p=GetVirtualPixels(image,y,0,1,image->rows,exception); |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 1600 | if (p == (const Quantum *) NULL) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1601 | break; |
cristy | 4c08aed | 2011-07-01 19:47:50 +0000 | [diff] [blame] | 1602 | (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info, |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1603 | z2qtype[z],pixels,exception); |
| 1604 | (void) WriteBlob(image,image->rows,pixels); |
Cristy | 9df12af | 2016-04-08 16:38:33 -0400 | [diff] [blame] | 1605 | } |
cristy | 1e178e7 | 2011-08-28 19:44:34 +0000 | [diff] [blame] | 1606 | if (SyncAuthenticPixels(image,exception) == MagickFalse) |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1607 | break; |
Dirk Lemstra | 4feca79 | 2017-05-07 11:54:08 +0200 | [diff] [blame] | 1608 | } while (z-- >= 2); |
| 1609 | while (padding-- > 0) |
| 1610 | (void) WriteBlobByte(image,0); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1611 | quantum_info=DestroyQuantumInfo(quantum_info); |
| 1612 | if (GetNextImageInList(image) == (Image *) NULL) |
| 1613 | break; |
| 1614 | image=SyncNextImageInList(image); |
| 1615 | status=SetImageProgress(image,SaveImagesTag,scene++, |
| 1616 | GetImageListLength(image)); |
| 1617 | if (status == MagickFalse) |
| 1618 | break; |
| 1619 | } while (image_info->adjoin != MagickFalse); |
| 1620 | (void) CloseBlob(image); |
Dirk Lemstra | 4feca79 | 2017-05-07 11:54:08 +0200 | [diff] [blame] | 1621 | return(status); |
cristy | 3ed852e | 2009-09-05 21:47:34 +0000 | [diff] [blame] | 1622 | } |