summaryrefslogtreecommitdiff
path: root/imageto/input-img.c
blob: 522ea50381e86827710a35a01e2673d25d9ccadb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# 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 <http://www.gnu.org/licenses/>.
#

#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;
}