1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % SSSSS CCCC RRRR %
7 % SS C R R %
8 % SSS C RRRR %
9 % SS C R R %
10 % SSSSS CCCC R R %
11 % %
12 % %
13 % Read ZX-Spectrum SCREEN$ Format %
14 % %
15 % Software Design %
16 % Catalin Mihaila %
17 % October 2003 %
18 % %
19 % %
20 % Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
22 % %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
25 % %
26 % https://imagemagick.org/script/license.php %
27 % %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
33 % %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38
39 /*
40 Include declarations.
41 */
42 #include "MagickCore/studio.h"
43 #include "MagickCore/blob.h"
44 #include "MagickCore/blob-private.h"
45 #include "MagickCore/cache.h"
46 #include "MagickCore/exception.h"
47 #include "MagickCore/exception-private.h"
48 #include "MagickCore/image.h"
49 #include "MagickCore/image-private.h"
50 #include "MagickCore/list.h"
51 #include "MagickCore/magick.h"
52 #include "MagickCore/memory_.h"
53 #include "MagickCore/monitor.h"
54 #include "MagickCore/monitor-private.h"
55 #include "MagickCore/pixel-accessor.h"
56 #include "MagickCore/quantum-private.h"
57 #include "MagickCore/static.h"
58 #include "MagickCore/string_.h"
59 #include "MagickCore/module.h"
60
61 /*
62 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
63 % %
64 % %
65 % %
66 % R e a d S C R I m a g e %
67 % %
68 % %
69 % %
70 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
71 %
72 % ReadSCRImage() reads a Scitex image file and returns it. It allocates
73 % the memory necessary for the new Image structure and returns a pointer to
74 % the new image.
75 %
76 % The format of the ReadSCRImage method is:
77 %
78 % Image *ReadSCRImage(const ImageInfo *image_info,ExceptionInfo *exception)
79 %
80 % A description of each parameter follows:
81 %
82 % o image_info: the image info.
83 %
84 % o exception: return any errors or warnings in this structure.
85 %
86 */
ReadSCRImage(const ImageInfo * image_info,ExceptionInfo * exception)87 static Image *ReadSCRImage(const ImageInfo *image_info,ExceptionInfo *exception)
88 {
89 char zxscr[6144];
90 char zxattr[768];
91 int octetnr;
92 int octetline;
93 int zoneline;
94 int zonenr;
95 int octet_val;
96 int attr_nr;
97 int pix;
98 int piy;
99 int binar[8];
100 int attrbin[8];
101 int *pbin;
102 int *abin;
103 int z;
104 int one_nr;
105 int ink;
106 int paper;
107 int bright;
108
109 unsigned char color_palette[] = {
110 0, 0, 0,
111 0, 0,192,
112 192, 0, 0,
113 192, 0,192,
114 0,192, 0,
115 0,192,192,
116 192,192, 0,
117 192,192,192,
118 0, 0, 0,
119 0, 0,255,
120 255, 0, 0,
121 255, 0,255,
122 0,255, 0,
123 0,255,255,
124 255,255, 0,
125 255,255,255
126 };
127
128 Image
129 *image;
130
131 MagickBooleanType
132 status;
133
134 Quantum
135 *q;
136
137 ssize_t
138 count;
139
140 /*
141 Open image file.
142 */
143 assert(image_info != (const ImageInfo *) NULL);
144 assert(image_info->signature == MagickCoreSignature);
145 if (image_info->debug != MagickFalse)
146 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
147 image_info->filename);
148 assert(exception != (ExceptionInfo *) NULL);
149 assert(exception->signature == MagickCoreSignature);
150 image=AcquireImage(image_info,exception);
151 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
152 if (status == MagickFalse)
153 {
154 image=DestroyImageList(image);
155 return((Image *) NULL);
156 }
157 image->columns = 256;
158 image->rows = 192;
159 status=SetImageExtent(image,image->columns,image->rows,exception);
160 if (status == MagickFalse)
161 return(DestroyImageList(image));
162 count=ReadBlob(image,6144,(unsigned char *) zxscr);
163 if (count != 6144)
164 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
165 count=ReadBlob(image,768,(unsigned char *) zxattr);
166 if (count != 768)
167 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
168 for(zonenr=0;zonenr<3;zonenr++)
169 {
170 for(zoneline=0;zoneline<8;zoneline++)
171 {
172 for(octetline=0;octetline<8;octetline++)
173 {
174 for(octetnr=(zoneline*32);octetnr<((zoneline*32)+32);octetnr++)
175 {
176 octet_val = zxscr[octetnr+(256*octetline)+(zonenr*2048)];
177 attr_nr = zxattr[octetnr+(256*zonenr)];
178
179 pix = (((8*octetnr)-(256*zoneline)));
180 piy = ((octetline+(8*zoneline)+(zonenr*64)));
181
182 pbin = binar;
183 abin = attrbin;
184
185 one_nr=1;
186
187 for(z=0;z<8;z++)
188 {
189 if(octet_val&one_nr)
190 {
191 *pbin = 1;
192 } else {
193 *pbin = 0;
194 }
195 one_nr=one_nr*2;
196 pbin++;
197 }
198
199 one_nr = 1;
200
201 for(z=0;z<8;z++)
202 {
203 if(attr_nr&one_nr)
204 {
205 *abin = 1;
206 } else {
207 *abin = 0;
208 }
209 one_nr=one_nr*2;
210 abin++;
211 }
212
213 ink = (attrbin[0]+(2*attrbin[1])+(4*attrbin[2]));
214 paper = (attrbin[3]+(2*attrbin[4])+(4*attrbin[5]));
215 bright = attrbin[6];
216
217 if(bright) { ink=ink+8; paper=paper+8; }
218
219 for(z=7;z>-1;z--)
220 {
221 q=QueueAuthenticPixels(image,pix,piy,1,1,exception);
222 if (q == (Quantum *) NULL)
223 break;
224
225 if(binar[z])
226 {
227 SetPixelRed(image,ScaleCharToQuantum(
228 color_palette[3*ink]),q);
229 SetPixelGreen(image,ScaleCharToQuantum(
230 color_palette[1+(3*ink)]),q);
231 SetPixelBlue(image,ScaleCharToQuantum(
232 color_palette[2+(3*ink)]),q);
233 } else {
234 SetPixelRed(image,ScaleCharToQuantum(
235 color_palette[3*paper]),q);
236 SetPixelGreen(image,ScaleCharToQuantum(
237 color_palette[1+(3*paper)]),q);
238 SetPixelBlue(image,ScaleCharToQuantum(
239 color_palette[2+(3*paper)]),q);
240 }
241
242 pix++;
243 }
244 }
245 }
246 }
247 }
248 (void) CloseBlob(image);
249 return(GetFirstImageInList(image));
250 }
251
252 /*
253 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
254 % %
255 % %
256 % %
257 % R e g i s t e r S C R I m a g e %
258 % %
259 % %
260 % %
261 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
262 %
263 % RegisterSCRImage() adds attributes for the SCR image format to
264 % the list of supported formats. The attributes include the image format
265 % tag, a method to read and/or write the format, whether the format
266 % supports the saving of more than one frame to the same file or blob,
267 % whether the format supports native in-memory I/O, and a brief
268 % description of the format.
269 %
270 % The format of the RegisterSCRImage method is:
271 %
272 % size_t RegisterSCRImage(void)
273 %
274 */
RegisterSCRImage(void)275 ModuleExport size_t RegisterSCRImage(void)
276 {
277 MagickInfo
278 *entry;
279
280 entry=AcquireMagickInfo("SCR","SCR","ZX-Spectrum SCREEN$");
281 entry->decoder=(DecodeImageHandler *) ReadSCRImage;
282 entry->flags^=CoderAdjoinFlag;
283 (void) RegisterMagickInfo(entry);
284 return(MagickImageCoderSignature);
285 }
286
287 /*
288 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
289 % %
290 % %
291 % %
292 % U n r e g i s t e r S C R I m a g e %
293 % %
294 % %
295 % %
296 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
297 %
298 % UnregisterSCRImage() removes format registrations made by the
299 % SCR module from the list of supported formats.
300 %
301 % The format of the UnregisterSCRImage method is:
302 %
303 % UnregisterSCRImage(void)
304 %
305 */
UnregisterSCRImage(void)306 ModuleExport void UnregisterSCRImage(void)
307 {
308 (void) UnregisterMagickInfo("SCR");
309 }
310