Coverage Report

Created: 2026-11-12 07:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/imagemagick/coders/mat.c
Line
Count
Source
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
%  Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization         %
20
%  dedicated to making software imaging solutions freely available.           %
21
%                                                                             %
22
%  You may not use this file except in compliance with the License.  You may  %
23
%  obtain a copy of the License at                                            %
24
%                                                                             %
25
%    https://imagemagick.org/license/                                         %
26
%                                                                             %
27
%  Unless required by applicable law or agreed to in writing, software        %
28
%  distributed under the License is distributed on an "AS IS" BASIS,          %
29
%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
30
%  See the License for the specific language governing permissions and        %
31
%  limitations under the License.                                             %
32
%                                                                             %
33
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34
%
35
%
36
*/
37

38
/*
39
  Include declarations.
40
*/
41
#include "MagickCore/studio.h"
42
#include "MagickCore/attribute.h"
43
#include "MagickCore/blob.h"
44
#include "MagickCore/blob-private.h"
45
#include "MagickCore/cache.h"
46
#include "MagickCore/color-private.h"
47
#include "MagickCore/colormap.h"
48
#include "MagickCore/colorspace-private.h"
49
#include "MagickCore/distort.h"
50
#include "MagickCore/exception.h"
51
#include "MagickCore/exception-private.h"
52
#include "MagickCore/image.h"
53
#include "MagickCore/image-private.h"
54
#include "MagickCore/list.h"
55
#include "MagickCore/magick.h"
56
#include "MagickCore/memory_.h"
57
#include "MagickCore/monitor.h"
58
#include "MagickCore/monitor-private.h"
59
#include "MagickCore/pixel-accessor.h"
60
#include "MagickCore/quantum.h"
61
#include "MagickCore/quantum-private.h"
62
#include "MagickCore/option.h"
63
#include "MagickCore/pixel.h"
64
#include "MagickCore/resource_.h"
65
#include "MagickCore/static.h"
66
#include "MagickCore/string_.h"
67
#include "MagickCore/module.h"
68
#include "MagickCore/timer-private.h"
69
#include "MagickCore/transform.h"
70
#include "MagickCore/utility-private.h"
71
#include "coders/coders-private.h"
72
#if defined(MAGICKCORE_ZLIB_DELEGATE)
73
 #include "zlib.h"
74
#endif
75

76
/*
77
  Forward declaration.
78
*/
79
static MagickBooleanType
80
  WriteMATImage(const ImageInfo *,Image *,ExceptionInfo *);
81
82
83
/* Auto coloring method, sorry this creates some artefact inside data
84
MinReal+j*MaxComplex = red  MaxReal+j*MaxComplex = black
85
MinReal+j*0 = white          MaxReal+j*0 = black
86
MinReal+j*MinComplex = blue  MaxReal+j*MinComplex = black
87
*/
88
89
typedef struct
90
{
91
  char identific[124];
92
  unsigned short Version;
93
  char EndianIndicator[2];
94
  unsigned int DataType;
95
  unsigned int ObjectSize;
96
  unsigned int unknown1;
97
  unsigned int unknown2;
98
99
  unsigned short unknown5;
100
  unsigned char StructureFlag;
101
  unsigned char StructureClass;
102
  unsigned int unknown3;
103
  unsigned int unknown4;
104
  unsigned int DimFlag;
105
106
  unsigned int SizeX;
107
  unsigned int SizeY;
108
  unsigned short Flag1;
109
  unsigned short NameFlag;
110
}
111
MATHeader;
112
113
static const char
114
  MonthsTab[12][4] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
115
116
static const char
117
   DayOfWTab[7][4] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
118
119
static const char
120
  OsDesc[] =
121
#if defined(MAGICKCORE_WINDOWS_SUPPORT)
122
    "PCWIN";
123
#else
124
 #ifdef __APPLE__
125
    "MAC";
126
 #else
127
    "LNX86";
128
 #endif
129
#endif
130
131
typedef enum
132
  {
133
    miINT8 = 1,   /* 8 bit signed */
134
    miUINT8,      /* 8 bit unsigned */
135
    miINT16,      /* 16 bit signed */
136
    miUINT16,     /* 16 bit unsigned */
137
    miINT32,      /* 32 bit signed */
138
    miUINT32,     /* 32 bit unsigned */
139
    miSINGLE,     /* IEEE 754 single precision float */
140
    miRESERVE1,
141
    miDOUBLE,     /* IEEE 754 double precision float */
142
    miRESERVE2,
143
    miRESERVE3,
144
    miINT64,      /* 64 bit signed */
145
    miUINT64,     /* 64 bit unsigned */
146
    miMATRIX,     /* MATLAB array */
147
    miCOMPRESSED, /* Compressed Data */
148
    miUTF8,       /* Unicode UTF-8 Encoded Character Data */
149
    miUTF16,      /* Unicode UTF-16 Encoded Character Data */
150
    miUTF32       /* Unicode UTF-32 Encoded Character Data */
151
  } mat5_data_type;
152
153
typedef enum
154
  {
155
    mxCELL_CLASS=1,  /* cell array */
156
    mxSTRUCT_CLASS,  /* structure */
157
    mxOBJECT_CLASS,  /* object */
158
    mxCHAR_CLASS,    /* character array */
159
    mxSPARSE_CLASS,  /* sparse array */
160
    mxDOUBLE_CLASS,  /* double precision array */
161
    mxSINGLE_CLASS,  /* single precision floating point */
162
    mxINT8_CLASS,    /* 8 bit signed integer */
163
    mxUINT8_CLASS,   /* 8 bit unsigned integer */
164
    mxINT16_CLASS,   /* 16 bit signed integer */
165
    mxUINT16_CLASS,  /* 16 bit unsigned integer */
166
    mxINT32_CLASS,   /* 32 bit signed integer */
167
    mxUINT32_CLASS,  /* 32 bit unsigned integer */
168
    mxINT64_CLASS,   /* 64 bit signed integer */
169
    mxUINT64_CLASS,  /* 64 bit unsigned integer */
170
    mxFUNCTION_CLASS /* Function handle */
171
  } arrayclasstype;
172
173
7.47k
#define FLAG_COMPLEX 0x8
174
#define FLAG_GLOBAL  0x4
175
34.7k
#define FLAG_LOGICAL 0x2
176
177
static const QuantumType z2qtype[4] = {GrayQuantum, BlueQuantum, GreenQuantum, RedQuantum};
178
179
static void InsertComplexDoubleRow(Image *image,double *p,int y,double MinVal,
180
  double MaxVal,ExceptionInfo *exception)
181
11.0k
{
182
11.0k
  double f;
183
11.0k
  int x;
184
11.0k
  Quantum *q;
185
186
11.0k
  if (MinVal >= 0)
187
10.3k
    MinVal = -1;
188
11.0k
  if (MaxVal <= 0)
189
9.22k
    MaxVal = 1;
190
191
11.0k
  q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
192
11.0k
  if (q == (Quantum *) NULL)
193
0
    return;
194
8.26M
  for (x = 0; x < (ssize_t) image->columns; x++)
195
8.25M
  {
196
8.25M
    if (*p > 0)
197
721k
      {
198
721k
        f=(*p/MaxVal)*((double) QuantumRange-(double) GetPixelRed(image,q));
199
721k
        if (IsNaN(f) != 0)      
200
1.19k
          f=0.0;
201
721k
        if ((f+(double) GetPixelRed(image,q)) >= (double) QuantumRange)
202
13.4k
          SetPixelRed(image,QuantumRange,q);
203
708k
        else
204
708k
          SetPixelRed(image,GetPixelRed(image,q)+ClampToQuantum(f),q);
205
721k
        f=(double) GetPixelGreen(image,q)-f/2.0;
206
721k
        if (IsNaN(f) != 0)      
207
130k
          f=0.0;
208
721k
        if (f <= 0.0)
209
656k
          {
210
656k
            SetPixelGreen(image,0,q);
211
656k
            SetPixelBlue(image,0,q);
212
656k
          }
213
65.2k
        else
214
65.2k
          {
215
65.2k
            SetPixelBlue(image,ClampToQuantum(f),q);
216
65.2k
            SetPixelGreen(image,ClampToQuantum(f),q);
217
65.2k
          }
218
721k
      }
219
8.25M
    if (*p < 0)
220
323k
      {
221
323k
        f=(*p/MinVal)*(Quantum) (QuantumRange-GetPixelBlue(image,q));
222
323k
        if (IsNaN(f) != 0)      
223
402
          f=0.0;
224
323k
        if ((f+(double) GetPixelBlue(image,q)) >= (double) QuantumRange)
225
3.81k
          SetPixelBlue(image,QuantumRange,q);
226
319k
        else
227
319k
          SetPixelBlue(image,GetPixelBlue(image,q)+ClampToQuantum(f),q);
228
323k
        f=GetPixelGreen(image,q)-f/2.0;
229
323k
        if (f <= 0.0)
230
183k
          {
231
183k
            SetPixelRed(image,0,q);
232
183k
            SetPixelGreen(image,0,q);
233
183k
          }
234
140k
        else
235
140k
          {
236
140k
            SetPixelRed(image,ClampToQuantum(f),q);
237
140k
            SetPixelGreen(image,ClampToQuantum(f),q);
238
140k
          }
239
323k
      }
240
8.25M
    p++;
241
8.25M
    q++;
242
8.25M
  }
243
11.0k
  if (!SyncAuthenticPixels(image,exception))
244
0
    return;
245
11.0k
  return;
246
11.0k
}
247
248
static void InsertComplexFloatRow(Image *image,float *p,int y,double MinVal,
249
  double MaxVal,ExceptionInfo *exception)
