]>
git.ipfire.org Git - thirdparty/cups.git/blob - filter/image-sgilib.c
2 * "$Id: image-sgilib.c 7221 2008-01-16 22:20:08Z mike $"
4 * SGI image file format library routines for the Common UNIX Printing
7 * Copyright 2007-2008 by Apple Inc.
8 * Copyright 1993-2005 by Easy Software Products.
10 * These coded instructions, statements, and computer programs are the
11 * property of Apple Inc. and are protected by Federal copyright
12 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
13 * which should have been included with this file. If this file is
14 * file is missing or damaged, see the license at "http://www.cups.org/".
16 * This file is subject to the Apple OS-Developed Software exception.
20 * sgiClose() - Close an SGI image file.
21 * sgiGetRow() - Get a row of image data from a file.
22 * sgiOpen() - Open an SGI image file for reading or writing.
23 * sgiOpenFile() - Open an SGI image file for reading or writing.
24 * sgiPutRow() - Put a row of image data to a file.
25 * getlong() - Get a 32-bit big-endian integer.
26 * getshort() - Get a 16-bit big-endian integer.
27 * putlong() - Put a 32-bit big-endian integer.
28 * putshort() - Put a 16-bit big-endian integer.
29 * read_rle8() - Read 8-bit RLE data.
30 * read_rle16() - Read 16-bit RLE data.
31 * write_rle8() - Write 8-bit RLE data.
32 * write_rle16() - Write 16-bit RLE data.
35 #include "image-sgi.h"
42 static int getlong(FILE *);
43 static int getshort(FILE *);
44 static int putlong(long, FILE *);
45 static int putshort(unsigned short, FILE *);
46 static int read_rle8(FILE *, unsigned short *, int);
47 static int read_rle16(FILE *, unsigned short *, int);
48 static int write_rle8(FILE *, unsigned short *, int);
49 static int write_rle16(FILE *, unsigned short *, int);
53 * 'sgiClose()' - Close an SGI image file.
56 int /* O - 0 on success, -1 on error */
57 sgiClose(sgi_t
*sgip
) /* I - SGI image */
59 int i
; /* Return status */
60 long *offset
; /* Looping var for offset table */
66 if (sgip
->mode
== SGI_WRITE
&& sgip
->comp
!= SGI_COMP_NONE
)
69 * Write the scanline offset table to the file...
72 fseek(sgip
->file
, 512, SEEK_SET
);
74 for (i
= sgip
->ysize
* sgip
->zsize
, offset
= sgip
->table
[0];
77 if (putlong(offset
[0], sgip
->file
) < 0)
80 for (i
= sgip
->ysize
* sgip
->zsize
, offset
= sgip
->length
[0];
83 if (putlong(offset
[0], sgip
->file
) < 0)
87 if (sgip
->table
!= NULL
)
93 if (sgip
->length
!= NULL
)
95 free(sgip
->length
[0]);
99 if (sgip
->comp
== SGI_COMP_ARLE
)
100 free(sgip
->arle_row
);
102 i
= fclose(sgip
->file
);
110 * 'sgiGetRow()' - Get a row of image data from a file.
113 int /* O - 0 on success, -1 on error */
114 sgiGetRow(sgi_t
*sgip
, /* I - SGI image */
115 unsigned short *row
, /* O - Row to read */
116 int y
, /* I - Line to read */
117 int z
) /* I - Channel to read */
119 int x
; /* X coordinate */
120 long offset
; /* File offset */
125 y
< 0 || y
>= sgip
->ysize
||
126 z
< 0 || z
>= sgip
->zsize
)
133 * Seek to the image row - optimize buffering by only seeking if
137 offset
= 512 + (y
+ z
* sgip
->ysize
) * sgip
->xsize
* sgip
->bpp
;
138 if (offset
!= ftell(sgip
->file
))
139 fseek(sgip
->file
, offset
, SEEK_SET
);
143 for (x
= sgip
->xsize
; x
> 0; x
--, row
++)
144 *row
= getc(sgip
->file
);
148 for (x
= sgip
->xsize
; x
> 0; x
--, row
++)
149 *row
= getshort(sgip
->file
);
154 offset
= sgip
->table
[z
][y
];
155 if (offset
!= ftell(sgip
->file
))
156 fseek(sgip
->file
, offset
, SEEK_SET
);
159 return (read_rle8(sgip
->file
, row
, sgip
->xsize
));
161 return (read_rle16(sgip
->file
, row
, sgip
->xsize
));
169 * 'sgiOpen()' - Open an SGI image file for reading or writing.
172 sgi_t
* /* O - New image */
173 sgiOpen(const char *filename
, /* I - File to open */
174 int mode
, /* I - Open mode (SGI_READ or SGI_WRITE) */
175 int comp
, /* I - Type of compression */
176 int bpp
, /* I - Bytes per pixel */
177 int xsize
, /* I - Width of image in pixels */
178 int ysize
, /* I - Height of image in pixels */
179 int zsize
) /* I - Number of channels */
181 sgi_t
*sgip
; /* New SGI image file */
182 FILE *file
; /* Image file pointer */
185 if (mode
== SGI_READ
)
186 file
= fopen(filename
, "rb");
188 file
= fopen(filename
, "wb+");
193 if ((sgip
= sgiOpenFile(file
, mode
, comp
, bpp
, xsize
, ysize
, zsize
)) == NULL
)
201 * 'sgiOpenFile()' - Open an SGI image file for reading or writing.
204 sgi_t
* /* O - New image */
205 sgiOpenFile(FILE *file
, /* I - File to open */
206 int mode
, /* I - Open mode (SGI_READ or SGI_WRITE) */
207 int comp
, /* I - Type of compression */
208 int bpp
, /* I - Bytes per pixel */
209 int xsize
, /* I - Width of image in pixels */
210 int ysize
, /* I - Height of image in pixels */
211 int zsize
) /* I - Number of channels */
213 int i
, j
; /* Looping var */
214 char name
[80]; /* Name of file in image header */
215 short magic
; /* Magic number */
216 sgi_t
*sgip
; /* New image pointer */
219 if ((sgip
= calloc(sizeof(sgi_t
), 1)) == NULL
)
227 sgip
->mode
= SGI_READ
;
229 magic
= getshort(sgip
->file
);
230 if (magic
!= SGI_MAGIC
)
236 sgip
->comp
= getc(sgip
->file
);
237 sgip
->bpp
= getc(sgip
->file
);
238 getshort(sgip
->file
); /* Dimensions */
239 sgip
->xsize
= getshort(sgip
->file
);
240 sgip
->ysize
= getshort(sgip
->file
);
241 sgip
->zsize
= getshort(sgip
->file
);
242 getlong(sgip
->file
); /* Minimum pixel */
243 getlong(sgip
->file
); /* Maximum pixel */
248 * This file is compressed; read the scanline tables...
251 fseek(sgip
->file
, 512, SEEK_SET
);
253 if ((sgip
->table
= calloc(sgip
->zsize
, sizeof(long *))) == NULL
)
259 if ((sgip
->table
[0] = calloc(sgip
->ysize
* sgip
->zsize
,
260 sizeof(long))) == NULL
)
267 for (i
= 1; i
< sgip
->zsize
; i
++)
268 sgip
->table
[i
] = sgip
->table
[0] + i
* sgip
->ysize
;
270 for (i
= 0; i
< sgip
->zsize
; i
++)
271 for (j
= 0; j
< sgip
->ysize
; j
++)
272 sgip
->table
[i
][j
] = getlong(sgip
->file
);
280 bpp
< 1 || bpp
> 2 ||
281 comp
< SGI_COMP_NONE
|| comp
> SGI_COMP_ARLE
)
287 sgip
->mode
= SGI_WRITE
;
289 putshort(SGI_MAGIC
, sgip
->file
);
290 putc((sgip
->comp
= comp
) != 0, sgip
->file
);
291 putc(sgip
->bpp
= bpp
, sgip
->file
);
292 putshort(3, sgip
->file
); /* Dimensions */
293 putshort(sgip
->xsize
= xsize
, sgip
->file
);
294 putshort(sgip
->ysize
= ysize
, sgip
->file
);
295 putshort(sgip
->zsize
= zsize
, sgip
->file
);
298 putlong(0, sgip
->file
); /* Minimum pixel */
299 putlong(255, sgip
->file
); /* Maximum pixel */
303 putlong(-32768, sgip
->file
); /* Minimum pixel */
304 putlong(32767, sgip
->file
); /* Maximum pixel */
306 putlong(0, sgip
->file
); /* Reserved */
308 memset(name
, 0, sizeof(name
));
309 fwrite(name
, sizeof(name
), 1, sgip
->file
);
311 for (i
= 0; i
< 102; i
++)
312 putlong(0, sgip
->file
);
316 case SGI_COMP_NONE
: /* No compression */
318 * This file is uncompressed. To avoid problems with sparse files,
319 * we need to write blank pixels for the entire image...
324 for (i
= xsize
* ysize
* zsize
; i
> 0; i
--)
329 for (i
= xsize
* ysize
* zsize
; i
> 0; i
--)
330 putshort(0, sgip
->file
);
334 case SGI_COMP_ARLE
: /* Aggressive RLE */
335 sgip
->arle_row
= calloc(xsize
, sizeof(unsigned short));
336 sgip
->arle_offset
= 0;
338 case SGI_COMP_RLE
: /* Run-Length Encoding */
340 * This file is compressed; write the (blank) scanline tables...
343 for (i
= 2 * ysize
* zsize
; i
> 0; i
--)
344 putlong(0, sgip
->file
);
346 sgip
->firstrow
= ftell(sgip
->file
);
347 sgip
->nextrow
= ftell(sgip
->file
);
348 if ((sgip
->table
= calloc(sgip
->zsize
, sizeof(long *))) == NULL
)
354 if ((sgip
->table
[0] = calloc(sgip
->ysize
* sgip
->zsize
,
355 sizeof(long))) == NULL
)
362 for (i
= 1; i
< sgip
->zsize
; i
++)
363 sgip
->table
[i
] = sgip
->table
[0] + i
* sgip
->ysize
;
365 if ((sgip
->length
= calloc(sgip
->zsize
, sizeof(long *))) == NULL
)
372 if ((sgip
->length
[0] = calloc(sgip
->ysize
* sgip
->zsize
,
373 sizeof(long))) == NULL
)
381 for (i
= 1; i
< sgip
->zsize
; i
++)
382 sgip
->length
[i
] = sgip
->length
[0] + i
* sgip
->ysize
;
397 * 'sgiPutRow()' - Put a row of image data to a file.
400 int /* O - 0 on success, -1 on error */
401 sgiPutRow(sgi_t
*sgip
, /* I - SGI image */
402 unsigned short *row
, /* I - Row to write */
403 int y
, /* I - Line to write */
404 int z
) /* I - Channel to write */
406 int x
; /* X coordinate */
407 long offset
; /* File offset */
412 y
< 0 || y
>= sgip
->ysize
||
413 z
< 0 || z
>= sgip
->zsize
)
420 * Seek to the image row - optimize buffering by only seeking if
424 offset
= 512 + (y
+ z
* sgip
->ysize
) * sgip
->xsize
* sgip
->bpp
;
425 if (offset
!= ftell(sgip
->file
))
426 fseek(sgip
->file
, offset
, SEEK_SET
);
430 for (x
= sgip
->xsize
; x
> 0; x
--, row
++)
431 putc(*row
, sgip
->file
);
435 for (x
= sgip
->xsize
; x
> 0; x
--, row
++)
436 putshort(*row
, sgip
->file
);
441 if (sgip
->table
[z
][y
] != 0)
445 * First check the last row written...
448 if (sgip
->arle_offset
> 0)
450 for (x
= 0; x
< sgip
->xsize
; x
++)
451 if (row
[x
] != sgip
->arle_row
[x
])
454 if (x
== sgip
->xsize
)
456 sgip
->table
[z
][y
] = sgip
->arle_offset
;
457 sgip
->length
[z
][y
] = sgip
->arle_length
;
463 * If that didn't match, search all the previous rows...
466 fseek(sgip
->file
, sgip
->firstrow
, SEEK_SET
);
472 sgip
->arle_offset
= ftell(sgip
->file
);
473 if ((sgip
->arle_length
= read_rle8(sgip
->file
, sgip
->arle_row
, sgip
->xsize
)) < 0)
479 if (memcmp(row
, sgip
->arle_row
, sgip
->xsize
* sizeof(unsigned short)) == 0)
490 sgip
->arle_offset
= ftell(sgip
->file
);
491 if ((sgip
->arle_length
= read_rle16(sgip
->file
, sgip
->arle_row
, sgip
->xsize
)) < 0)
497 if (memcmp(row
, sgip
->arle_row
, sgip
->xsize
* sizeof(unsigned short)) == 0)
505 if (x
== sgip
->xsize
)
507 sgip
->table
[z
][y
] = sgip
->arle_offset
;
508 sgip
->length
[z
][y
] = sgip
->arle_length
;
512 fseek(sgip
->file
, 0, SEEK_END
); /* Clear EOF */
515 if (sgip
->table
[z
][y
] != 0)
518 offset
= sgip
->table
[z
][y
] = sgip
->nextrow
;
520 if (offset
!= ftell(sgip
->file
))
521 fseek(sgip
->file
, offset
, SEEK_SET
);
524 x
= write_rle8(sgip
->file
, row
, sgip
->xsize
);
526 x
= write_rle16(sgip
->file
, row
, sgip
->xsize
);
528 if (sgip
->comp
== SGI_COMP_ARLE
)
530 sgip
->arle_offset
= offset
;
531 sgip
->arle_length
= x
;
532 memcpy(sgip
->arle_row
, row
, sgip
->xsize
* sizeof(unsigned short));
535 sgip
->nextrow
= ftell(sgip
->file
);
536 sgip
->length
[z
][y
] = x
;
546 * 'getlong()' - Get a 32-bit big-endian integer.
549 static int /* O - Long value */
550 getlong(FILE *fp
) /* I - File to read from */
552 unsigned char b
[4]; /* Bytes from file */
556 return ((b
[0] << 24) | (b
[1] << 16) | (b
[2] << 8) | b
[3]);
561 * 'getshort()' - Get a 16-bit big-endian integer.
564 static int /* O - Short value */
565 getshort(FILE *fp
) /* I - File to read from */
567 unsigned char b
[2]; /* Bytes from file */
571 return ((b
[0] << 8) | b
[1]);
576 * 'putlong()' - Put a 32-bit big-endian integer.
579 static int /* O - 0 on success, -1 on error */
580 putlong(long n
, /* I - Long to write */
581 FILE *fp
) /* I - File to write to */
583 if (putc(n
>> 24, fp
) == EOF
)
585 if (putc(n
>> 16, fp
) == EOF
)
587 if (putc(n
>> 8, fp
) == EOF
)
589 if (putc(n
, fp
) == EOF
)
597 * 'putshort()' - Put a 16-bit big-endian integer.
600 static int /* O - 0 on success, -1 on error */
601 putshort(unsigned short n
, /* I - Short to write */
602 FILE *fp
) /* I - File to write to */
604 if (putc(n
>> 8, fp
) == EOF
)
606 if (putc(n
, fp
) == EOF
)
614 * 'read_rle8()' - Read 8-bit RLE data.
617 static int /* O - Value on success, -1 on error */
618 read_rle8(FILE *fp
, /* I - File to read from */
619 unsigned short *row
, /* O - Data */
620 int xsize
) /* I - Width of data in pixels */
622 int i
, /* Looping var */
623 ch
, /* Current character */
624 count
, /* RLE count */
625 length
; /* Number of bytes read... */
632 if ((ch
= getc(fp
)) == EOF
)
642 for (i
= 0; i
< count
; i
++, row
++, xsize
--, length
++)
649 for (i
= 0; i
< count
; i
++, row
++, xsize
--)
654 return (xsize
> 0 ? -1 : length
);
659 * 'read_rle16()' - Read 16-bit RLE data.
662 static int /* O - Value on success, -1 on error */
663 read_rle16(FILE *fp
, /* I - File to read from */
664 unsigned short *row
, /* O - Data */
665 int xsize
) /* I - Width of data in pixels */
667 int i
, /* Looping var */
668 ch
, /* Current character */
669 count
, /* RLE count */
670 length
; /* Number of bytes read... */
677 if ((ch
= getshort(fp
)) == EOF
)
687 for (i
= 0; i
< count
; i
++, row
++, xsize
--, length
++)
694 for (i
= 0; i
< count
; i
++, row
++, xsize
--)
699 return (xsize
> 0 ? -1 : length
* 2);
704 * 'write_rle8()' - Write 8-bit RLE data.
707 static int /* O - Length on success, -1 on error */
708 write_rle8(FILE *fp
, /* I - File to write to */
709 unsigned short *row
, /* I - Data */
710 int xsize
) /* I - Width of data in pixels */
712 int length
, /* Length in bytes */
713 count
, /* Number of repeating pixels */
715 x
; /* Current column */
716 unsigned short *start
, /* Start of current sequence */
717 repeat
; /* Repeated pixel */
720 for (x
= xsize
, length
= 0; x
> 0;)
726 while (x
> 0 && (row
[-2] != row
[-1] || row
[-1] != row
[0]))
738 i
= count
> 126 ? 126 : count
;
741 if (putc(128 | i
, fp
) == EOF
)
747 if (putc(*start
, fp
) == EOF
)
764 while (x
> 0 && *row
== repeat
)
773 i
= count
> 126 ? 126 : count
;
776 if (putc(i
, fp
) == EOF
)
780 if (putc(repeat
, fp
) == EOF
)
788 if (putc(0, fp
) == EOF
)
796 * 'write_rle16()' - Write 16-bit RLE data.
799 static int /* O - Length in words */
800 write_rle16(FILE *fp
, /* I - File to write to */
801 unsigned short *row
, /* I - Data */
802 int xsize
) /* I - Width of data in pixels */
804 int length
, /* Length in words */
805 count
, /* Number of repeating pixels */
807 x
; /* Current column */
808 unsigned short *start
, /* Start of current sequence */
809 repeat
; /* Repeated pixel */
812 for (x
= xsize
, length
= 0; x
> 0;)
818 while (x
> 0 && (row
[-2] != row
[-1] || row
[-1] != row
[0]))
830 i
= count
> 126 ? 126 : count
;
833 if (putshort(128 | i
, fp
) == EOF
)
839 if (putshort(*start
, fp
) == EOF
)
856 while (x
> 0 && *row
== repeat
)
865 i
= count
> 126 ? 126 : count
;
868 if (putshort(i
, fp
) == EOF
)
872 if (putshort(repeat
, fp
) == EOF
)
880 if (putshort(0, fp
) == EOF
)
888 * End of "$Id: image-sgilib.c 7221 2008-01-16 22:20:08Z mike $".