Coverage Report

Created: 2026-11-12 07:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/imagemagick/coders/cip.c
Line
Count
Source
1
/*
2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3
%                                                                             %
4
%                                                                             %
5
%                             CCCC  IIIII  PPPP                               %
6
%                            C        I    P   P                              %
7
%                            C        I    PPPP                               %
8
%                            C        I    P                                  %
9
%                             CCCC  IIIII  P                                  %
10
%                                                                             %
11
%                                                                             %
12
%                  Read/Write Cisco IP Phone Image Format                     %
13
%                                                                             %
14
%                              Software Design                                %
15
%                                   Cristy                                    %
16
%                                April 2004                                   %
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/blob.h"
43
#include "MagickCore/blob-private.h"
44
#include "MagickCore/cache.h"
45
#include "MagickCore/color-private.h"
46
#include "MagickCore/colorspace.h"
47
#include "MagickCore/colorspace-private.h"
48
#include "MagickCore/constitute.h"
49
#include "MagickCore/exception.h"
50
#include "MagickCore/exception-private.h"
51
#include "MagickCore/image.h"
52
#include "MagickCore/image-private.h"
53
#include "MagickCore/list.h"
54
#include "MagickCore/magick.h"
55
#include "MagickCore/memory_.h"
56
#include "MagickCore/monitor.h"
57
#include "MagickCore/monitor-private.h"
58
#include "MagickCore/pixel-accessor.h"
59
#include "MagickCore/property.h"
60
#include "MagickCore/quantize.h"
61
#include "MagickCore/quantum-private.h"
62
#include "MagickCore/static.h"
63
#include "MagickCore/string_.h"
64
#include "MagickCore/module.h"
65
#include "MagickCore/utility.h"
66
#include "MagickCore/xml-tree-private.h"
67

68
/*
69
  Forward declarations.
70
*/
71
static MagickBooleanType
72
  WriteCIPImage(const ImageInfo *,Image *,ExceptionInfo *);
73

74
/*
75
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
76
%                                                                             %
77
%                                                                             %
78
%                                                                             %
79
%   R e g i s t e r C I P I m a g e                                           %
80
%                                                                             %
81
%                                                                             %
82
%                                                                             %
83
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
84
%
85
%  RegisterCIPImage() adds properties for the CIP IP phone image format to
86
%  the list of supported formats.  The properties include the image format
87
%  tag, a method to read and/or write the format, whether the format
88
%  supports the saving of more than one frame to the same file or blob,
89
%  whether the format supports native in-memory I/O, and a brief
90
%  description of the format.
91
%
92
%  The format of the RegisterCIPImage method is:
93
%
94
%      size_t RegisterCIPImage(void)
95
%
96
*/
97
ModuleExport size_t RegisterCIPImage(void)
98
7
{
99
7
  MagickInfo
100
7
    *entry;
101
102
7
  entry=AcquireMagickInfo("CIP","CIP","Cisco IP phone image format");
103
7
  entry->encoder=(EncodeImageHandler *) WriteCIPImage;
104
7
  entry->flags^=CoderAdjoinFlag;
105
7
  (void) RegisterMagickInfo(entry);
106
7
  return(MagickImageCoderSignature);
107
7
}
108

109
/*
110
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
111
%                                                                             %
112
%                                                                             %
113
%                                                                             %
114
%   U n r e g i s t e r C I P I m a g e                                       %
115
%                                                                             %
116
%                                                                             %
117
%                                                                             %
118
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
119
%
120
%  UnregisterCIPImage() removes format registrations made by the
121
%  CIP module from the list of supported formats.
122
%
123
%  The format of the UnregisterCIPImage method is:
124
%
125
%      UnregisterCIPImage(void)
126
%
127
*/
128
ModuleExport void UnregisterCIPImage(void)
129
0
{
130
0
  (void) UnregisterMagickInfo("CIP");
131
0
}
132

