Class: Pxlsrt::Smart

Inherits:
Object
  • Object
show all
Defined in:
lib/pxlsrt/smart.rb

Overview

Smart sorting uses sorted-finding algorithms to create bands to sort, as opposed to brute sorting which doesn’t care for the content or sorteds, just a specified range to create bands.

Class Method Summary collapse

Class Method Details

.smart(input, o = {}) ⇒ Object

The main attraction of the Smart class. Returns a ChunkyPNG::Image that is sorted according to the options provided. Will raise any error that occurs.



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
# File 'lib/pxlsrt/smart.rb', line 19

def self.smart(input, o={})
  startTime=Time.now
  defOptions={
    :reverse => false,
    :vertical => false,
    :diagonal => false,
    :smooth => false,
    :method => "sum-rgb",
    :verbose => false,
    :absolute => false,
    :threshold => 20,
    :trusted => false,
    :middle => false
  }
  defRules={
    :reverse => :anything,
    :vertical => [false, true],
    :diagonal => [false, true],
    :smooth => [false, true],
    :method => Pxlsrt::Colors::METHODS,
    :verbose => [false, true],
    :absolute => [false, true],
    :threshold => [{:class => [Float, Fixnum]}],
    :trusted => [false, true],
    :middle => :anything
  }
  options=defOptions.merge(o)
  if o.length==0 or options[:trusted]==true or (options[:trusted]==false and o.length!=0 and Pxlsrt::Helpers.checkOptions(options, defRules)!=false)
    Pxlsrt::Helpers.verbose("Options are all good.") if options[:verbose]
    if input.class==String
      Pxlsrt::Helpers.verbose("Getting image from file...") if options[:verbose]
      if File.file?(input)
        if Pxlsrt::Colors.isPNG?(input)
          input=ChunkyPNG::Image.from_file(input)
        else
          Pxlsrt::Helpers.error("File #{input} is not a valid PNG.") if options[:verbose]
          raise "Invalid PNG"
        end
      else
        Pxlsrt::Helpers.error("File #{input} doesn't exist!") if options[:verbose]
        raise "File doesn't exist"
      end
    elsif input.class!=String and input.class!=ChunkyPNG::Image
      Pxlsrt::Helpers.error("Input is not a filename or ChunkyPNG::Image") if options[:verbose]
      raise "Invalid input (must be filename or ChunkyPNG::Image)"
    end
    Pxlsrt::Helpers.verbose("Smart mode.") if options[:verbose]
    png=Pxlsrt::Image.new(input)
    if !options[:vertical] and !options[:diagonal]
      Pxlsrt::Helpers.verbose("Retrieving rows") if options[:verbose]
      lines = png.horizontalLines
    elsif options[:vertical] and !options[:diagonal]
      Pxlsrt::Helpers.verbose("Retrieving columns") if options[:verbose]
      lines = png.verticalLines
    elsif !options[:vertical] and options[:diagonal]
      Pxlsrt::Helpers.verbose("Retrieving diagonals") if options[:verbose]
      lines = png.diagonalLines
    elsif options[:vertical] and options[:diagonal]
      Pxlsrt::Helpers.verbose("Retrieving diagonals") if options[:verbose]
      lines = png.rDiagonalLines
    end
    Pxlsrt::Helpers.verbose("Retrieving edges") if options[:verbose]
    png.getSobels
    if !options[:diagonal]
      iterator = 0...(lines.length)
    else
      iterator = lines.keys
    end
    prr = 0
    len = iterator.to_a.length
    Pxlsrt::Helpers.progress("Dividing and pixel sorting lines", prr, len) if options[:verbose]
    for k in iterator
      line = lines[k]
      divisions = []
      division = []
      if line.length > 1
        for pixel in 0...(line.length)
          if !options[:vertical] and !options[:diagonal]
            xy = png.horizontalXY(k, pixel)
          elsif options[:vertical] and !options[:diagonal]
            xy = png.verticalXY(k, pixel)
          elsif !options[:vertical] and options[:diagonal]
            xy = png.diagonalXY(k, pixel)
          elsif options[:vertical] and options[:diagonal]
            xy = png.rDiagonalXY(k, pixel)
          end
          pxlSobel = png.getSobelAndColor(xy["x"], xy["y"])
          if division.length == 0 or (options[:absolute] ? pxlSobel["sobel"] : pxlSobel["sobel"] - division.last["sobel"]) <= options[:threshold]
            division.push(pxlSobel)
          else
            divisions.push(division)
            division = [pxlSobel]
          end
          if pixel == line.length - 1
            divisions.push(division)
            division = []
          end
        end
      end
      newLine = []
      for band in divisions
        newLine.concat(
          Pxlsrt::Helpers.handlePixelSort(
            band.map { |sobelAndColor| sobelAndColor["color"] },
            options
          )
        )
      end
      if !options[:diagonal]
        png.replaceHorizontal(k, newLine) if !options[:vertical]
        png.replaceVertical(k, newLine) if options[:vertical]
      else
        png.replaceDiagonal(k, newLine) if !options[:vertical]
        png.replaceRDiagonal(k, newLine) if options[:vertical]
      end
      prr += 1
      Pxlsrt::Helpers.progress("Dividing and pixel sorting lines", prr, len) if options[:verbose]
    end
    endTime=Time.now
    timeElapsed=endTime-startTime
    if timeElapsed < 60
      Pxlsrt::Helpers.verbose("Took #{timeElapsed.round(4)} second#{ timeElapsed.round(4)!=1.0 ? "s" : "" }.") if options[:verbose]
    else
      minutes=(timeElapsed/60).floor
      seconds=(timeElapsed % 60).round(4)
      Pxlsrt::Helpers.verbose("Took #{minutes} minute#{ minutes!=1 ? "s" : "" } and #{seconds} second#{ seconds!=1.0 ? "s" : "" }.") if options[:verbose]
    end
    Pxlsrt::Helpers.verbose("Returning ChunkyPNG::Image...") if options[:verbose]
    return png.returnModified
  else
    Pxlsrt::Helpers.error("Options specified do not follow the correct format.") if options[:verbose]
    raise "Bad options"
  end
end

.suite(inputFileName, outputFileName, o = {}) ⇒ Object

Uses Pxlsrt::Smart.smart to input and output from pne method.



11
12
13
14
15
16
# File 'lib/pxlsrt/smart.rb', line 11

def self.suite(inputFileName, outputFileName, o={})
  kml=Pxlsrt::Smart.smart(inputFileName, o)
  if Pxlsrt::Helpers.contented(kml)
    kml.save(outputFileName)
  end
end