250
14.8k
{
251
14.8k
  double f;
252
14.8k
  int x;
253
14.8k
  Quantum *q;
254
255
14.8k
  if (MinVal >= 0)
256
14.3k
    MinVal = -1;
257
14.8k
  if (MaxVal <= 0)
258
13.4k
    MaxVal = 1;
259
260
14.8k
  q = QueueAuthenticPixels(image, 0, y, image->columns, 1,exception);
261
14.8k
  if (q == (Quantum *) NULL)
262
0
    return;
263
11.4M
  for (x = 0; x < (ssize_t) image->columns; x++)
264
11.4M
  {
265
11.4M
    if (*p > 0)
266
2.03M
      {
267
2.03M
        f=((double) *p/MaxVal)*((double) QuantumRange-(double)
268
2.03M
          GetPixelRed(image,q));
269
2.03M
        if (IsNaN(f) != 0)      
270
1.28k
          f=0.0;
271
2.03M
        if ((f+GetPixelRed(image,q)) < QuantumRange)
272
929k
          SetPixelRed(image,GetPixelRed(image,q)+ClampToQuantum(f),q);
273
1.10M
        else
274
1.10M
          SetPixelRed(image,QuantumRange,q);
275
2.03M
        f/=2.0;
276
2.03M
        if (f < GetPixelGreen(image,q))
277
1.73M
          {
278
1.73M
            SetPixelBlue(image,GetPixelBlue(image,q)-ClampToQuantum(f),q);
279
1.73M
            SetPixelGreen(image,GetPixelBlue(image,q),q);
280
1.73M
          }
281
304k
        else
282
304k
          {
283
304k
            SetPixelGreen(image,0,q);
284
304k
            SetPixelBlue(image,0,q);
285
304k
          }
286
2.03M
      }
287
11.4M
    if (*p < 0)
288
347k
      {
289
347k
        f=(*p/MaxVal)*(Quantum) (QuantumRange-GetPixelBlue(image,q));
290
347k
        if (IsNaN(f) != 0)      
291
577
          f=0.0;
292
347k
        if ((f+GetPixelBlue(image,q)) < QuantumRange)
293
201k
          SetPixelBlue(image,GetPixelBlue(image,q)+ClampToQuantum(f),q);
294
146k
        else
295
146k
          SetPixelBlue(image,QuantumRange,q);
296
347k
        f/=2.0;
297
347k
        if (f < GetPixelGreen(image,q))
298
151k
          {
299
151k
            SetPixelRed(image,GetPixelRed(image,q)-ClampToQuantum(f),q);
300
151k
            SetPixelGreen(image,GetPixelRed(image,q),q);
301
151k
          }
302
196k
        else
303
196k
          {
304
196k
            SetPixelGreen(image,0,q);
305
196k
            SetPixelRed(image,0,q);
306
196k
          }
307
347k
      }
308
11.4M
    p++;
309
11.4M
    q++;
310
11.4M
  }
311
14.8k
  if (!SyncAuthenticPixels(image,exception))
312
0
    return;
313
14.8k
  return;
314
14.8k
}
315
316
317
/************** READERS ******************/
318
319
/* This function reads one block of floats*/
320
static void ReadBlobFloatsLSB(Image * image, size_t len, float *data)
321
1.49k
{
322
2.79k
  while (len >= 4)
323
1.29k
  {
324
1.29k
    *data++ = ReadBlobFloat(image);
325
1.29k
    len -= sizeof(float);
326
1.29k
  }
327
1.49k
  if (len > 0)
328
935
    (void) SeekBlob(image, (MagickOffsetType) len, SEEK_CUR);
329
1.49k
}
330
331
static void ReadBlobFloatsMSB(Image * image, size_t len, float *data)
332
5.29k
{
333
13.3k
  while (len >= 4)
334
8.09k
  {
335
8.09k
    *data++ = ReadBlobFloat(image);
336
8.09k
    len -= sizeof(float);
337
8.09k
  }
338
5.29k
  if (len > 0)
339
2.07k
    (void) SeekBlob(image, (MagickOffsetType) len, SEEK_CUR);
340
5.29k
}
341
342
/* This function reads one block of doubles*/
343
static void ReadBlobDoublesLSB(Image * image, size_t len, double *data)
344
1.97k
{
345
3.00k
  while (len >= 8)
346
1.03k
  {
347
1.03k
    *data++ = ReadBlobDouble(image);
348
1.03k
    len -= sizeof(double);
349
1.03k
  }
350
1.97k
  if (len > 0)
351
1.25k
    (void) SeekBlob(image, (MagickOffsetType) len, SEEK_CUR);
352
1.97k
}
353
354
static void ReadBlobDoublesMSB(Image * image, size_t len, double *data)
355
4.90k
{
356
10.3k
  while (len >= 8)
357
5.43k
  {
358
5.43k
    *data++ = ReadBlobDouble(image);
359
5.43k
    len -= sizeof(double);
360
5.43k
  }
361
4.90k
  if (len > 0)
362
2.41k
    (void) SeekBlob(image, (MagickOffsetType) len, SEEK_CUR);
363
4.90k
}
364
365
/* Calculate minimum and maximum from a given block of data */
366
static void CalcMinMax(Image *image, int endian_indicator, ssize_t SizeX, ssize_t SizeY, size_t CellType, unsigned ldblk, void *BImgBuff, double *Min, double *Max)
367
1.39k
{
368
1.39k
MagickOffsetType filepos;
369
1.39k
ssize_t i, x;
370
1.39k
void (*ReadBlobDoublesXXX)(Image * image, size_t len, double *data);
371
1.39k
void (*ReadBlobFloatsXXX)(Image * image, size_t len, float *data);
372
1.39k
double *dblrow;
373
1.39k
float *fltrow;
374
375
1.39k
  if (endian_indicator == LSBEndian)
376
0
  {
377
0
    ReadBlobDoublesXXX = ReadBlobDoublesLSB;
378
0
    ReadBlobFloatsXXX = ReadBlobFloatsLSB;
379
0
  }
380
1.39k
  else    /* MI */
381
1.39k
  {
382
1.39k
    ReadBlobDoublesXXX = ReadBlobDoublesMSB;
383
1.39k
    ReadBlobFloatsXXX = ReadBlobFloatsMSB;
384
1.39k
  }
385
386
1.39k
  filepos = TellBlob(image);     /* Please note that file seeking occurs only in the case of doubles */
387
10.3k
  for (i = 0; i < SizeY; i++)
388
8.91k
  {
389
8.91k
    if (CellType==miDOUBLE)
390
4.26k
    {
391
4.26k
      ReadBlobDoublesXXX(image, ldblk, (double *)BImgBuff);
392
4.26k
      dblrow = (double *)BImgBuff;
393
4.26k
      if (i == 0)
394
676
      {
395
676
        *Min = *Max = *dblrow;
396
676
      }
397
13.8k
      for (x = 0; x < SizeX; x++)
398
9.56k
      {
399
9.56k
        if (*Min > *dblrow)
400
784
          *Min = *dblrow;
401
9.56k
        if (*Max < *dblrow)
402
537
          *Max = *dblrow;
403
9.56k
        dblrow++;
404
9.56k
      }
405
4.26k
    }
406
8.91k
    if (CellType==miSINGLE)
407
4.65k
    {
408
4.65k
      ReadBlobFloatsXXX(image, ldblk, (float *)BImgBuff);
409
4.65k
      fltrow = (float *)BImgBuff;
410
4.65k
      if (i == 0)
411
715
      {
412
715
        *Min = *Max = *fltrow;
413
715
      }
414
14.1k
    for (x = 0; x < (ssize_t) SizeX; x++)
415
9.50k
      {
416
9.50k
        if (*Min > *fltrow)
417
487
          *Min = *fltrow;
418
9.50k
        if (*Max < *fltrow)
419
491
          *Max = *fltrow;
420
9.50k
        fltrow++;
421
9.50k
      }
422
4.65k
    }
423
8.91k
  }
424
1.39k
  (void) SeekBlob(image, (MagickOffsetType) filepos, SEEK_SET);
425
1.39k
}
426
427
428
static void FixSignedValues(const Image *image,Quantum *q, ssize_t y)
429
25.7k
{
430
9.74M
  while(y-->0)
431
9.72M
  {
432
     /* Please note that negative values will overflow
433
        Q=8; QuantumRange=255: <0;127> + 127+1 = <128; 255>
434
           <-1;-128> + 127+1 = <0; 127> */
435
9.72M
    SetPixelRed(image,GetPixelRed(image,q)+QuantumRange/2+1,q);
436
9.72M
    SetPixelGreen(image,GetPixelGreen(image,q)+QuantumRange/2+1,q);
437
9.72M
    SetPixelBlue(image,GetPixelBlue(image,q)+QuantumRange/2+1,q);
438
9.72M
    q++;
439
9.72M
  }
440
25.7k
}
441
442
443
/** Fix whole row of logical/binary data. It means pack it. */
444
static void FixLogical(unsigned char *Buff,ssize_t ldblk)
445
9.23k
{
446
9.23k
unsigned char mask=128;
447
9.23k
unsigned char *BuffL = Buff;
448
9.23k
unsigned char val = 0;
449
450
9.23k
  if (ldblk == 0)
451
0
    return;
452
453
36.4k
  while(ldblk-->0)
454
27.2k
  {
455
27.2k
    if(*Buff++ != 0)
456
16.0k
      val |= mask;
457
458
27.2k
    mask >>= 1;
459
27.2k
    if(mask==0)
460
2.14k
    {
461
2.14k
      *BuffL++ = val;
462
2.14k
      val = 0;
463
2.14k
      mask = 128;
464
2.14k
    }
465
466
27.2k
  }
467
9.23k
  *BuffL = val;
468
9.23k
}
469
470
#if defined(MAGICKCORE_ZLIB_DELEGATE)
471
static voidpf AcquireZIPMemory(voidpf context,unsigned int items,
472
  unsigned int size)
473
1.32k
{
474
1.32k
  (void) context;
475
1.32k
  return((voidpf) AcquireQuantumMemory(items,size));
476
1.32k
}
477
478
static void RelinquishZIPMemory(voidpf context,voidpf memory)
479
1.32k
{
480
1.32k
  (void) context;
481
1.32k
  memory=RelinquishMagickMemory(memory);
482
1.32k
}
483
#endif
484
485
#if defined(MAGICKCORE_ZLIB_DELEGATE)
486
/** This procedure decompreses an image block for a new MATLAB format. */
487
static Image *decompress_block(Image *orig,unsigned int *Size,
488
  ImageInfo *clone_info,ExceptionInfo *exception)
