diff options
Diffstat (limited to 'src/page.vala')
-rw-r--r-- | src/page.vala | 538 |
1 files changed, 248 insertions, 290 deletions
diff --git a/src/page.vala b/src/page.vala index f27258c..34613b3 100644 --- a/src/page.vala +++ b/src/page.vala @@ -19,44 +19,150 @@ public enum ScanDirection public class Page { + /* Width of the page in pixels after rotation applied */ + public int width + { + get + { + if (scan_direction == ScanDirection.TOP_TO_BOTTOM || scan_direction == ScanDirection.BOTTOM_TO_TOP) + return scan_width; + else + return scan_height; + } + } + + /* Height of the page in pixels after rotation applied */ + public int height + { + get + { + if (scan_direction == ScanDirection.TOP_TO_BOTTOM || scan_direction == ScanDirection.BOTTOM_TO_TOP) + return scan_height; + else + return scan_width; + } + } + + /* true if the page is landscape (wider than the height) */ + public bool is_landscape { get { return width > height; } } + /* Resolution of page */ - private int dpi; + public int dpi { get; private set; } /* Number of rows in this page or -1 if currently unknown */ private int expected_rows; /* Bit depth */ - private int depth; + public int depth { get; private set; } /* Color profile */ - private string? color_profile; + public string? color_profile { get; set; } + + /* Width of raw scan data in pixels */ + public int scan_width { get; private set; } - /* Scanned image data */ - private int width; - private int n_rows; - private int rowstride; - private int n_channels; + /* Height of raw scan data in pixels */ + public int scan_height { get; private set; } + + /* Offset between rows in scan data */ + public int rowstride { get; private set; } + + /* Number of color channels */ + public int n_channels { get; private set; } + + /* Pixel data */ private uchar[] pixels; /* Page is getting data */ - private bool scanning; + public bool is_scanning { get; private set; } /* true if have some page data */ - private bool has_data_; + public bool has_data { get; private set; } /* Expected next scan row */ - private int scan_line; + public int scan_line { get; private set; } + + /* true if scan contains color information */ + public bool is_color { get { return n_channels > 1; } } /* Rotation of scanned data */ - private ScanDirection scan_direction = ScanDirection.TOP_TO_BOTTOM; + private ScanDirection scan_direction_; + public ScanDirection scan_direction + { + get { return scan_direction_; } + + set + { + if (scan_direction_ == value) + return; + + /* Work out how many times it has been rotated to the left */ + var size_has_changed = false; + var left_steps = (int) (value - scan_direction_); + if (left_steps < 0) + left_steps += 4; + if (left_steps != 2) + size_has_changed = true; + + /* Rotate crop */ + if (has_crop) + { + switch (left_steps) + { + /* 90 degrees counter-clockwise */ + case 1: + var t = crop_x; + crop_x = crop_y; + crop_y = width - (t + crop_width); + t = crop_width; + crop_width = crop_height; + crop_height = t; + break; + /* 180 degrees */ + case 2: + crop_x = width - (crop_x + crop_width); + crop_y = width - (crop_y + crop_height); + break; + /* 90 degrees clockwise */ + case 3: + var t = crop_y; + crop_y = crop_x; + crop_x = height - (t + crop_height); + t = crop_width; + crop_width = crop_height; + crop_height = t; + break; + } + } + + scan_direction_ = value; + if (size_has_changed) + size_changed (); + scan_direction_changed (); + if (has_crop) + crop_changed (); + } + + default = ScanDirection.TOP_TO_BOTTOM; + } + + /* True if the page has a crop set */ + public bool has_crop { get; private set; } - /* Crop */ - private bool has_crop_; - private string? crop_name; - private int crop_x; - private int crop_y; - private int crop_width; - private int crop_height; + /* Name of the crop if using a named crop */ + public string? crop_name { get; private set; } + + /* X co-ordinate of top left crop corner */ + public int crop_x { get; private set; } + + /* Y co-ordinate of top left crop corner */ + public int crop_y { get; private set; } + + /* Width of crop in pixels */ + public int crop_width { get; private set; } + + /* Height of crop in pixels*/ + public int crop_height { get; private set; } public signal void pixels_changed (); public signal void size_changed (); @@ -69,40 +175,75 @@ public class Page { if (scan_direction == ScanDirection.TOP_TO_BOTTOM || scan_direction == ScanDirection.BOTTOM_TO_TOP) { - this.width = width; - n_rows = height; + scan_width = width; + scan_height = height; } else { - this.width = height; - n_rows = width; + scan_width = height; + scan_height = width; } this.dpi = dpi; this.scan_direction = scan_direction; } + public Page.from_data (int scan_width, + int scan_height, + int rowstride, + int n_channels, + int depth, + int dpi, + ScanDirection scan_direction, + string? color_profile, + uchar[]? pixels, + bool has_crop, + string? crop_name, + int crop_x, + int crop_y, + int crop_width, + int crop_height) + { + this.scan_width = scan_width; + this.scan_height = scan_height; + this.expected_rows = scan_height; + this.rowstride = rowstride; + this.n_channels = n_channels; + this.depth = depth; + this.dpi = dpi; + this.scan_direction = scan_direction; + this.color_profile = color_profile; + this.pixels = pixels; + has_data = pixels != null; + this.has_crop = has_crop; + this.crop_name = crop_name; + this.crop_x = crop_x; + this.crop_y = crop_y; + this.crop_width = crop_width; + this.crop_height = crop_height; + } + public void set_page_info (ScanPageInfo info) { expected_rows = info.height; dpi = (int) info.dpi; /* Create a white page */ - width = info.width; - n_rows = info.height; + scan_width = info.width; + scan_height = info.height; /* Variable height, try 50% of the width for now */ - if (n_rows < 0) - n_rows = width / 2; + if (scan_height < 0) + scan_height = scan_width / 2; depth = info.depth; n_channels = info.n_channels; - rowstride = (width * depth * n_channels + 7) / 8; - pixels.resize (n_rows * rowstride); + rowstride = (scan_width * depth * n_channels + 7) / 8; + pixels.resize (scan_height * rowstride); return_if_fail (pixels != null); /* Fill with white */ if (depth == 1) - Memory.set (pixels, 0x00, n_rows * rowstride); + Memory.set (pixels, 0x00, scan_height * rowstride); else - Memory.set (pixels, 0xFF, n_rows * rowstride); + Memory.set (pixels, 0xFF, scan_height * rowstride); size_changed (); pixels_changed (); @@ -110,47 +251,23 @@ public class Page public void start () { - scanning = true; + is_scanning = true; scan_line_changed (); } - public bool is_scanning () - { - return scanning; - } - - public bool has_data () - { - return has_data_; - } - - public bool is_color () - { - return n_channels > 1; - } - - public int get_scan_line () - { - return scan_line; - } - private void parse_line (ScanLine line, int n, out bool size_changed) { - int line_number; - - line_number = line.number + n; + var line_number = line.number + n; /* Extend image if necessary */ size_changed = false; - while (line_number >= get_scan_height ()) + while (line_number >= scan_height) { - int rows; - /* Extend image */ - rows = n_rows; - n_rows = rows + width / 2; - debug ("Extending image from %d lines to %d lines", rows, n_rows); - pixels.resize (n_rows * rowstride); + var rows = scan_height; + scan_height = rows + scan_width / 2; + debug ("Extending image from %d lines to %d lines", rows, scan_height); + pixels.resize (scan_height * rowstride); size_changed = true; } @@ -170,7 +287,7 @@ public class Page for (var i = 0; i < line.n_lines; i++) parse_line (line, i, out size_has_changed); - has_data_ = true; + has_data = true; if (size_has_changed) size_changed (); @@ -184,18 +301,16 @@ public class Page /* Trim page */ if (expected_rows < 0 && - scan_line != get_scan_height ()) + scan_line != scan_height) { - int rows; - - rows = n_rows; - n_rows = scan_line; - pixels.resize (n_rows * rowstride); - debug ("Trimming page from %d lines to %d lines", rows, n_rows); + var rows = scan_height; + scan_height = scan_line; + pixels.resize (scan_height * rowstride); + debug ("Trimming page from %d lines to %d lines", rows, scan_height); size_has_changed = true; } - scanning = false; + is_scanning = false; if (size_has_changed) size_changed (); @@ -203,197 +318,72 @@ public class Page scan_finished (); } - public ScanDirection get_scan_direction () - { - return scan_direction; - } - - private void set_scan_direction (ScanDirection direction) - { - int left_steps, t; - bool size_has_changed = false; - int width, height; - - if (scan_direction == direction) - return; - - /* Work out how many times it has been rotated to the left */ - left_steps = direction - scan_direction; - if (left_steps < 0) - left_steps += 4; - if (left_steps != 2) - size_has_changed = true; - - width = get_width (); - height = get_height (); - - /* Rotate crop */ - if (has_crop_) - { - switch (left_steps) - { - /* 90 degrees counter-clockwise */ - case 1: - t = crop_x; - crop_x = crop_y; - crop_y = width - (t + crop_width); - t = crop_width; - crop_width = crop_height; - crop_height = t; - break; - /* 180 degrees */ - case 2: - crop_x = width - (crop_x + crop_width); - crop_y = width - (crop_y + crop_height); - break; - /* 90 degrees clockwise */ - case 3: - t = crop_y; - crop_y = crop_x; - crop_x = height - (t + crop_height); - t = crop_width; - crop_width = crop_height; - crop_height = t; - break; - } - } - - scan_direction = direction; - if (size_has_changed) - size_changed (); - scan_direction_changed (); - if (has_crop_) - crop_changed (); - } - public void rotate_left () { - var direction = scan_direction; - switch (direction) + switch (scan_direction) { case ScanDirection.TOP_TO_BOTTOM: - direction = ScanDirection.LEFT_TO_RIGHT; + scan_direction = ScanDirection.LEFT_TO_RIGHT; break; case ScanDirection.LEFT_TO_RIGHT: - direction = ScanDirection.BOTTOM_TO_TOP; + scan_direction = ScanDirection.BOTTOM_TO_TOP; break; case ScanDirection.BOTTOM_TO_TOP: - direction = ScanDirection.RIGHT_TO_LEFT; + scan_direction = ScanDirection.RIGHT_TO_LEFT; break; case ScanDirection.RIGHT_TO_LEFT: - direction = ScanDirection.TOP_TO_BOTTOM; + scan_direction = ScanDirection.TOP_TO_BOTTOM; break; } - set_scan_direction (direction); } public void rotate_right () { - var direction = scan_direction; - switch (direction) + switch (scan_direction) { case ScanDirection.TOP_TO_BOTTOM: - direction = ScanDirection.RIGHT_TO_LEFT; + scan_direction = ScanDirection.RIGHT_TO_LEFT; break; case ScanDirection.LEFT_TO_RIGHT: - direction = ScanDirection.TOP_TO_BOTTOM; + scan_direction = ScanDirection.TOP_TO_BOTTOM; break; case ScanDirection.BOTTOM_TO_TOP: - direction = ScanDirection.LEFT_TO_RIGHT; + scan_direction = ScanDirection.LEFT_TO_RIGHT; break; case ScanDirection.RIGHT_TO_LEFT: - direction = ScanDirection.BOTTOM_TO_TOP; + scan_direction = ScanDirection.BOTTOM_TO_TOP; break; } - set_scan_direction (direction); - } - - public int get_dpi () - { - return dpi; - } - - public bool is_landscape () - { - return get_width () > get_height (); - } - - public int get_width () - { - if (scan_direction == ScanDirection.TOP_TO_BOTTOM || scan_direction == ScanDirection.BOTTOM_TO_TOP) - return width; - else - return n_rows; - } - - public int get_height () - { - if (scan_direction == ScanDirection.TOP_TO_BOTTOM || scan_direction == ScanDirection.BOTTOM_TO_TOP) - return n_rows; - else - return width; - } - - public int get_depth () - { - return depth; - } - - public int get_n_channels () - { - return n_channels; - } - - public int get_rowstride () - { - return rowstride; - } - - public int get_scan_width () - { - return width; - } - - public int get_scan_height () - { - return n_rows; - } - - public void set_color_profile (string? color_profile) - { - this.color_profile = color_profile; - } - - public string get_color_profile () - { - return color_profile; } public void set_no_crop () { - if (!has_crop_) + if (!has_crop) return; - has_crop_ = false; + has_crop = false; + crop_name = null; + crop_x = 0; + crop_y = 0; + crop_width = 0; + crop_height = 0; crop_changed (); } public void set_custom_crop (int width, int height) { - //int pw, ph; - return_if_fail (width >= 1); return_if_fail (height >= 1); - - if (crop_name == null && has_crop_ && crop_width == width && crop_height == height) + + if (crop_name == null && has_crop && crop_width == width && crop_height == height) return; crop_name = null; - has_crop_ = true; + has_crop = true; crop_width = width; crop_height = height; - /*pw = get_width (); - ph = get_height (); + /*var pw = width; + var ph = height; if (crop_width < pw) crop_x = (pw - crop_width) / 2; else @@ -408,32 +398,32 @@ public class Page public void set_named_crop (string name) { - double width, height; + double w, h; switch (name) { case "A4": - width = 8.3; - height = 11.7; + w = 8.3; + h = 11.7; break; case "A5": - width = 5.8; - height = 8.3; + w = 5.8; + h = 8.3; break; case "A6": - width = 4.1; - height = 5.8; + w = 4.1; + h = 5.8; break; case "letter": - width = 8.5; - height = 11; + w = 8.5; + h = 11; break; case "legal": - width = 8.5; - height = 14; + w = 8.5; + h = 14; break; case "4x6": - width = 4; - height = 6; + w = 4; + h = 6; break; default: warning ("Unknown paper size '%s'", name); @@ -441,23 +431,22 @@ public class Page } crop_name = name; - has_crop_ = true; + has_crop = true; - var pw = get_width (); - var ph = get_height (); + var pw = width; + var ph = height; /* Rotate to match original aspect */ if (pw > ph) { - double t; - t = width; - width = height; - height = t; + var t = w; + w = h; + h = t; } /* Custom crop, make slightly smaller than original */ - crop_width = (int) (width * dpi + 0.5); - crop_height = (int) (height * dpi + 0.5); + crop_width = (int) (w * dpi + 0.5); + crop_height = (int) (h * dpi + 0.5); if (crop_width < pw) crop_x = (pw - crop_width) / 2; @@ -474,8 +463,8 @@ public class Page { return_if_fail (x >= 0); return_if_fail (y >= 0); - return_if_fail (x < get_width ()); - return_if_fail (y < get_height ()); + return_if_fail (x < width); + return_if_fail (y < height); crop_x = x; crop_y = y; @@ -484,22 +473,18 @@ public class Page public void rotate_crop () { - int t; - - if (!has_crop_) + if (!has_crop) return; - t = crop_width; + var t = crop_width; crop_width = crop_height; crop_height = t; /* Clip custom crops */ if (crop_name == null) { - int w, h; - - w = get_width (); - h = get_height (); + var w = width; + var h = height; if (crop_x + crop_width > w) crop_x = w - crop_width; @@ -520,36 +505,11 @@ public class Page crop_changed (); } - public bool has_crop () - { - return has_crop_; - } - - public void get_crop (out int x, out int y, out int width, out int height) - { - x = crop_x; - y = crop_y; - width = crop_width; - height = crop_height; - } - - public string get_named_crop () - { - return crop_name; - } - public unowned uchar[] get_pixels () { return pixels; } - public void set_pixels (uchar[] new_pixels) - { - pixels = new_pixels; - has_data_ = new_pixels != null; - pixels_changed (); - } - // FIXME: Copied from page-view, should be shared code private uchar get_sample (uchar[] pixels, int offset, int x, int depth, int n_channels, int channel) { @@ -560,29 +520,27 @@ public class Page // FIXME: Copied from page-view, should be shared code private void get_pixel (int x, int y, uchar[] pixel, int offset) { - switch (get_scan_direction ()) + switch (scan_direction) { case ScanDirection.TOP_TO_BOTTOM: break; case ScanDirection.BOTTOM_TO_TOP: - x = get_scan_width () - x - 1; - y = get_scan_height () - y - 1; + x = scan_width - x - 1; + y = scan_height - y - 1; break; case ScanDirection.LEFT_TO_RIGHT: var t = x; - x = get_scan_width () - y - 1; + x = scan_width - y - 1; y = t; break; case ScanDirection.RIGHT_TO_LEFT: var t = x; x = y; - y = get_scan_height () - t - 1; + y = scan_height - t - 1; break; } - var depth = get_depth (); - var n_channels = get_n_channels (); - var line_offset = get_rowstride () * y; + var line_offset = rowstride * y; /* Optimise for 8 bit images */ if (depth == 8 && n_channels == 3) @@ -630,7 +588,7 @@ public class Page public Gdk.Pixbuf get_image (bool apply_crop) { int l, r, t, b; - if (apply_crop && has_crop_) + if (apply_crop && has_crop) { l = crop_x; r = l + crop_width; @@ -639,19 +597,19 @@ public class Page if (l < 0) l = 0; - if (r > get_width ()) - r = get_width (); + if (r > width) + r = width; if (t < 0) t = 0; - if (b > get_height ()) - b = get_height (); + if (b > height) + b = height; } else { l = 0; - r = get_width (); + r = width; t = 0; - b = get_height (); + b = height; } var image = new Gdk.Pixbuf (Gdk.Colorspace.RGB, false, 8, r - l, b - t); |