/src/graphicsmagick/coders/hrz.c
Line | Count | Source |
1 | | /* |
2 | | % Copyright (C) 2009-2025 GraphicsMagick Group |
3 | | % |
4 | | % This program is covered by multiple licenses, which are described in |
5 | | % Copyright.txt. You should have received a copy of Copyright.txt with this |
6 | | % package; otherwise see http://www.graphicsmagick.org/www/Copyright.html. |
7 | | % |
8 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
9 | | % % |
10 | | % % |
11 | | % H H RRRR ZZZZZ % |
12 | | % H H R R ZZ % |
13 | | % HHHHH RRRR Z % |
14 | | % H H R R ZZ % |
15 | | % H H R R ZZZZZ % |
16 | | % % |
17 | | % % |
18 | | % Slow scan TV. % |
19 | | % % |
20 | | % % |
21 | | % Software Design % |
22 | | % Jaroslav Fojtik % |
23 | | % 2009-2024 % |
24 | | % % |
25 | | % % |
26 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
27 | | % |
28 | | % |
29 | | */ |
30 | | |
31 | | /* |
32 | | Include declarations. |
33 | | */ |
34 | | #include "magick/studio.h" |
35 | | #include "magick/blob.h" |
36 | | #include "magick/pixel_cache.h" |
37 | | #include "magick/log.h" |
38 | | #include "magick/magick.h" |
39 | | #include "magick/monitor.h" |
40 | | #include "magick/resize.h" |
41 | | #include "magick/utility.h" |
42 | | #include "magick/constitute.h" |
43 | | #include "magick/static.h" |
44 | | |
45 | | |
46 | | /* |
47 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
48 | | % % |
49 | | % % |
50 | | % % |
51 | | % R e a d H R Z I m a g e % |
52 | | % % |
53 | | % % |
54 | | % % |
55 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
56 | | % |
57 | | % Method ReadHRZImage reads an HRZ image file and returns it. It |
58 | | % allocates the memory necessary for the new Image structure and returns a |
59 | | % pointer to the new image. |
60 | | % |
61 | | % The format of the ReadHRZImage method is: |
62 | | % |
63 | | % Image *ReadHRZImage(const ImageInfo *image_info,ExceptionInfo *exception) |
64 | | % |
65 | | % A description of each parameter follows: |
66 | | % |
67 | | % o image: Method ReadHRZImage returns a pointer to the image after |
68 | | % reading. A null image is returned if there is a memory shortage or if |
69 | | % the image cannot be read. |
70 | | % |
71 | | % o image_info: Specifies a pointer to a ImageInfo structure. |
72 | | % |
73 | | % o exception: return any errors or warnings in this structure. |
74 | | % |
75 | | % |
76 | | */ |
77 | | static Image *ReadHRZImage(const ImageInfo *image_info,ExceptionInfo *exception) |
78 | 50 | { |
79 | 50 | Image *image; |
80 | 50 | unsigned char *BImgBuff; |
81 | 50 | const PixelPacket *q; |
82 | 50 | size_t ldblk; |
83 | 50 | unsigned long x,y,width,height; |
84 | 50 | unsigned int status; |
85 | | |
86 | | /* |
87 | | Open image file. |
88 | | */ |
89 | 50 | assert(image_info != (const ImageInfo *) NULL); |
90 | 50 | assert(image_info->signature == MagickSignature); |
91 | 50 | assert(exception != (ExceptionInfo *) NULL); |
92 | 50 | assert(exception->signature == MagickSignature); |
93 | | |
94 | 50 | image=AllocateImage(image_info); |
95 | 50 | status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); |
96 | 50 | if (status == False) |
97 | 50 | ThrowReaderException(FileOpenError,UnableToOpenFile,image); |
98 | | |
99 | | /* |
100 | | Read HRZ image. |
101 | | */ |
102 | 50 | width = 256; |
103 | 50 | height = 240; |
104 | 50 | ldblk = 3*width; |
105 | | |
106 | 50 | if (BlobIsSeekable(image)) |
107 | 50 | { |
108 | 50 | if (GetBlobSize(image) != ((magick_off_t) ((size_t)ldblk*height))) |
109 | 48 | ThrowReaderException(CorruptImageError,ImproperImageHeader,image); |
110 | 2 | } |
111 | | |
112 | 2 | image->columns = width; |
113 | 2 | image->rows = height; |
114 | 2 | image->depth = 8; |
115 | | |
116 | | /* printf("HRZ header checked OK %d,%d\n",image->colors,image->depth); */ |
117 | | |
118 | | /* If ping is true, then only set image size without reading any image data. */ |
119 | 2 | if (image_info->ping) |
120 | 0 | goto DONE_READING; |
121 | | |
122 | | /* ----- Load packed raster ----- */ |
123 | 2 | BImgBuff=MagickAllocateResourceLimitedMemory(unsigned char *, ldblk); |
124 | 2 | if (BImgBuff==NULL) |
125 | 2 | ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image); |
126 | | |
127 | 482 | for (y=0; y < height; y++) |
128 | 480 | { |
129 | 480 | if (ReadBlob(image,ldblk,(char *)BImgBuff) != ldblk) |
130 | 0 | break; |
131 | | |
132 | 369k | for (x=0; x < ldblk; x++) |
133 | 368k | { |
134 | 368k | BImgBuff[x] <<= 2; |
135 | 368k | } |
136 | | |
137 | 480 | q = SetImagePixels(image,0,y,image->columns,1); |
138 | 480 | if (q == (PixelPacket *)NULL) |
139 | 0 | break; |
140 | | |
141 | 480 | (void) ImportImagePixelArea(image,RGBQuantum,8,BImgBuff,NULL,0); |
142 | 480 | if (!SyncImagePixels(image)) |
143 | 0 | break; |
144 | 480 | } |
145 | | |
146 | 2 | if (BImgBuff!=NULL) |
147 | 2 | MagickFreeResourceLimitedMemory(unsigned char *,BImgBuff); |
148 | 2 | if ((y != height) || EOFBlob(image)) |
149 | 2 | ThrowReaderException(CorruptImageError, UnexpectedEndOfFile, image); |
150 | | |
151 | 2 | DONE_READING: |
152 | 2 | CloseBlob(image); |
153 | 2 | StopTimer(&image->timer); |
154 | 2 | return(image); |
155 | 2 | } |
156 | | |
157 | | |
158 | | /* |
159 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
160 | | % % |
161 | | % % |
162 | | % % |
163 | | % W r i t e H R Z I m a g e % |
164 | | % % |
165 | | % % |
166 | | % % |
167 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
168 | | % |
169 | | % WriteHRZImage() writes an image to a file in HRZ image format. |
170 | | % |
171 | | % The format of the WriteHRZImage method is: |
172 | | % |
173 | | % MagickBooleanType WriteHRZImage(const ImageInfo *image_info, |
174 | | % Image *image,ExceptionInfo *exception) |
175 | | % |
176 | | % A description of each parameter follows. |
177 | | % |
178 | | % o image_info: the image info. |
179 | | % |
180 | | % o image: The image. |
181 | | % |
182 | | % o exception: return any errors or warnings in this structure. |
183 | | % |
184 | | */ |
185 | | static unsigned int WriteHRZImage(const ImageInfo *image_info,Image *image) |
186 | 2 | { |
187 | 2 | int logging; |
188 | 2 | Image *hrz_image; |
189 | 2 | unsigned status; |
190 | 2 | unsigned long x, y; |
191 | 2 | ssize_t count; |
192 | 2 | unsigned char *pixels, *q; |
193 | | |
194 | | /* |
195 | | Open output image file. |
196 | | */ |
197 | 2 | assert(image_info != (const ImageInfo *) NULL); |
198 | 2 | assert(image_info->signature == MagickSignature); |
199 | 2 | assert(image != (Image *) NULL); |
200 | 2 | assert(image->signature == MagickSignature); |
201 | 2 | assert(image->exception.signature == MagickSignature); |
202 | | |
203 | 2 | logging = LogMagickEvent(CoderEvent,GetMagickModule(),"enter HRZ"); |
204 | | |
205 | 2 | status = OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); |
206 | 2 | if (status == MagickFail) |
207 | 2 | ThrowWriterException(FileOpenError,UnableToOpenFile,image); |
208 | | |
209 | 2 | hrz_image = ResizeImage(image,256,240,image->filter,1.0,&image->exception); |
210 | 2 | if (hrz_image == (Image *)NULL) |
211 | 0 | { |
212 | 0 | CloseBlob(image); |
213 | 0 | return(MagickFalse); |
214 | 0 | } |
215 | | /* |
216 | | Allocate memory for pixels. |
217 | | */ |
218 | 2 | pixels = MagickAllocateResourceLimitedClearedArray(unsigned char *, |
219 | 2 | (size_t)hrz_image->columns,3*sizeof(*pixels)); |
220 | 2 | if (pixels == (unsigned char *) NULL) |
221 | 0 | { |
222 | 0 | DestroyImage(hrz_image); |
223 | 0 | ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image); |
224 | 0 | } |
225 | | /* |
226 | | Convert MIFF to HRZ raster pixels. |
227 | | */ |
228 | 482 | for (y=0; y < hrz_image->rows; y++) |
229 | 480 | { |
230 | 480 | if (AcquireImagePixels(image,0,y,image->columns,1,&image->exception) == (const PixelPacket *)NULL) |
231 | 0 | { |
232 | 0 | status=MagickFail; |
233 | 0 | break; |
234 | 0 | } |
235 | 480 | if (ExportImagePixelArea(image,RGBQuantum,8,pixels,0,0) != MagickPass) |
236 | 0 | { |
237 | 0 | status = MagickFail; |
238 | 0 | break; |
239 | 0 | } |
240 | 480 | q = pixels; |
241 | 123k | for (x=0; x < hrz_image->columns; x++) |
242 | 122k | { |
243 | 122k | *q++ /= 4; |
244 | 122k | *q++ /= 4; |
245 | 122k | *q++ /= 4; |
246 | 122k | } |
247 | 480 | count = WriteBlob(image,(size_t) (q-pixels),pixels); |
248 | 480 | if (count != (ssize_t)(q-pixels)) |
249 | 0 | { |
250 | 0 | status = MagickFail; |
251 | 0 | break; |
252 | 0 | } |
253 | | /* status = SetImageProgress(image,SaveImageTag,y,hrz_image->rows); |
254 | | if (status == MagickFalse) |
255 | | break; */ |
256 | 480 | } |
257 | 2 | MagickFreeResourceLimitedMemory(unsigned char *,pixels); |
258 | 2 | DestroyImage(hrz_image); |
259 | 2 | status &= CloseBlob(image); |
260 | | |
261 | 2 | if (logging) |
262 | 0 | (void)LogMagickEvent(CoderEvent,GetMagickModule(),"return HRZ"); |
263 | | |
264 | 2 | return(status); |
265 | 2 | } |
266 | | |
267 | | |
268 | | |
269 | | /* |
270 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
271 | | % % |
272 | | % % |
273 | | % % |
274 | | % R e g i s t e r H R Z I m a g e % |
275 | | % % |
276 | | % % |
277 | | % % |
278 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
279 | | % |
280 | | % Method RegisterHRZImage adds attributes for the HRZ image format to |
281 | | % the list of supported formats. The attributes include the image format |
282 | | % tag, a method to read and/or write the format, whether the format |
283 | | % supports the saving of more than one frame to the same file or blob, |
284 | | % whether the format supports native in-memory I/O, and a brief |
285 | | % description of the format. |
286 | | % |
287 | | % The format of the RegisterHRZImage method is: |
288 | | % |
289 | | % RegisterHRZImage(void) |
290 | | % |
291 | | */ |
292 | | ModuleExport void RegisterHRZImage(void) |
293 | 1 | { |
294 | 1 | MagickInfo |
295 | 1 | *entry; |
296 | | |
297 | 1 | entry=SetMagickInfo("HRZ"); |
298 | 1 | entry->decoder = (DecoderHandler)ReadHRZImage; |
299 | 1 | entry->encoder = (EncoderHandler)WriteHRZImage; |
300 | 1 | entry->seekable_stream = MagickFalse; |
301 | 1 | entry->description="HRZ: Slow scan TV"; |
302 | 1 | entry->module="HRZ"; |
303 | 1 | entry->adjoin=MagickFalse; |
304 | 1 | (void) RegisterMagickInfo(entry); |
305 | 1 | } |
306 | | |
307 | | /* |
308 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
309 | | % % |
310 | | % % |
311 | | % % |
312 | | % U n r e g i s t e r H R Z I m a g e % |
313 | | % % |
314 | | % % |
315 | | % % |
316 | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
317 | | % |
318 | | % Method UnregisterHRZImage removes format registrations made by the |
319 | | % HRZ module from the list of supported formats. |
320 | | % |
321 | | % The format of the UnregisterHRZImage method is: |
322 | | % |
323 | | % UnregisterHRZImage(void) |
324 | | % |
325 | | */ |
326 | | ModuleExport void UnregisterHRZImage(void) |
327 | 0 | { |
328 | 0 | (void) UnregisterMagickInfo("HRZ"); |
329 | 0 | } |