489
24.7k
{
490
491
24.7k
Image *image2;
492
24.7k
void *cache_block, *decompress_block;
493
24.7k
z_stream zip_info;
494
24.7k
FILE *mat_file;
495
24.7k
ssize_t magick_size;
496
24.7k
size_t extent;
497
24.7k
int file;
498
499
24.7k
MagickBooleanType status;
500
24.7k
int zip_status;
501
24.7k
ssize_t total_size = 0;
502
24.7k
size_t compressed_total = 0;
503
24.7k
static const size_t MAX_ABSOLUTE_SIZE = 512UL * 1024UL * 1024UL; /* 512 MB */
504
24.7k
static const size_t MAX_EXPANSION_RATIO = 64; /* 64x expansion allowed */
505
506
24.7k
  if (clone_info == NULL)
507
0
    return NULL;
508
24.7k
  if (clone_info->file)    /* Close file opened from previous transaction. */
509
0
    {
510
0
      fclose(clone_info->file);
511
0
      clone_info->file = NULL;
512
0
      (void) remove_utf8(clone_info->filename);
513
0
    }
514
515
24.7k
  cache_block=AcquireQuantumMemory((size_t) (*Size < MagickMinBufferExtent) ?
516
24.7k
    *Size: MagickMinBufferExtent,sizeof(unsigned char *));
517
24.7k
  if (cache_block == NULL)
518
464
    return NULL;
519
24.3k
  decompress_block=AcquireQuantumMemory((size_t) (4096),
520
24.3k
    sizeof(unsigned char *));
521
24.3k
  if (decompress_block == NULL)
522
0
    {
523
0
      RelinquishMagickMemory(cache_block);
524
0
      return NULL;
525
0
    }
526
24.3k
  mat_file=0;
527
24.3k
  file=AcquireUniqueFileResource(clone_info->filename);
528
24.3k
  if (file != -1)
529
1.05k
    mat_file = fdopen(file,"ab+");
530
24.3k
  if(!mat_file)
531
23.2k
  {
532
23.2k
    RelinquishMagickMemory(cache_block);
533
23.2k
    RelinquishMagickMemory(decompress_block);
534
23.2k
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Cannot create file stream for decompressed image");
535
23.2k
    return NULL;
536
23.2k
  }
537
538
1.05k
  (void) memset(&zip_info,0,sizeof(zip_info));
539
1.05k
  zip_info.zalloc=AcquireZIPMemory;
540
1.05k
  zip_info.zfree=RelinquishZIPMemory;
541
1.05k
  zip_info.opaque=(voidpf) NULL;
542
1.05k
  zip_status=inflateInit(&zip_info);
543
1.05k
  if (zip_status != Z_OK)
544
0
    {
545
0
      RelinquishMagickMemory(cache_block);
546
0
      RelinquishMagickMemory(decompress_block);
547
0
      (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
548
0
        "UnableToUncompressImage","`%s'",clone_info->filename);
549
0
      (void) fclose(mat_file);
550
0
      RelinquishUniqueFileResource(clone_info->filename);
551
0
      return(NULL);
552
0
    }
553
1.05k
  zip_info.avail_in=0;
554
1.05k
  zip_info.total_out=0;
555
1.63k
  while ((*Size > 0) && (EOFBlob(orig) == 0))
556
1.05k
  {
557
1.05k
    magick_size=ReadBlob(orig,(*Size < MagickMinBufferExtent) ? *Size :
558
1.05k
      MagickMinBufferExtent,(unsigned char *) cache_block);
559
1.05k
    if (magick_size == 0)
560
44
      break;
561
1.01k
    zip_info.next_in=(Bytef *) cache_block;
562
1.01k
    zip_info.avail_in=(uInt) magick_size;
563
1.01k
    compressed_total+=magick_size;
564
1.63k
    while (zip_info.avail_in > 0)
565
1.04k
    {
566
1.04k
      size_t chunk_size = 0;
567
1.04k
      zip_info.avail_out=4096;
568
1.04k
      zip_info.next_out=(Bytef *) decompress_block;
569
1.04k
      zip_status=inflate(&zip_info,Z_NO_FLUSH);
570
1.04k
      if ((zip_status != Z_OK) && (zip_status != Z_STREAM_END))
571
413
        break;
572
633
      chunk_size=4096-zip_info.avail_out;
573
633
      extent=fwrite(decompress_block,1,chunk_size,mat_file);
574
633
      if (extent != chunk_size)
575
0
        {
576
0
          zip_status=Z_DATA_ERROR;
577
0
          break;
578
0
        }
579
633
      total_size+=chunk_size;
580
633
      if (compressed_total > 0)
581
633
        {
582
633
          if ((total_size > (ssize_t) MAX_ABSOLUTE_SIZE) ||
583
633
              (total_size > (ssize_t) (compressed_total*MAX_EXPANSION_RATIO)))
584
3
            {
585
3
              zip_status=Z_DATA_ERROR;
586
3
              break;
587
3
            }
588
633
        }
589
630
      if (zip_status == Z_STREAM_END)
590
11
        goto DblBreak;
591
630
    }
592
1.00k
    if ((zip_status != Z_OK) && (zip_status != Z_STREAM_END))
593
416
      break;
594
584
    *Size-=(unsigned int) magick_size;
595
584
  }
596
1.05k
DblBreak:
597
598
1.05k
  inflateEnd(&zip_info);
599
1.05k
  if (fseek(mat_file,0,SEEK_SET) != 0)
600
0
    (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
601
0
      "UnableToCreateTemporaryFile","`%s'",clone_info->filename);
602
1.05k
  RelinquishMagickMemory(cache_block);
603
1.05k
  RelinquishMagickMemory(decompress_block);
604
1.05k
  *Size = (unsigned int) total_size;
605
606
1.05k
  clone_info->file=mat_file;
607
1.05k
  if( (image2 = AcquireImage(clone_info,exception))==NULL ) goto EraseFile;
608
1.05k
  image2->columns=0;
609
1.05k
  image2->rows=0;
610
1.05k
  status = OpenBlob(clone_info,image2,ReadBinaryBlobMode,exception);
611
1.05k
  if (status == MagickFalse)
612
0
  {
613
0
    DeleteImageFromList(&image2);
614
0
EraseFile:
615
0
    fclose(clone_info->file);
616
0
    clone_info->file = NULL;
617
0
    RelinquishUniqueFileResource(clone_info->filename);
618
0
    return NULL;
619
0
  }
620
1.05k
  return(image2);
621
1.05k
}
622
#endif
623
624
static Image *ReadMATImageV4(const ImageInfo *image_info,Image *image,
625
  ExceptionInfo *exception)
626
1.59k
{
627
1.59k
  typedef struct {
628
1.59k
    unsigned char Type[4];
629
1.59k
    unsigned int nRows;
630
1.59k
    unsigned int nCols;
631
1.59k
    unsigned int imagf;
632
1.59k
    unsigned int nameLen;
633
1.59k
  } MAT4_HDR;
634
635
1.59k
  EndianType
636
1.59k
    endian;
637
638
1.59k
  Image
639
1.59k
    *rotated_image;
640
641
1.59k
  MagickBooleanType
642
1.59k
    status;
643
644
1.59k
  MAT4_HDR
645
1.59k
    HDR;
646
647
1.59k
  QuantumInfo
648
1.59k
    *quantum_info;
649
650
1.59k
  QuantumFormatType
651
1.59k
    format_type;
652
653
1.59k
  ssize_t
654
1.59k
    count,
655
1.59k
    i,
656
1.59k
    ldblk,
657
1.59k
    y;
658
659
1.59k
  unsigned char
660
1.59k
    *pixels;
661
662
1.59k
  unsigned int
663
1.59k
    depth;
664
665
1.59k
  quantum_info=(QuantumInfo *) NULL;
666
1.59k
  (void) SeekBlob(image,0,SEEK_SET);
667
1.59k
  status=MagickTrue;
668
2.27k
  while (EOFBlob(image) == MagickFalse)
669
2.27k
  {
670
    /*
671
     Object parser loop.
672
    */
673
2.27k
    ldblk=ReadBlobLSBLong(image);
674
2.27k
    if(EOFBlob(image)) break;
675
2.14k
    if ((ldblk > 9999) || (ldblk < 0))
676
741
      break;
677
1.40k
    HDR.Type[3]=(unsigned char) (ldblk % 10); ldblk /= 10;  /* T digit */
678
1.40k
    HDR.Type[2]=(unsigned char) (ldblk % 10); ldblk /= 10;  /* P digit */
679
1.40k
    HDR.Type[1]=(unsigned char) (ldblk % 10); ldblk /= 10;  /* O digit */
680
1.40k
    HDR.Type[0]=(unsigned char) (ldblk);        /* M digit */
681
1.40k
    if (HDR.Type[3] != 0)
682
20
      break;  /* Data format */
683
1.38k
    if (HDR.Type[2] != 0)
684
11
      break;  /* Always 0 */
685
1.37k
    if (HDR.Type[0] == 0)
686
587
      {
687
587
        HDR.nRows=ReadBlobLSBLong(image);
688
587
        HDR.nCols=ReadBlobLSBLong(image);
689
587
        HDR.imagf=ReadBlobLSBLong(image);
690
587
        HDR.nameLen=ReadBlobLSBLong(image);
691
587
        endian=LSBEndian;
692
587
      }
693
786
    else
694
786
      {
695
786
        HDR.nRows=ReadBlobMSBLong(image);
696
786
        HDR.nCols=ReadBlobMSBLong(image);
697
786
        HDR.imagf=ReadBlobMSBLong(image);
698
786
        HDR.nameLen=ReadBlobMSBLong(image);
699
786
        endian=MSBEndian;
700
786
      }
701
1.37k
    if ((HDR.imagf != 0) && (HDR.imagf != 1))
702
76
      break;
703
1.29k
    if (HDR.nameLen > 0xFFFF)
704
38
      return(DestroyImageList(image));
705
2.98M
    for (i=0; i < (ssize_t) HDR.nameLen; i++)
706
2.98M
    {
707
2.98M
      int
708
2.98M
        byte;
709
710
      /*
711
        Skip matrix name.
712
      */
713
2.98M
      byte=ReadBlobByte(image);
714
2.98M
      if (byte == EOF)
715
267
        {
716
267
          ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
717
267
            image->filename);
718
267
          break;
719
267
        }
720
2.98M
    }
721
1.25k
    image->columns=(size_t) HDR.nRows;
722
1.25k
    image->rows=(size_t) HDR.nCols;
723
1.25k
    if ((image->columns == 0) || (image->rows == 0))
724
46
      return(DestroyImageList(image));
725
1.21k
    if (image_info->ping != MagickFalse)
726
0
      {
727
0
        Swap(image->columns,image->rows);
728
0
        if(HDR.imagf==1) ldblk *= 2;
729
0
        SeekBlob(image, (MagickOffsetType) HDR.nCols*ldblk, SEEK_CUR);
730
0
        if ((image->columns == 0) || (image->rows == 0))
731
0
          return(image->previous == (Image *) NULL ? DestroyImageList(image)
732
0
            : image);
733
0
        goto skip_reading_current;
734
0
      }
735
1.21k
    if ((image->columns > GetBlobSize(image)) ||
736
996
        (image->rows > GetBlobSize(image)))
737
932
      ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
738
932
    status=SetImageExtent(image,image->columns,image->rows,exception);
739
932
    if (status == MagickFalse)
740
15
      return(DestroyImageList(image));
741
917
    (void) SetImageBackgroundColor(image,exception);
742
917
    (void) SetImageColorspace(image,GRAYColorspace,exception);
743
917
    quantum_info=AcquireQuantumInfo(image_info,image);
744
917
    if (quantum_info == (QuantumInfo *) NULL)
745
0
      return(DestroyImageList(image));
746
917
    switch(HDR.Type[1])
747
917
    {
748
188
      case 0:
749
188
        format_type=FloatingPointQuantumFormat;
750
188
        depth=64;
751
188
        break;
752
54
      case 1:
753
54
        format_type=FloatingPointQuantumFormat;
754
54
        depth=32;
755
54
        break;
756
34
      case 2:
757
34
        format_type=UnsignedQuantumFormat;
758
34
        depth=16;
759
34
        break;
760
12
      case 3:
761
12
        format_type=SignedQuantumFormat;
762
12
        depth=16;
763
12
        break;
764
142
      case 4:
765
142
        format_type=UnsignedQuantumFormat;
766
142
        depth=8;
767
142
        break;
768
487
      default:
769
487
        format_type=UnsignedQuantumFormat;
770
487
        depth=8;
771
487
        break;
772
917
    }
773
917
    image->depth=depth;
774
917
    if (HDR.Type[0] != 0)
775
718
      SetQuantumEndian(image,quantum_info,MSBEndian);
776
917
    status=SetQuantumFormat(image,quantum_info,format_type);
777
917
    if (status != MagickFalse)
778
917
      status=SetQuantumDepth(image,quantum_info,depth);
779
917
    if (status != MagickFalse)
780
917
      status=SetQuantumEndian(image,quantum_info,endian);
781
917
    if (status == MagickFalse)
782
0
      {
783
0
        quantum_info=DestroyQuantumInfo(quantum_info);
784
0
        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
785
0
      }
786
917
    SetQuantumScale(quantum_info,1.0);
787
917
    pixels=(unsigned char *) GetQuantumPixels(quantum_info);
788
79.0k
    for (y=0; y < (ssize_t) image->rows; y++)
789
78.1k
    {
790
78.1k
      Quantum
791
78.1k
        *magick_restrict q;
792
793
78.1k
      count=ReadBlob(image,depth/8*image->columns,(char *) pixels);
794
78.1k
      if (count == -1)
795
0
        break;
796
78.1k
      q=QueueAuthenticPixels(image,0,(ssize_t) image->rows-y-1,image->columns,1,
797
78.1k
        exception);
798
78.1k
      if (q == (Quantum *) NULL)
799
0
        break;
800
78.1k
      (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
801
78.1k
        GrayQuantum,pixels,exception);
802
78.1k
      if ((HDR.Type[1] == 2) || (HDR.Type[1] == 3))
803
6.29k
        FixSignedValues(image,q,(int) image->columns);
804
78.1k
      if (SyncAuthenticPixels(image,exception) == MagickFalse)
805
0
        break;
806
78.1k
      if (image->previous == (Image *) NULL)
807
66.7k
        {
808
66.7k
          status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
809
66.7k
            image->rows);
810
66.7k
          if (status == MagickFalse)
811
0
            break;
812
66.7k
        }
813
78.1k
    }
