# input-img.c: read Interleaf .img files. # # Copyright (C) 1992, 2011 Free Software Foundation, Inc. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #include "config.h" #include "file-input.h" #include "main.h" #include "image-header.h" #include "input-img.h" /* Where the input comes from. */ static FILE *img_input_file; static string img_input_filename; /* What we'll read the raw data for each scanline into. */ static one_byte *line_in_bytes; /* How big `line_in_bytes' is, in both bytes and pixels. */ static unsigned byte_width; static unsigned pixel_width; static unsigned pixel_depth; /* Macros for convenient input. The routines are defined in kbase. */ #define IMG_MATCH_BYTE(v) match_byte (v, img_input_file, img_input_filename) #define IMG_GET_TWO() get_two (img_input_file, img_input_filename) #define IMG_GET_FOUR() get_four (img_input_file, img_input_filename) /* Only one file can be open at a time. We do no path searching. If FILENAME can't be opened, we quit. */ void img_open_input_file (string filename) { assert (img_input_file == NULL); img_input_file = xfopen (filename, "r"); img_input_filename = filename; } /* Close the input file. If it hasn't been opened, we quit. */ void img_close_input_file () { assert (img_input_file != NULL); xfclose (img_input_file, img_input_filename); img_input_file = NULL; } /* Read the header information. Modifies the global image_header in main.c. */ void img_get_header () { unsigned flags; unsigned pixels_per_short; unsigned short_width; /* The ``magic number''. */ IMG_MATCH_BYTE (0211); IMG_MATCH_BYTE ('O'); IMG_MATCH_BYTE ('P'); IMG_MATCH_BYTE ('S'); /* The version number. */ IMG_MATCH_BYTE (0); IMG_MATCH_BYTE (2); image_header.hres = IMG_GET_TWO (); image_header.vres = IMG_GET_TWO (); flags = IMG_GET_FOUR (); if (flags != 0) FATAL1 ("img_get_header: Expected flags to be zero, not %u", flags); image_header.width = IMG_GET_TWO (); image_header.height = IMG_GET_TWO (); pixel_depth = image_header.depth = IMG_GET_TWO (); image_header.format = IMG_GET_TWO (); if (image_header.format != 0) FATAL1 ("img_get_header: Expected format to be zero, not %u", image_header.format); /* Allocate the space that we will read into (since that space is the same from scanline to scanline). The width is derived from the header information, which must already have been read. Specifically, the width in the header is given in bits. Each scanline is padded to a 16-bit boundary. For example, suppose the header width = 1516, that is 94.75 shorts; we round up to 95, thus getting a scanline width of 1520 bits, or 190 bytes. (For monochrome images.) */ pixel_width = image_header.width; pixels_per_short = 16 / image_header.depth; short_width = pixel_width / pixels_per_short + (pixel_width % pixels_per_short != 0); byte_width = short_width * 2; line_in_bytes = xmalloc (byte_width); } /* Read one scanline of the image, returning each bit of the scanline in a separate byte. We may use the `line_in_bytes' variable, allocated in `img_get_header' just above, to read into. */ boolean img_get_scanline (one_byte *line_in_pixels) { /* No point in using temp. buffer if pixels and bytes are the same. */ if (fread (line_in_bytes, byte_width, 1, img_input_file) != 1) { if (feof (img_input_file)) return false; else FATAL1 ("img_get_scanline: fread of %u bytes failed", byte_width); } /* Don't handle cases other than depth 1 or 8. */ if (pixel_depth == 1) { unsigned this_bit, this_byte, mask; for (this_bit = 0, this_byte = 0, mask = 0x80; this_bit < pixel_width; this_bit++) { /* Somewhere along the line, black and white got reversed. */ line_in_pixels[this_bit] = (line_in_bytes[this_byte] & mask) == 0; if (this_bit % 8 == 0) { this_byte = this_bit / 8; mask = 0x80; } else mask >>= 1; } } else memcpy (line_in_pixels, line_in_bytes, byte_width); print_scanline (line_in_pixels, pixel_width); return true; }