133
/*
134
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
135
%                                                                             %
136
%                                                                             %
137
%                                                                             %
138
%   W r i t e C I P I m a g e                                                 %
139
%                                                                             %
140
%                                                                             %
141
%                                                                             %
142
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
143
%
144
%  Procedure WriteCIPImage() writes an image to a file in the Cisco IP phone
145
%  image format.
146
%
147
%  The format of the WriteCIPImage method is:
148
%
149
%      MagickBooleanType WriteCIPImage(const ImageInfo *image_info,
150
%        Image *image,ExceptionInfo *exception)
151
%
152
%  A description of each parameter follows.
153
%
154
%    o image_info: the image info.
155
%
156
%    o image:  The image.
157
%
158
%    o exception: return any errors or warnings in this structure.
159
%
160
*/
161
static MagickBooleanType WriteCIPImage(const ImageInfo *image_info,Image *image,
162
  ExceptionInfo *exception)
163
0
{
164
0
  char
165
0
    buffer[MagickPathExtent],
166
0
    *escaped;
167
168
0
  const char
169
0
    *hex_digits="0123456789abcdef",
170
0
    *value;
171
172
0
  MagickBooleanType
173
0
    status;
174
175
0
  const Quantum
176
0
    *p;
177
178
0
  size_t
179
0
    row_extent;
180
181
0
  ssize_t
182
0
    i,
183
0
    x;
184
185
0
  ssize_t
186
0
    y;
187
188
0
  unsigned char
189
0
    byte,
190
0
    *pixels,
191
0
    *q;
192
193
  /*
194
    Open output image file.
195
  */
196
0
  assert(image_info != (const ImageInfo *) NULL);
197
0
  assert(image_info->signature == MagickCoreSignature);
198
0
  assert(image != (Image *) NULL);
199
0
  assert(image->signature == MagickCoreSignature);
200
0
  assert(exception != (ExceptionInfo *) NULL);
201
0
  assert(exception->signature == MagickCoreSignature);
202
0
  if (IsEventLogging() != MagickFalse)
203
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
204
0
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
205
0
  if (status == MagickFalse)
206
0
    return(status);
207
0
  (void) WriteBlobString(image,"<CiscoIPPhoneImage>\n");
208
0
  value=GetImageProperty(image,"label",exception);
209
0
  if (value == (const char *) NULL)
210
0
    {
211
0
      GetPathComponent(image->filename,BasePath,buffer);
212
0
      value=buffer;
213
0
    }
214
0
  escaped=SubstituteXMLEntities(value,MagickFalse);
215
0
  (void) WriteBlobString(image,"<Title>");
216
0
  if (escaped != (char*)NULL)
217
0
    (void) WriteBlobString(image,escaped);
218
0
  (void) WriteBlobString(image,"</Title>\n");
219
0
  escaped=DestroyString(escaped);
220
0
  (void) FormatLocaleString(buffer,MagickPathExtent,
221
0
    "<LocationX>%.17g</LocationX>\n",(double) image->page.x);
222
0
  (void) WriteBlobString(image,buffer);
223
0
  (void) FormatLocaleString(buffer,MagickPathExtent,
224
0
    "<LocationY>%.17g</LocationY>\n",(double) image->page.y);
225
0
  (void) WriteBlobString(image,buffer);
226
0
  (void) FormatLocaleString(buffer,MagickPathExtent,"<Width>%.17g</Width>\n",
227
0
    (double) (image->columns+(image->columns % 2)));
228
0
  (void) WriteBlobString(image,buffer);
229
0
  (void) FormatLocaleString(buffer,MagickPathExtent,"<Height>%.17g</Height>\n",
230
0
    (double) image->rows);
231
0
  (void) WriteBlobString(image,buffer);
232
0
  (void) FormatLocaleString(buffer,MagickPathExtent,"<Depth>2</Depth>\n");
233
0
  (void) WriteBlobString(image,buffer);
234
0
  (void) WriteBlobString(image,"<Data>");
235
0
  if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
236
0
    (void) TransformImageColorspace(image,sRGBColorspace,exception);
237
0
  row_extent=image->columns/4;
238
0
  if (row_extent > ((size_t) MAGICK_SSIZE_MAX-2*sizeof(unsigned int))/2)
239
0
    ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
240
  /* Allow space for the existing trailing-byte hexadecimal formatting. */
241
0
  row_extent=2*row_extent+2*sizeof(unsigned int);
242
0
  pixels=(unsigned char *) AcquireQuantumMemory(row_extent,sizeof(*pixels));
243
0
  if (pixels == (unsigned char *) NULL)
244
0
    ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
245
0
  for (y=0; y < (ssize_t) image->rows; y++)
246
0
  {
247
0
    p=GetVirtualPixels(image,0,y,image->columns,1,exception);
248
0
    if (p == (const Quantum *) NULL)
249
0
      {
250
0
        status=MagickFalse;
251
0
        break;
252
0
      }
253
0
    q=pixels;
254
0
    for (x=0; x < ((ssize_t) image->columns-3); x+=4)
255
0
    {
256
0
      byte=(unsigned char)
257
0
        ((((size_t) (3*ClampToQuantum(GetPixelLuma(image,p+3*GetPixelChannels(image)))/QuantumRange) & 0x03) << 6) |
258
0
         (((size_t) (3*ClampToQuantum(GetPixelLuma(image,p+2*GetPixelChannels(image)))/QuantumRange) & 0x03) << 4) |
259
0
         (((size_t) (3*ClampToQuantum(GetPixelLuma(image,p+1*GetPixelChannels(image)))/QuantumRange) & 0x03) << 2) |
260
0
         (((size_t) (3*ClampToQuantum(GetPixelLuma(image,p+0*GetPixelChannels(image)))/QuantumRange) & 0x03) << 0));
261
0
      *q++=(unsigned char) hex_digits[byte >> 4];
262
0
      *q++=(unsigned char) hex_digits[byte & 0x0f];
263
0
      p+=(ptrdiff_t) GetPixelChannels(image);
264
0
    }
265
0
    if ((image->columns % 4) != 0)
266
0
      {
267
0
        byte=0;
268
0
        for ( ; x < (ssize_t) image->columns; x++)
269
0
        {
270
0
          i=x % 4;
271
0
          switch (i)
272
0
          {
273
0
            case 0:
274
0
            {
275
0
              byte|=(unsigned char) (((size_t) (3*ClampToQuantum(GetPixelLuma(
276
0
                image,p+MagickMin(i,3)*(ssize_t) GetPixelChannels(image)))/
277
0
                QuantumRange) & 0x03) << 6);
278
0
              break;
279
0
            }
280
0
            case 1:
281
0
            {
282
0
              byte|=(unsigned char) (((size_t) (3*ClampToQuantum(GetPixelLuma(
283
0
                image,p+MagickMin(i,2)*(ssize_t) GetPixelChannels(image)))/
284
0
                QuantumRange) & 0x03) << 4);
285
0
              break;
286
0
            }
287
0
            case 2:
288
0
            {
289
0
              byte|=(unsigned char) (((size_t) (3*ClampToQuantum(GetPixelLuma(
290
0
                image,p+MagickMin(i,1)*(ssize_t) GetPixelChannels(image)))/
291
0
                QuantumRange) & 0x03) << 2);
292
0
              break;
293
0
            }
294
0
            case 3:
295
0
            {
296
0
              byte|=(unsigned char) (((size_t) (3*ClampToQuantum(GetPixelLuma(
297
0
                image,p+MagickMin(i,0)*(ssize_t) GetPixelChannels(image)))/
298
0
                QuantumRange) & 0x03) << 0);
299
0
              break;
300
0
            }
301
0
          }
302
0
        }
303
0
        (void) FormatLocaleString(buffer,MagickPathExtent,"%02x",~byte);
304
0
        (void) memcpy(q,buffer,strlen(buffer));
305
0
        q+=strlen(buffer);
306
0
      }
307
0
    if (WriteBlob(image,(size_t) (q-pixels),pixels) != (ssize_t) (q-pixels))
308
0
      {
309
0
        status=MagickFalse;
310
0
        break;
311
0
      }
312
0
    status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
313
0
      image->rows);
314
0
    if (status == MagickFalse)
315
0
      break;
316
0
  }
317
0
  pixels=(unsigned char *) RelinquishMagickMemory(pixels);
318
0
  (void) WriteBlobString(image,"</Data>\n");
319
0
  (void) WriteBlobString(image,"</CiscoIPPhoneImage>\n");
320
0
  if (CloseBlob(image) == MagickFalse)
321
0
    status=MagickFalse;
322
0
  return(status);
323
0
}