814
917
    if (HDR.imagf == 1)
815
21.4k
      for (y=0; y < (ssize_t) image->rows; y++)
816
21.2k
      {
817
        /*
818
          Read complex pixels.
819
        */
820
21.2k
        count=ReadBlob(image,depth/8*image->columns,(char *) pixels);
821
21.2k
        if (count == -1)
822
0
          break;
823
21.2k
        if (HDR.Type[1] == 0)
824
8.47k
          InsertComplexDoubleRow(image,(double *) pixels,(int) y,0,0,exception);
825
12.7k
        else
826
12.7k
          InsertComplexFloatRow(image,(float *) pixels,(int) y,0,0,exception);
827
21.2k
      }
828
917
    quantum_info=DestroyQuantumInfo(quantum_info);
829
917
    if (EOFBlob(image) != MagickFalse)
830
239
      {
831
239
        ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
832
239
          image->filename);
833
239
        break;
834
239
      }
835
678
    rotated_image=RotateImage(image,90.0,exception);
836
678
    if (rotated_image != (Image *) NULL)
837
678
      {
838
678
        rotated_image->page.x=0;
839
678
        rotated_image->page.y=0;
840
678
        rotated_image->colors = image->colors;
841
678
        DestroyBlob(rotated_image);
842
678
        rotated_image->blob=ReferenceBlob(image->blob);
843
678
        ReplaceImageInList(&image,rotated_image);
844
678
        image=rotated_image;
845
678
      }
846
    /*
847
      Proceed to next image.
848
    */
849
678
    if (image_info->number_scenes != 0)
850
0
      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
851
0
        break;
852
    /*
853
      Allocate next image structure.
854
    */
855
678
skip_reading_current:
856
678
    if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
857
0
      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
858
0
        break;
859
678
    AcquireNextImage(image_info,image,exception);
860
678
    if (GetNextImageInList(image) == (Image *) NULL)
861
0
      {
862
0
        status=MagickFalse;
863
0
        break;
864
0
      }
865
678
    image=SyncNextImageInList(image);
866
678
    status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
867
678
      GetBlobSize(image));
868
678
    if (status == MagickFalse)
869
0
      break;
870
678
  }
871
1.21k
  if (CloseBlob(image) == MagickFalse)
872
235
    status=MagickFalse;
873
1.21k
  if (status == MagickFalse)
874
235
    return(DestroyImageList(image));
875
979
  return(GetFirstImageInList(image));
876
1.21k
}
877

878
/*
879
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
880
%                                                                             %
881
%                                                                             %
882
%                                                                             %
883
%   R e a d M A T L A B i m a g e                                             %
884
%                                                                             %
885
%                                                                             %
886
%                                                                             %
887
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
888
%
889
%  ReadMATImage() reads an MAT X image file and returns it.  It
890
%  allocates the memory necessary for the new Image structure and returns a
891
%  pointer to the new image.
892
%
893
%  The format of the ReadMATImage method is:
894
%
895
%      Image *ReadMATImage(const ImageInfo *image_info,ExceptionInfo *exception)
896
%
897
%  A description of each parameter follows:
898
%
899
%    o image:  Method ReadMATImage returns a pointer to the image after
900
%      reading. A null image is returned if there is a memory shortage or if
901
%      the image cannot be read.
902
%
903
%    o image_info: Specifies a pointer to a ImageInfo structure.
904
%
905
%    o exception: return any errors or warnings in this structure.
906
%
907
*/
908
static Image *ReadMATImage(const ImageInfo *image_info,ExceptionInfo *exception)
909
4.66k
{
910
4.66k
  Image *image, *image2=NULL,
911
4.66k
   *rotated_image;
912
4.66k
  Quantum *q;
913
914
4.66k
  unsigned int status;
915
4.66k
  MATHeader MATLAB_HDR;
916
4.66k
  size_t size;
917
4.66k
  size_t CellType;
918
4.66k
  QuantumInfo *quantum_info;
919
4.66k
  ImageInfo *clone_info;
920
4.66k
  ssize_t i;
921
4.66k
  ssize_t ldblk;
922
4.66k
  unsigned char *BImgBuff = NULL;
923
4.66k
  double MinVal, MaxVal;
924
4.66k
  unsigned z, z2;
925
4.66k
  unsigned Frames;
926
4.66k
  MagickBooleanType logging;
927
4.66k
  int sample_size;
928
4.66k
  MagickOffsetType filepos=0x80;
929
930
4.66k
  unsigned int (*ReadBlobXXXLong)(Image *image);
931
4.66k
  unsigned short (*ReadBlobXXXShort)(Image *image);
932
4.66k
  void (*ReadBlobDoublesXXX)(Image * image, size_t len, double *data);
933
4.66k
  void (*ReadBlobFloatsXXX)(Image * image, size_t len, float *data);
934
935
936
4.66k
  assert(image_info != (const ImageInfo *) NULL);
937
4.66k
  assert(image_info->signature == MagickCoreSignature);
938
4.66k
  assert(exception != (ExceptionInfo *) NULL);
939
4.66k
  assert(exception->signature == MagickCoreSignature);
940
4.66k
  logging = LogMagickEvent(CoderEvent,GetMagickModule(),"enter");
941
942
  /*
943
     Open image file.
944
   */
945
4.66k
  image = AcquireImage(image_info,exception);
946
4.66k
  image2 = (Image *) NULL;
947
948
4.66k
  status = OpenBlob(image_info, image, ReadBinaryBlobMode, exception);
949
4.66k
  if (status == MagickFalse)
950
0
    {
951
0
      image=DestroyImageList(image);
952
0
      return((Image *) NULL);
953
0
    }
954
  /*
955
     Read MATLAB image.
956
   */
957
4.66k
  quantum_info=(QuantumInfo *) NULL;
958
4.66k
  clone_info=(ImageInfo *) NULL;
959
4.66k
  if (ReadBlob(image,124,(unsigned char *) &MATLAB_HDR.identific) != 124)
960
4.02k
    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
961
4.02k
  if (strncmp(MATLAB_HDR.identific,"MATLAB",6) != 0)
962
1.59k
    {
963
1.59k
      image=ReadMATImageV4(image_info,image,exception);
964
1.59k
      if (image == NULL)
965
615
        {
966
615
          if ((image != image2) && (image2 != (Image *) NULL))
967
0
            image2=DestroyImage(image2);
968
615
          if (clone_info != (ImageInfo *) NULL)
969
0
            clone_info=DestroyImageInfo(clone_info);
970
615
          return((Image *) NULL);
971
615
        }
972
979
      goto END_OF_READING;
973
1.59k
    }
974
2.42k
  MATLAB_HDR.Version = ReadBlobLSBShort(image);
975
2.42k
  if(ReadBlob(image,2,(unsigned char *) &MATLAB_HDR.EndianIndicator) != 2)
976
2.41k
    ThrowReaderException(CorruptImageError,"ImproperImageHeader");
977
978
2.41k
  if (logging)
979
0
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),"  Endian %c%c",
980
0
      MATLAB_HDR.EndianIndicator[0],MATLAB_HDR.EndianIndicator[1]);
