/usr/lib/python2.7/dist-packages/ginga/rv/plugins/Compose.py is in python-ginga 2.6.1-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 | #
# Compose.py -- Compose plugin for Ginga reference viewer
#
# This is open-source software licensed under a BSD license.
# Please see the file LICENSE.txt for details.
#
import os
from ginga.gw import Widgets
from ginga.misc import Bunch
from ginga import RGBImage, LayerImage
from ginga import GingaPlugin
import numpy
try:
from PIL import Image
have_PIL = True
except ImportError:
have_PIL = False
class ComposeImage(RGBImage.RGBImage, LayerImage.LayerImage):
def __init__(self, *args, **kwdargs):
RGBImage.RGBImage.__init__(self, *args, **kwdargs)
LayerImage.LayerImage.__init__(self)
class Compose(GingaPlugin.LocalPlugin):
"""
Usage:
Start the Compose plugin from the Operation menu--the tab should
show up under "Dialogs"
- Press "New Image" to start composing a new RGB image.
- drag your three constituent images that will make up the R, G and B
planes to the main viewer window--drag them in the order R (red),
G (green) and B (blue).
In the plugin, the R, G and B iamges should show up as three slider
controls in the Layers area of the plugin.
You should now have a composite three color image in the Compose preview
window. Most likely the image does not have good cut levels set, so you
may want to set cut levels on the image using any of the usual cut levels
controls.
- Play with the alpha levels of each layer using the sliders in the
Compose plugin, when you release a slider the image should update.
- When you see something you like you can save it to a file using the
"Save As" button.
"""
def __init__(self, fv, fitsimage):
# superclass defines some variables for us, like logger
super(Compose, self).__init__(fv, fitsimage)
self.limage = None
self.count = 0
self.layertag = 'compose-canvas'
self.dc = fv.get_draw_classes()
canvas = self.dc.DrawingCanvas()
canvas.set_callback('drag-drop', self.drop_file_cb)
canvas.set_surface(self.fitsimage)
self.canvas = canvas
self.gui_up = False
def build_gui(self, container):
top = Widgets.VBox()
top.set_border_width(4)
vbox, sw, orientation = Widgets.get_oriented_box(container)
vbox.set_border_width(4)
vbox.set_spacing(2)
self.msg_font = self.fv.get_font("sansFont", 12)
tw = Widgets.TextArea(wrap=True, editable=False)
tw.set_font(self.msg_font)
self.tw = tw
fr = Widgets.Expander("Instructions")
fr.set_widget(tw)
vbox.add_widget(fr, stretch=0)
fr = Widgets.Frame("Compositing")
captions = (("Compose Type:", 'label', "Compose Type", 'combobox'),
("New Image", 'button', "Insert Layer", 'button'),
)
w, b = Widgets.build_info(captions)
self.w.update(b)
fr.set_widget(w)
vbox.add_widget(fr, stretch=0)
combobox = b.compose_type
index = 0
for name in ('Alpha', 'RGB'):
combobox.append_text(name)
index += 1
combobox.set_index(1)
#combobox.add_callback('activated', self.set_combine_cb)
b.new_image.add_callback('activated', lambda w: self.new_cb())
b.new_image.set_tooltip("Start a new composite image")
b.insert_layer.add_callback('activated', lambda w: self.insert_cb())
b.insert_layer.set_tooltip("Insert channel image as layer")
fr = Widgets.Frame("Layers")
self.w.scales = fr
vbox.add_widget(fr, stretch=0)
hbox = Widgets.HBox()
hbox.set_border_width(4)
hbox.set_spacing(4)
btn = Widgets.Button("Save Image As")
btn.add_callback('activated', lambda w: self.save_as_cb())
hbox.add_widget(btn, stretch=0)
self.entry2 = Widgets.TextEntry()
hbox.add_widget(self.entry2, stretch=1)
self.entry2.add_callback('activated', lambda *args: self.save_as_cb())
vbox.add_widget(hbox, stretch=0)
# spacer
vbox.add_widget(Widgets.Label(''), stretch=1)
top.add_widget(sw, stretch=1)
btns = Widgets.HBox()
btns.set_border_width(4)
btns.set_spacing(4)
btn = Widgets.Button("Close")
btn.add_callback('activated', lambda w: self.close())
btns.add_widget(btn)
btns.add_widget(Widgets.Label(''), stretch=1)
top.add_widget(btns, stretch=0)
container.add_widget(top, stretch=1)
self.gui_up = True
def _gui_config_layers(self):
# remove all old scales
self.logger.debug("removing layer alpha controls")
self.w.scales.remove_all()
self.logger.debug("building layer alpha controls")
# construct a new vbox of alpha controls
captions = []
num_layers = self.limage.num_layers()
for i in range(num_layers):
layer = self.limage.get_layer(i)
captions.append((layer.name+':', 'label', 'layer_%d' % i, 'hscale'))
w, b = Widgets.build_info(captions)
self.w.update(b)
for i in range(num_layers):
layer = self.limage.get_layer(i)
adj = b['layer_%d' % (i)]
lower, upper = 0, 100
adj.set_limits(lower, upper, incr_value=1)
#adj.set_decimals(2)
adj.set_value(int(layer.alpha * 100.0))
#adj.set_tracking(True)
adj.add_callback('value-changed', self.set_opacity_cb, i)
self.logger.debug("adding layer alpha controls")
self.w.scales.set_widget(w)
def new_cb(self):
#self.fitsimage.clear()
name = "composite%d" % (self.count)
self.limage = ComposeImage(logger=self.logger, order='RGB')
# Alpha or RGB composition?
index = self.w.compose_type.get_index()
if index == 0:
self.limage.compose = 'alpha'
else:
self.limage.compose = 'rgb'
self._gui_config_layers()
self.limage.set(name=name, nothumb=True)
def _get_layer_attributes(self):
# Get layer name
idx = self.limage.num_layers()
if self.limage.compose == 'rgb':
idx = min(idx, 2)
names = ['Red', 'Green', 'Blue']
name = names[idx]
else:
name = 'layer%d' % (idx)
# Get alpha
alpha = 1.0
bnch = Bunch.Bunch(name=name, alpha=alpha, idx=idx)
return bnch
def insert_image(self, image):
if self.limage is None:
self.new_cb()
nlayers = self.limage.num_layers()
if (self.limage.compose == 'rgb') and (nlayers >= 3):
self.fv.show_error("There are already 3 layers")
return
elif nlayers == 0:
# populate metadata from first layer
metadata = image.get_metadata()
self.limage.update_metadata(metadata)
attrs = self._get_layer_attributes()
self.limage.insert_layer(attrs.idx, image, name=attrs.name,
alpha=attrs.alpha)
self._gui_config_layers()
self.logger.debug("setting layer image")
self.fitsimage.set_image(self.limage)
def insert_cb(self):
image = self.fitsimage.get_image()
self.insert_image(image)
def drop_file_cb(self, viewer, paths):
self.logger.info("dropped files: %s" % str(paths))
for path in paths[:3]:
image = self.fv.load_image(path)
self.insert_image(image)
return True
def set_opacity_cb(self, w, val, idx):
alpha = val / 100.0
self.limage.set_alpha(idx, alpha)
def _alphas_controls_to_layers(self):
self.logger.debug("updating layers in %s from controls" % self.limage)
num_layers = self.limage.num_layers()
vals = []
for i in range(num_layers):
alpha = self.w['layer_%d' % i].get_value() / 100.0
vals.append(alpha)
self.logger.debug("%d: alpha=%f" % (i, alpha))
i += 1
self.limage.set_alphas(vals)
def _alphas_layers_to_controls(self):
self.logger.debug("updating controls from %s" % self.limage)
num_layers = self.limage.num_layers()
for i in range(num_layers):
layer = self.limage.get_layer(i)
self.logger.debug("%d: alpha=%f" % (i, layer.alpha))
ctrlname = 'layer_%d' % (i)
if ctrlname in self.w:
self.w[ctrlname].set_value(layer.alpha * 100.0)
i += 1
def add_to_channel_cb(self):
image = self.limage.copy()
name = "composite%d" % (self.count)
self.count += 1
image.set(name=name)
self.fv.add_image(name, image)
def save_as_file(self, path, image, order='RGB'):
if not have_PIL:
raise Exception("You need to install PIL or pillow to save images")
data = image.get_data()
viewer = self.fitsimage
rgbmap = viewer.get_rgbmap()
vmin, vmax = 0, rgbmap.get_hash_size() - 1
# Cut levels on the full image, with settings from viewer
autocuts = viewer.autocuts
loval, hival = viewer.get_cut_levels()
data = autocuts.cut_levels(data, loval, hival,
vmin=vmin, vmax=vmax)
# result becomes an index array fed to the RGB mapper
if not numpy.issubdtype(data.dtype, numpy.dtype('uint')):
data = data.astype(numpy.uint)
# get RGB array using settings from viewer
rgbobj = rgbmap.get_rgbarray(data, order=order,
image_order='RGB')
data = rgbobj.get_array(order)
# Save image using PIL
p_image = Image.fromarray(data)
p_image.save(path)
def save_as_cb(self):
path = str(self.entry2.get_text()).strip()
if not path.startswith('/'):
path = os.path.join('.', path)
image = self.fitsimage.get_image()
self.fv.nongui_do(self.fv.error_wrap, self.save_as_file, path, image)
def instructions(self):
self.tw.set_text("""Drag R, then G then B images to the window. Adjust cut levels and contrast as desired.
Then manipulate channel mix using the sliders.""")
def close(self):
self.fv.stop_local_plugin(self.chname, str(self))
return True
def start(self):
self.instructions()
# start ruler drawing operation
p_canvas = self.fitsimage.get_canvas()
try:
obj = p_canvas.get_object_by_tag(self.layertag)
except KeyError:
# Add ruler layer
p_canvas.add(self.canvas, tag=self.layertag)
self.resume()
def pause(self):
self.canvas.ui_setActive(False)
def resume(self):
self.canvas.ui_setActive(True)
def stop(self):
# remove the canvas from the image
p_canvas = self.fitsimage.get_canvas()
try:
p_canvas.delete_object_by_tag(self.layertag)
except:
pass
self.canvas.ui_setActive(False)
self.fv.show_status("")
self.gui_up = False
def redo(self):
pass
def __str__(self):
return 'compose'
#END
|