981
2.41k
  if (!strncmp(MATLAB_HDR.EndianIndicator, "IM", 2))
982
1.23k
  {
983
1.23k
    ReadBlobXXXLong = ReadBlobLSBLong;
984
1.23k
    ReadBlobXXXShort = ReadBlobLSBShort;
985
1.23k
    ReadBlobDoublesXXX = ReadBlobDoublesLSB;
986
1.23k
    ReadBlobFloatsXXX = ReadBlobFloatsLSB;
987
1.23k
    image->endian = LSBEndian;
988
1.23k
  }
989
1.17k
  else if (!strncmp(MATLAB_HDR.EndianIndicator, "MI", 2))
990
1.15k
  {
991
1.15k
    ReadBlobXXXLong = ReadBlobMSBLong;
992
1.15k
    ReadBlobXXXShort = ReadBlobMSBShort;
993
1.15k
    ReadBlobDoublesXXX = ReadBlobDoublesMSB;
994
1.15k
    ReadBlobFloatsXXX = ReadBlobFloatsMSB;
995
1.15k
    image->endian = MSBEndian;
996
1.15k
  }
997
28
  else
998
28
    {
999
581
MATLAB_KO:
1000
581
      if ((image != image2) && (image2 != (Image *) NULL))
1001
7
        image2=DestroyImage(image2);
1002
581
      if (clone_info != (ImageInfo *) NULL)
1003
382
        clone_info=DestroyImageInfo(clone_info);
1004
581
      ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1005
0
    }
1006
1007
2.39k
  filepos = TellBlob(image);
1008
32.4k
  while(filepos < (MagickOffsetType) GetBlobSize(image) && !EOFBlob(image)) /* object parser loop */
1009
31.7k
  {
1010
31.7k
    Frames = 1;
1011
31.7k
    if(filepos > (MagickOffsetType) GetBlobSize(image) || filepos < 0)
1012
0
      break;
1013
31.7k
    if(SeekBlob(image,(MagickOffsetType) filepos,SEEK_SET) != filepos) break;
1014
    /* printf("pos=%X\n",TellBlob(image)); */
1015
1016
31.7k
    MATLAB_HDR.DataType = ReadBlobXXXLong(image);
1017
31.7k
    if(EOFBlob(image)) break;
1018
31.6k
    MATLAB_HDR.ObjectSize = ReadBlobXXXLong(image);
1019
31.6k
    if(EOFBlob(image)) break;
1020
31.5k
    if((MagickSizeType) (MATLAB_HDR.ObjectSize+filepos) >= GetBlobSize(image))
1021
256
      goto MATLAB_KO;
1022
31.3k
    filepos += (MagickOffsetType) MATLAB_HDR.ObjectSize + 4 + 4;
1023
1024
31.3k
    if (clone_info != (ImageInfo *) NULL)
1025
23.2k
      clone_info=DestroyImageInfo(clone_info);
1026
31.3k
    clone_info=CloneImageInfo(image_info);
1027
31.3k
    if ((image != image2) && (image2 != (Image *) NULL))
1028
0
      image2=DestroyImage(image2);
1029
31.3k
    image2 = image;
1030
31.3k
#if defined(MAGICKCORE_ZLIB_DELEGATE)
1031
31.3k
    if(MATLAB_HDR.DataType == miCOMPRESSED)
1032
24.7k
    {
1033
24.7k
      image2 = decompress_block(image,&MATLAB_HDR.ObjectSize,clone_info,exception);
1034
24.7k
      if(image2==NULL) continue;
1035
1.05k
      MATLAB_HDR.DataType = ReadBlobXXXLong(image2); /* replace compressed object type. */
1036
1.05k
    }
1037
7.59k
#endif
1038
1039
7.59k
    if (MATLAB_HDR.DataType != miMATRIX)
1040
5.07k
      {
1041
5.07k
        clone_info=DestroyImageInfo(clone_info);
1042
5.07k
#if defined(MAGICKCORE_ZLIB_DELEGATE)
1043
5.07k
        if (image2 != image)
1044
1.02k
          DeleteImageFromList(&image2);
1045
5.07k
#endif
1046
5.07k
        continue;  /* skip another objects. */
1047
5.07k
      }
1048
1049
2.52k
    MATLAB_HDR.unknown1 = ReadBlobXXXLong(image2);
1050
2.52k
    MATLAB_HDR.unknown2 = ReadBlobXXXLong(image2);
1051
1052
2.52k
    MATLAB_HDR.unknown5 = (unsigned short) ReadBlobXXXLong(image2);
1053
2.52k
    MATLAB_HDR.StructureClass = MATLAB_HDR.unknown5 & 0xFF;
1054
2.52k
    MATLAB_HDR.StructureFlag = (MATLAB_HDR.unknown5>>8) & 0xFF;
1055
1056
2.52k
    MATLAB_HDR.unknown3 = ReadBlobXXXLong(image2);
1057
2.52k
    if(image!=image2)
1058
33
      MATLAB_HDR.unknown4 = ReadBlobXXXLong(image2);  /* ??? don't understand why ?? */
1059
2.52k
    MATLAB_HDR.unknown4 = ReadBlobXXXLong(image2);
1060
2.52k
    MATLAB_HDR.DimFlag = ReadBlobXXXLong(image2);
1061
2.52k
    MATLAB_HDR.SizeX = ReadBlobXXXLong(image2);
1062
2.52k
    MATLAB_HDR.SizeY = ReadBlobXXXLong(image2);
1063
1064
1065
2.52k
    switch(MATLAB_HDR.DimFlag)
1066
2.52k
    {
1067
1.24k
      case  8: z2=z=1; break;      /* 2D matrix*/
1068
93
      case 12: z2=z = ReadBlobXXXLong(image2);  /* 3D matrix RGB*/
1069
93
           (void) ReadBlobXXXLong(image2);
1070
93
         if(z!=3)
1071
41
           {
1072
41
             if (clone_info != (ImageInfo *) NULL)
1073
41
               clone_info=DestroyImageInfo(clone_info);
1074
41
             if ((image != image2) && (image2 != (Image *) NULL))
1075
1
               image2=DestroyImage(image2);
1076
41
             ThrowReaderException(CoderError,
1077
41
               "MultidimensionalMatricesAreNotSupported");
1078
0
           }
1079
52
         break;
1080
1.16k
      case 16: z2=z = ReadBlobXXXLong(image2);  /* 4D matrix animation */
1081
1.16k
         if(z!=3 && z!=1)
1082
40
           {
1083
40
             if (clone_info != (ImageInfo *) NULL)
1084
40
               clone_info=DestroyImageInfo(clone_info);
1085
40
             if ((image != image2) && (image2 != (Image *) NULL))
1086
1
               image2=DestroyImage(image2);
1087
40
             ThrowReaderException(CoderError,
1088
40
               "MultidimensionalMatricesAreNotSupported");
1089
0
           }
1090
1.12k
          Frames = ReadBlobXXXLong(image2);
1091
1.12k
          if (Frames == 0)
1092
11
            {
1093
11
              if (clone_info != (ImageInfo *) NULL)
1094
11
                clone_info=DestroyImageInfo(clone_info);
1095
11
              if ((image != image2) && (image2 != (Image *) NULL))
1096
0
                image2=DestroyImage(image2);
1097
11
              ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1098
0
            }
1099
1.11k
          if (AcquireMagickResource(ListLengthResource,Frames) == MagickFalse)
1100
59
            {
1101
59
              if (clone_info != (ImageInfo *) NULL)
1102
59
                clone_info=DestroyImageInfo(clone_info);
1103
59
              if ((image != image2) && (image2 != (Image *) NULL))
1104
0
                image2=DestroyImage(image2);
1105
59
              ThrowReaderException(ResourceLimitError,"ListLengthExceedsLimit");
1106
0
            }
1107
1.05k
         break;
1108
1.05k
      default:
1109
24
        if (clone_info != (ImageInfo *) NULL)
1110
24
          clone_info=DestroyImageInfo(clone_info);
1111
24
        if ((image != image2) && (image2 != (Image *) NULL))
1112
3
          image2=DestroyImage(image2);
1113
24
        ThrowReaderException(CoderError, "MultidimensionalMatricesAreNotSupported");
1114
2.52k
    }
1115
1116
2.34k
    MATLAB_HDR.Flag1 = ReadBlobXXXShort(image2);
1117
2.34k
    MATLAB_HDR.NameFlag = ReadBlobXXXShort(image2);
1118
1119
2.34k
    if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),
1120
0
          "MATLAB_HDR.StructureClass %d",MATLAB_HDR.StructureClass);
1121
2.34k
    if (MATLAB_HDR.StructureClass != mxCHAR_CLASS &&
1122
2.04k
        MATLAB_HDR.StructureClass != mxSINGLE_CLASS &&    /* float + complex float */
1123
1.89k
        MATLAB_HDR.StructureClass != mxDOUBLE_CLASS &&    /* double + complex double */
1124
1.72k
        MATLAB_HDR.StructureClass != mxINT8_CLASS &&
1125
1.37k
        MATLAB_HDR.StructureClass != mxUINT8_CLASS &&    /* uint8 + uint8 3D */
1126
1.22k
        MATLAB_HDR.StructureClass != mxINT16_CLASS &&
1127
643
        MATLAB_HDR.StructureClass != mxUINT16_CLASS &&    /* uint16 + uint16 3D */
1128
488
        MATLAB_HDR.StructureClass != mxINT32_CLASS &&
1129
319
        MATLAB_HDR.StructureClass != mxUINT32_CLASS &&    /* uint32 + uint32 3D */
1130
246
        MATLAB_HDR.StructureClass != mxINT64_CLASS &&
1131
153
        MATLAB_HDR.StructureClass != mxUINT64_CLASS)    /* uint64 + uint64 3D */
1132
19
      {
1133
19
        if ((image2 != (Image*) NULL) && (image2 != image))
1134
1
          {
1135
1
            CloseBlob(image2);
1136
1
            DeleteImageFromList(&image2);
1137
1
          }
1138
19
        if (clone_info != (ImageInfo *) NULL)
1139
19
          clone_info=DestroyImageInfo(clone_info);
1140
19
        ThrowReaderException(CoderError,"UnsupportedCellTypeInTheMatrix");
1141
0
      }
1142
1143
2.33k
    switch (MATLAB_HDR.NameFlag)
1144
2.33k
    {
1145
313
      case 0:
1146
313
        size = ReadBlobXXXLong(image2);  /* Object name string size */
1147
313
        size = 4 * (((size_t) size + 3 + 1) / 4);
1148
313
        (void) SeekBlob(image2, (MagickOffsetType) size, SEEK_CUR);
1149
313
        break;
1150
1.28k
      case 1:
1151
1.60k
      case 2:
1152
1.83k
      case 3:
1153
2.01k
      case 4:
1154
2.01k
        (void) ReadBlob(image2, 4, (unsigned char *) &size); /* Object name string */
1155
2.01k
        break;
1156
3
      default:
1157
3
        goto MATLAB_KO;
1158
2.33k
    }
1159
1160
2.32k
    CellType = ReadBlobXXXLong(image2);    /* Additional object type */
1161
2.32k
    if (logging)
1162
0
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1163
0
        "MATLAB_HDR.CellType: %.17g",(double) CellType);
1164
1165
    /* data size */
1166
2.32k
    if (ReadBlob(image2, 4, (unsigned char *) &size) != 4)
1167
174
      goto MATLAB_KO;
1168
1169
5.06k
    NEXT_FRAME:
1170
5.06k
    switch (CellType)
1171
5.06k
    {
1172
2.47k
      case miINT8:
1173
3.02k
      case miUINT8:
1174
3.02k
        sample_size = 8;
1175
3.02k
        if(MATLAB_HDR.StructureFlag & FLAG_LOGICAL)
1176
787
          image->depth = 1;
1177
2.23k
        else
1178
2.23k
          image->depth = 8;         /* Byte type cell */
1179
3.02k
        ldblk = (ssize_t) MATLAB_HDR.SizeX;
1180
3.02k
        break;
1181
121
      case miINT16:
1182
201
      case miUINT16:
1183
201
        sample_size = 16;
1184
201
        image->depth = 16;        /* Word type cell */
1185
201
        ldblk = (2 * (ssize_t) MATLAB_HDR.SizeX);
1186
201
        break;
1187
251
      case miINT32:
1188
335
      case miUINT32:
1189
335
        sample_size = 32;
1190
335
        image->depth = 32;        /* Dword type cell */
1191
335
        ldblk = (4 * (ssize_t) MATLAB_HDR.SizeX);
1192
335
        break;
1193
255
      case miINT64:
1194
347
      case miUINT64:
1195
347
        sample_size = 64;
1196
347
        image->depth = 64;        /* Qword type cell */
1197
347
        ldblk = (8 * (ssize_t) MATLAB_HDR.SizeX);
1198
347
        break;
1199
639
      case miSINGLE:
1200
639
        sample_size = 32;
1201
639
        image->depth = 32;        /* double type cell */
1202
639
        (void) SetImageOption(clone_info,"quantum:format","floating-point");
1203
639
        if (MATLAB_HDR.StructureFlag & FLAG_COMPLEX)
1204
338
          {              /* complex float type cell */
1205
338
          }
1206
639
        ldblk = (4 * (ssize_t) MATLAB_HDR.SizeX);
1207
639
        break;
1208
495
      case miDOUBLE:
1209
495
        sample_size = 64;
1210
495
        image->depth = 64;        /* double type cell */
1211
495
        (void) SetImageOption(clone_info,"quantum:format","floating-point");
1212
495
DisableMSCWarning(4127)
1213
495
        if (sizeof(double) != 8)
1214
0
RestoreMSCWarning
1215
0
          {
1216
0
            if (clone_info != (ImageInfo *) NULL)
1217
0
              clone_info=DestroyImageInfo(clone_info);
1218
0
            if ((image != image2) && (image2 != (Image *) NULL))
1219
0
              image2=DestroyImage(image2);
1220
0
            ThrowReaderException(CoderError, "IncompatibleSizeOfDouble");
1221
0
          }
1222
495
        if (MATLAB_HDR.StructureFlag & FLAG_COMPLEX)
1223
212
          {                         /* complex double type cell */
1224
212
          }
1225
495
        ldblk = (8 * (ssize_t) MATLAB_HDR.SizeX);
1226
495
        break;
1227
25
      default:
1228
25
        if ((image != image2) && (image2 != (Image *) NULL))
1229
2
          image2=DestroyImage(image2);
1230
25
        if (clone_info)
1231
25
          clone_info=DestroyImageInfo(clone_info);
1232
25
        ThrowReaderException(CoderError, "UnsupportedCellTypeInTheMatrix");
1233
5.06k
    }
1234
5.03k
    (void) sample_size;
1235
5.03k
    image->columns = MATLAB_HDR.SizeX;
1236
5.03k
    image->rows = MATLAB_HDR.SizeY;
1237
5.03k
    image->colors = (size_t) GetQuantumRange(image->depth);
1238
5.03k
    if (image->columns == 0 || image->rows == 0)
1239
5
      goto MATLAB_KO;
1240
5.03k
    if ((ldblk < 0) ||
1241
5.03k
         ((size_t) ldblk > ((size_t) ~0)/MATLAB_HDR.SizeY) ||
1242
5.01k
         (((size_t) ldblk*MATLAB_HDR.SizeY) > MATLAB_HDR.ObjectSize))
1243
115
      goto MATLAB_KO;
1244
    /* Image is gray when no complex flag is set and 2D Matrix */
1245
4.91k
    if ((MATLAB_HDR.DimFlag == 8) &&
1246
996
        ((MATLAB_HDR.StructureFlag & FLAG_COMPLEX) == 0))
1247
400
      {
1248
400
        image->type=GrayscaleType;
1249
400
        SetImageColorspace(image,GRAYColorspace,exception);
1250
400
      }
1251
1252
1253
    /*
1254
      If ping is true, then only set image size and colors without
1255
      reading any image data.
1256
    */
1257
4.91k
    if (image_info->ping)
1258
3
    {
1259
3
      size_t temp = image->columns;
1260
3
      image->columns = image->rows;
1261
3
      image->rows = temp;
1262
3
      goto done_reading; /* !!!!!! BAD  !!!! */
1263
3
    }
1264
4.91k
    if ((image->columns > GetBlobSize(image)) ||
1265
4.91k
        (image->rows > GetBlobSize(image)))
1266
0
      {
1267
0
        if (clone_info != (ImageInfo *) NULL)
1268
0
          clone_info=DestroyImageInfo(clone_info);
1269
0
        if ((image != image2) && (image2 != (Image *) NULL))
1270
0
          image2=DestroyImage(image2);
1271
0
        ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
1272
0
      }
1273
4.91k
    status=SetImageExtent(image,image->columns,image->rows,exception);
1274
4.91k
    if (status == MagickFalse)
1275
14
      {
1276
14
        if (clone_info != (ImageInfo *) NULL)
1277
14
          clone_info=DestroyImageInfo(clone_info);
1278
14
        if ((image != image2) && (image2 != (Image *) NULL))
1279
0
          image2=DestroyImage(image2);
1280
14
        return(DestroyImageList(image));
1281
14
      }
1282
4.90k
    (void) SetImageBackgroundColor(image,exception);
1283
4.90k
    quantum_info=AcquireQuantumInfo(clone_info,image);
1284
4.90k
    if (quantum_info == (QuantumInfo *) NULL)
1285
0
      {
1286
0
        if (clone_info != (ImageInfo *) NULL)
1287
0
          clone_info=DestroyImageInfo(clone_info);
1288
0
        if ((image != image2) && (image2 != (Image *) NULL))
1289
0
          image2=DestroyImage(image2);
1290
0
        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1291
0
      }
1292
1293
  /* ----- Load raster data ----- */
1294
4.90k
    BImgBuff = (unsigned char *) AcquireQuantumMemory((size_t) (ldblk),sizeof(double));    /* Ldblk was set in the check phase */
1295
4.90k
    if (BImgBuff == NULL)
1296
0
      {
1297
0
        if (clone_info != (ImageInfo *) NULL)
1298
0
          clone_info=DestroyImageInfo(clone_info);
1299
0
        if ((image != image2) && (image2 != (Image *) NULL))
1300
0
          image2=DestroyImage(image2);
1301
0
        if (quantum_info != (QuantumInfo *) NULL)
1302
0
          quantum_info=DestroyQuantumInfo(quantum_info);
1303
0
        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1304
0
      }
1305
4.90k
    (void) memset(BImgBuff,0,(size_t) ldblk*sizeof(double));
1306
1307
4.90k
    MinVal = 0;
1308
4.90k
    MaxVal = 0;
1309
4.90k
    if (CellType==miDOUBLE || CellType==miSINGLE)        /* Find Min and Max Values for floats */
1310
1.07k
      {
1311
1.07k
        CalcMinMax(image2,(int) image_info->endian,MATLAB_HDR.SizeX,
1312
1.07k
          MATLAB_HDR.SizeY,CellType,(unsigned int) ldblk,BImgBuff,
1313
1.07k
          &quantum_info->minimum,&quantum_info->maximum);
1314
1.07k
      }
1315
1316
    /* Main loop for reading all scanlines */
1317
4.90k
    if(z==1) z=0; /* read grey scanlines */
1318
    /* else read color scanlines */
1319
4.90k
    do
1320
5.87k
    {
1321
46.0k
      for (i = 0; i < (ssize_t) MATLAB_HDR.SizeY; i++)
1322
40.6k
      {
1323
40.6k
        q=GetAuthenticPixels(image,0,MATLAB_HDR.SizeY-i-1,image->columns,1,exception);
1324
40.6k
        if (q == (Quantum *) NULL)
1325
0
          {
1326
0
            if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),
1327
0
              "  MAT set image pixels returns unexpected NULL on a row %u.", (unsigned)(MATLAB_HDR.SizeY-i-1));
1328
0
            goto done_reading;    /* Skip image rotation, when cannot set image pixels    */
1329
0
          }
1330
40.6k
        if(ReadBlob(image2,(size_t) ldblk,(unsigned char *) BImgBuff) != (ssize_t) ldblk)
1331
446
          {
1332
446
            if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),
1333
0
              "  MAT cannot read scanrow %u from a file.", (unsigned)(MATLAB_HDR.SizeY-i-1));
1334
446
           if ((image != image2) && (image2 != (Image *) NULL))
1335
6
              image2=DestroyImage(image2);
1336
446
            if (clone_info != (ImageInfo *) NULL)
1337
446
              clone_info=DestroyImageInfo(clone_info);
1338
446
            if (quantum_info != (QuantumInfo *) NULL)
1339
446
              quantum_info=DestroyQuantumInfo(quantum_info);
1340
446
            BImgBuff=(unsigned char *) RelinquishMagickMemory(BImgBuff);
1341
446
            ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
1342
0
          }
1343
40.2k
        if((CellType==miINT8 || CellType==miUINT8) && (MATLAB_HDR.StructureFlag & FLAG_LOGICAL))
1344
9.23k
        {
1345
9.23k
          FixLogical((unsigned char *)BImgBuff,ldblk);
1346
9.23k
          if(ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,z2qtype[z],BImgBuff,exception) <= 0)
1347
0
            {
1348
0
ImportQuantumPixelsFailed:
1349
0
              if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),
1350
0
                "  MAT failed to ImportQuantumPixels for a row %u", (unsigned)(MATLAB_HDR.SizeY-i-1));
1351
0
              break;
1352
0
            }
1353
9.23k
        }
1354
30.9k
        else
1355
30.9k
        {
1356
30.9k
          if(ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,z2qtype[z],BImgBuff,exception) <= 0)
1357
0
            goto ImportQuantumPixelsFailed;
1358
1359
1360
30.9k
          if (z<=1 &&       /* fix only during a last pass z==0 || z==1 */
1361
26.6k
             (CellType==miINT8 || CellType==miINT16 || CellType==miINT32 || CellType==miINT64))
1362
19.4k
            FixSignedValues(image,q,MATLAB_HDR.SizeX);
1363
30.9k
        }
1364
1365
40.2k
        if (!SyncAuthenticPixels(image,exception))
1366
0
          {
1367
0
            if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),
1368
0
              "  MAT failed to sync image pixels for a row %u", (unsigned)(MATLAB_HDR.SizeY-i-1));
1369
0
            goto ExitLoop;
1370
0
          }
1371
40.2k
      }
1372
5.87k
    } while(z-- >= 2);
1373
4.45k
ExitLoop:
1374
4.45k
    if (i != (long) MATLAB_HDR.SizeY)
1375
0
      goto END_OF_READING;
1376
1377
    /* Read complex part of numbers here */
1378
4.45k
    if (MATLAB_HDR.StructureFlag & FLAG_COMPLEX)
1379
1.10k
    {        /* Find Min and Max Values for complex parts of floats */
1380
1.10k
      CellType = ReadBlobXXXLong(image2);    /* Additional object type */
1381
1.10k
      i = ReadBlobXXXLong(image2);           /* size of a complex part - toss away*/
1382
1383
1.10k
      if (CellType==miDOUBLE || CellType==miSINGLE)
1384
313
      {
1385
313
        CalcMinMax(image2,(int) image_info->endian,MATLAB_HDR.SizeX,
1386
313
          MATLAB_HDR.SizeY,CellType,(unsigned int) ldblk,BImgBuff,&MinVal,&MaxVal);
1387
313
      }
1388
1389
1.10k
      if (CellType==miDOUBLE)
1390
2.77k
        for (i = 0; i < (ssize_t) MATLAB_HDR.SizeY; i++)
1391
2.61k
        {
1392
2.61k
          ReadBlobDoublesXXX(image2, (size_t) ldblk, (double *)BImgBuff);
1393
2.61k
          if (EOFBlob(image) != MagickFalse)
1394
29
            break;
1395
2.58k
          InsertComplexDoubleRow(image,(double *)BImgBuff,(int) i,MinVal,MaxVal,
1396
2.58k
            exception);
1397
2.58k
        }
1398
1399
1.10k
      if (CellType==miSINGLE)
1400
2.22k
        for (i = 0; i < (ssize_t) MATLAB_HDR.SizeY; i++)
1401
2.14k
        {
1402
2.14k
          ReadBlobFloatsXXX(image2, (size_t) ldblk, (float *)BImgBuff);
1403
2.14k
          if (EOFBlob(image) != MagickFalse)
1404
33
            break;
1405
2.10k
          InsertComplexFloatRow(image,(float *)BImgBuff,(int) i,MinVal,MaxVal,
1406
2.10k
            exception);
1407
2.10k
        }
1408
1.10k
    }
1409
1410
      /* Image is gray when no complex flag is set and 2D Matrix AGAIN!!! */
1411
4.45k
    if ((MATLAB_HDR.DimFlag == 8) &&
1412
889
        ((MATLAB_HDR.StructureFlag & FLAG_COMPLEX) == 0))
1413
350
      image->type=GrayscaleType;
1414
4.45k
    if (image->depth == 1)
1415
684
      image->type=BilevelType;
1416
1417
4.45k
    if(image2==image)
1418
4.44k
        image2 = NULL;    /* Remove shadow copy to an image before rotation. */
1419
1420
      /*  Rotate image. */
1421
4.45k
    rotated_image = RotateImage(image, 90.0, exception);
1422
4.45k
    if (rotated_image != (Image *) NULL)
1423
4.45k
    {
1424
        /* Remove page offsets added by RotateImage */
1425
4.45k
      rotated_image->page.x=0;
1426
4.45k
      rotated_image->page.y=0;
1427
4.45k
      rotated_image->colors = image->colors;
1428
4.45k
      DestroyBlob(rotated_image);
1429
4.45k
      rotated_image->blob=ReferenceBlob(image->blob);
1430
4.45k
      AppendImageToList(&image,rotated_image);
1431
4.45k
      DeleteImageFromList(&image);
1432
4.45k
    }
1433
1434
4.45k
done_reading:
1435
1436
4.45k
    if(image2!=NULL)
1437
12
      if(image2!=image)
1438
12
      {
1439
12
        DeleteImageFromList(&image2);
1440
12
        if(clone_info)
1441
12
        {
1442
12
          if(clone_info->file)
1443
12
          {
1444
12
            fclose(clone_info->file);
1445
12
            clone_info->file = NULL;
1446
12
            (void) remove_utf8(clone_info->filename);
1447
12
          }
1448
12
        }
1449
12
      }
1450
4.45k
    if (EOFBlob(image) != MagickFalse)
1451
333
      break;
1452
1453
      /* Allocate next image structure. */
1454
4.12k
    if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
1455
0
      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1456
0
        break;
1457
4.12k
    AcquireNextImage(image_info,image,exception);
1458
4.12k
    if (image->next == (Image *) NULL) break;
1459
4.12k
    image=SyncNextImageInList(image);
1460
4.12k
    image->columns=image->rows=0;
1461
4.12k
    image->colors=0;
1462
1463
      /* row scan buffer is no longer needed */
1464
4.12k
    RelinquishMagickMemory(BImgBuff);
1465
4.12k
    BImgBuff = NULL;
1466
4.12k
    if (quantum_info != (QuantumInfo *) NULL)
1467
4.12k
      quantum_info=DestroyQuantumInfo(quantum_info);
1468
1469
4.12k
    if(--Frames>0)
1470
3.24k
    {
1471
3.24k
      z = z2;
1472
3.24k
      if(image2==NULL) image2 = image;
1473
3.24k
      if(!EOFBlob(image) && TellBlob(image)<filepos)
1474
2.90k
        goto NEXT_FRAME;
1475
3.24k
    }
1476
1.21k
    if ((image2!=NULL) && (image2!=image))   /* Does shadow temporary decompressed image exist? */
1477
0
      {
1478
/*  CloseBlob(image2); */
1479
0
        DeleteImageFromList(&image2);
1480
0
        if(clone_info)
1481
0
        {
1482
0
          if(clone_info->file)
1483
0
          {
1484
0
            fclose(clone_info->file);
1485
0
            clone_info->file = NULL;
1486
0
            (void) remove_utf8(clone_info->filename);
1487
0
          }
1488
0
        }
1489
0
      }
1490
1491
1.21k
    if (clone_info)
1492
1.21k
      clone_info=DestroyImageInfo(clone_info);
1493
1.21k
  }
1494
1495
2.13k
END_OF_READING:
1496
2.13k
  RelinquishMagickMemory(BImgBuff);
1497
2.13k
  if (quantum_info != (QuantumInfo *) NULL)
1498
333
    quantum_info=DestroyQuantumInfo(quantum_info);
1499
2.13k
  CloseBlob(image);
1500
1501
1502
2.13k
  {
1503
2.13k
    Image *p;
1504
2.13k
    ssize_t scene=0;
1505
1506
    /*
1507
      Rewind list, removing any empty images while rewinding.
1508
    */
1509
2.13k
    p=GetLastImageInList(image);
1510
2.13k
    image=NULL;
1511
7.04k
    while (p != (Image *) NULL)
1512
4.91k
      {
1513
4.91k
        Image *tmp=p;
1514
4.91k
        if ((p->rows == 0) || (p->columns == 0)) {
1515
1.61k
          p=p->previous;
1516
1.61k
          if (tmp == image2)
1517
154
            image2=(Image *) NULL;
1518
1.61k
          DeleteImageFromList(&tmp);
1519
3.30k
        } else {
1520
3.30k
          image=p;
1521
3.30k
          p=p->previous;
1522
3.30k
        }
1523
4.91k
      }
1524
1525
    /*
1526
      Fix scene numbers
1527
    */
1528
5.43k
    for (p=image; p != (Image *) NULL; p=p->next)
1529
3.30k
      p->scene=(size_t) scene++;
1530
2.13k
  }
1531
1532
2.13k
  if(clone_info != NULL)  /* cleanup garbage file from compression */
1533
672
  {
1534
672
    if(clone_info->file)
1535
0
    {
1536
0
      fclose(clone_info->file);
1537
0
      clone_info->file = NULL;
1538
0
      (void) remove_utf8(clone_info->filename);
1539
0
    }
1540
672
    DestroyImageInfo(clone_info);
1541
672
    clone_info = NULL;
1542
672
  }
1543
2.13k
  if (logging) (void)LogMagickEvent(CoderEvent,GetMagickModule(),"return");
1544
2.13k
  if ((image != image2) && (image2 != (Image *) NULL))
1545
0
    image2=DestroyImage(image2);
1546
2.13k
  if (image == (Image *) NULL)
1547
1.16k
    ThrowReaderException(CorruptImageError,"ImproperImageHeader")
1548
970
  return(image);
1549
2.13k
}
1550

1551
/*
1552
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1553
%                                                                             %
1554
%                                                                             %
1555
%                                                                             %
1556
%   R e g i s t e r M A T I m a g e                                           %
1557
%                                                                             %
1558
%                                                                             %
1559
%                                                                             %
1560
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1561
%
1562
%  Method RegisterMATImage adds attributes for the MAT image format to
1563
%  the list of supported formats.  The attributes include the image format
1564
%  tag, a method to read and/or write the format, whether the format
1565
%  supports the saving of more than one frame to the same file or blob,
1566
%  whether the format supports native in-memory I/O, and a brief
1567
%  description of the format.
1568
%
1569
%  The format of the RegisterMATImage method is:
1570
%
1571
%      size_t RegisterMATImage(void)
1572
%
1573
*/
1574
ModuleExport size_t RegisterMATImage(void)
1575
11
{
1576
11
  MagickInfo
1577
11
    *entry;
1578
1579
11
  entry=AcquireMagickInfo("MAT","MAT","MATLAB level 5 image format");
1580
11
  entry->decoder=(DecodeImageHandler *) ReadMATImage;
1581
11
  entry->encoder=(EncodeImageHandler *) WriteMATImage;
1582
11
  entry->flags^=CoderBlobSupportFlag;
1583
11
  entry->flags|=CoderDecoderSeekableStreamFlag;
1584
11
  (void) RegisterMagickInfo(entry);
1585
11
  return(MagickImageCoderSignature);
1586
11
}
1587

1588
/*
1589
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1590
%                                                                             %
1591
%                                                                             %
1592
%                                                                             %
1593
%   U n r e g i s t e r M A T I m a g e                                       %
1594
%                                                                             %
1595
%                                                                             %
1596
%                                                                             %
1597
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1598
%
1599
%  Method UnregisterMATImage removes format registrations made by the
1600
%  MAT module from the list of supported formats.
1601
%
1602
%  The format of the UnregisterMATImage method is:
1603
%
1604
%      UnregisterMATImage(void)
1605
%
1606
*/
1607
ModuleExport void UnregisterMATImage(void)
1608
0
{
1609
0
  (void) UnregisterMagickInfo("MAT");
1610
0
}
1611

1612
/*
1613
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1614
%                                                                             %
1615
%                                                                             %
1616
%                                                                             %
1617
%   W r i t e M A T L A B I m a g e                                           %
1618
%                                                                             %
1619
%                                                                             %
1620
%                                                                             %
1621
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1622
%
1623
%  Function WriteMATImage writes an Matlab matrix to a file.
1624
%
1625
%  The format of the WriteMATImage method is:
1626
%
1627
%      MagickBooleanType WriteMATImage(const ImageInfo *image_info,
1628
%        Image *image,ExceptionInfo *exception)
1629
%
1630
%  A description of each parameter follows.
1631
%
1632
%    o image_info: Specifies a pointer to a ImageInfo structure.
1633
%
1634
%    o image:  A pointer to an Image structure.
1635
%
1636
%    o exception: return any errors or warnings in this structure.
1637
%
1638
*/
1639
static MagickBooleanType WriteMATImage(const ImageInfo *image_info,Image *image,
1640
  ExceptionInfo *exception)
1641
771
{
1642
771
  char
1643
771
    MATLAB_HDR[0x80];
1644
1645
771
  MagickBooleanType
1646
771
    status;
1647
1648
771
  MagickOffsetType
1649
771
    scene;
1650
1651
771
  size_t
1652
771
    number_scenes;
1653
1654
771
  struct tm
1655
771
    utc_time;
1656
1657
771
  time_t
1658
771
    current_time;
1659
1660
  /*
1661
    Open output image file.
1662
  */
1663
771
  assert(image_info != (const ImageInfo *) NULL);
1664
771
  assert(image_info->signature == MagickCoreSignature);
1665
771
  assert(image != (Image *) NULL);
1666
771
  assert(image->signature == MagickCoreSignature);
1667
771
  (void) LogMagickEvent(CoderEvent,GetMagickModule(),"enter MAT");
1668
771
  assert(exception != (ExceptionInfo *) NULL);
1669
771
  assert(exception->signature == MagickCoreSignature);
1670
771
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
1671
771
  if (status == MagickFalse)
1672
0
    return(MagickFalse);
1673
771
  image->depth=8;
1674
1675
771
  current_time=GetMagickTime();
1676
771
  GetMagickUTCTime(&current_time,&utc_time);
1677
771
  (void) memset(MATLAB_HDR,' ',MagickMin(sizeof(MATLAB_HDR),124));
1678
771
  FormatLocaleString(MATLAB_HDR,sizeof(MATLAB_HDR),
1679
771
    "MATLAB 5.0 MAT-file, Platform: %s, Created on: %s %s %2d %2d:%2d:%2d %d",
1680
771
    OsDesc,DayOfWTab[utc_time.tm_wday],MonthsTab[utc_time.tm_mon],
1681
771
    utc_time.tm_mday,utc_time.tm_hour,utc_time.tm_min,
1682
771
    utc_time.tm_sec,utc_time.tm_year+1900);
1683
771
  MATLAB_HDR[0x7C]=0;
1684
771
  MATLAB_HDR[0x7D]=1;
1685
771
  MATLAB_HDR[0x7E]='I';
1686
771
  MATLAB_HDR[0x7F]='M';
1687
771
  (void) WriteBlob(image,sizeof(MATLAB_HDR),(unsigned char *) MATLAB_HDR);
1688
771
  scene=0;
1689
771
  number_scenes=GetImageListLength(image);
1690
771
  do
1691
771
  {
1692
771
    char
1693
771
      padding;
1694
1695
771
    MagickBooleanType
1696
771
      is_gray;
1697
1698
771
    QuantumInfo
1699
771
      *quantum_info;
1700
1701
771
    size_t
1702
771
      data_size;
1703
1704
771
    unsigned char
1705
771
      *pixels;
1706
1707
771
    unsigned int
1708
771
      z;
1709
1710
771
    if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
1711
0
      (void) TransformImageColorspace(image,sRGBColorspace,exception);
1712
771
    is_gray=IdentifyImageCoderGray(image,exception);
1713
771
    z=(is_gray != MagickFalse) ? 0 : 3;
1714
1715
    /*
1716
      Store MAT header.
1717
    */
1718
771
    data_size = image->rows * image->columns;
1719
771
    if (is_gray == MagickFalse)
1720
411
      data_size*=3;
1721
771
    padding=((unsigned char)(data_size-1) & 0x7) ^ 0x7;
1722
1723
771
    (void) WriteBlobLSBLong(image,miMATRIX);
1724
771
    (void) WriteBlobLSBLong(image,(unsigned int) ((ssize_t) data_size+padding+
1725
771
      ((is_gray != MagickFalse) ? 48 : 56)));
1726
771
    (void) WriteBlobLSBLong(image,0x6); /* 0x88 */
1727
771
    (void) WriteBlobLSBLong(image,0x8); /* 0x8C */
1728
771
    (void) WriteBlobLSBLong(image,0x6); /* 0x90 */
1729
771
    (void) WriteBlobLSBLong(image,0);
1730
771
    (void) WriteBlobLSBLong(image,0x5); /* 0x98 */
1731
771
    (void) WriteBlobLSBLong(image,(is_gray != MagickFalse) ? 0x8 : 0xC); /* 0x9C - DimFlag */
1732
771
    (void) WriteBlobLSBLong(image,(unsigned int) image->rows);    /* x: 0xA0 */
1733
771
    (void) WriteBlobLSBLong(image,(unsigned int) image->columns); /* y: 0xA4 */
1734
771
    if (is_gray == MagickFalse)
1735
411
      {
1736
411
        (void) WriteBlobLSBLong(image,3); /* z: 0xA8 */
1737
411
        (void) WriteBlobLSBLong(image,0);
1738
411
      }
1739
771
    (void) WriteBlobLSBShort(image,1);  /* 0xB0 */
1740
771
    (void) WriteBlobLSBShort(image,1);  /* 0xB2 */
1741
771
    (void) WriteBlobLSBLong(image,'M'); /* 0xB4 */
1742
771
    (void) WriteBlobLSBLong(image,0x2); /* 0xB8 */
1743
771
    (void) WriteBlobLSBLong(image,(unsigned int) data_size); /* 0xBC */
1744
1745
    /*
1746
      Store image data.
1747
    */
1748
771
    quantum_info=AcquireQuantumInfo(image_info,image);
1749
771
    if (quantum_info == (QuantumInfo *) NULL)
1750
771
      ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1751
771
    pixels=(unsigned char *) GetQuantumPixels(quantum_info);
1752
771
    do
1753
1.59k
    {
1754
1.59k
      const Quantum
1755
1.59k
        *p;
1756
1757
1.59k
      ssize_t
1758
1.59k
        y;
1759
1760
54.9k
      for (y=0; y < (ssize_t) image->columns; y++)
1761
53.3k
      {
1762
53.3k
        size_t
1763
53.3k
          length;
1764
1765
53.3k
        p=GetVirtualPixels(image,y,0,1,image->rows,exception);
1766
53.3k
        if (p == (const Quantum *) NULL)
1767
0
          break;
1768
53.3k
        length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1769
53.3k
          z2qtype[z],pixels,exception);
1770
53.3k
        if (length != image->columns)
1771
0
          break;
1772
53.3k
        if (WriteBlob(image,image->rows,pixels) != (ssize_t) image->rows)
1773
0
          break;
1774
53.3k
      }
1775
1.59k
      if (y < (ssize_t) image->columns)
1776
0
        break;
1777
1.59k
      if (SyncAuthenticPixels(image,exception) == MagickFalse)
1778
0
        break;
1779
1.59k
    } while (z-- >= 2);
1780
771
    (void) WriteBlobPadding(image,padding,'\0');
1781
771
    quantum_info=DestroyQuantumInfo(quantum_info);
1782
771
    if (GetNextImageInList(image) == (Image *) NULL)
1783
771
      break;
1784
0
    image=SyncNextImageInList(image);
1785
0
    status=SetImageProgress(image,SaveImagesTag,scene++,number_scenes);
1786
0
    if (status == MagickFalse)
1787
0
      break;
1788
0
  } while (image_info->adjoin != MagickFalse);
1789
771
  if (CloseBlob(image) == MagickFalse)
1790
0
    status=MagickFalse;
1791
771
  return(status);
1792
771
}