コード例 #1
0
ファイル: gimp_spine.py プロジェクト: jclounge/gimp-spine
def spine_export(img, active_layer, compression, dir_name, json_filename, export_visible_only, reverse_draw_order, autocrop_layers, padding_amt):
    ''' Plugin entry point
    '''

    orig_img = img
    orig_active_layer = pdb.gimp_image_get_active_layer(orig_img)
    img = pdb.gimp_image_duplicate(orig_img)

    # Set up the initial JSON format
    output = {
        'bones': [{'name': 'root'}],
        'slots': [],
        'skins': {'default': {}},
        'animations': {}
    }
    slots = output['slots']
    attachments = output['skins']['default']

    # Iterate through the layers, extracting their info into the JSON output
    # and saving the layers as individual images
    for layer in img.layers:
       if (layer.visible or not(export_visible_only)):
               to_save = process_layer(img, layer, slots, attachments, reverse_draw_order, autocrop_layers, padding_amt)
               save_layers(img, to_save, compression, dir_name)

    # Write the JSON output
    if not json_filename:
        json_filename = os.path.splitext(os.path.basename(orig_img.filename))[0]

    with open(os.path.join(dir_name, '%s.json' % json_filename), 'w') as json_file:
        json.dump(output, json_file)

    pdb.gimp_image_delete(img)
    pdb.gimp_image_set_active_layer(orig_img, orig_active_layer)
コード例 #2
0
 def _get_in_memory_preview(self, layer):
   self._preview_width, self._preview_height = self._get_preview_size(
     layer.width, layer.height)
   self._preview_scaling_factor = self._preview_width / layer.width
   
   image_preview = self._get_image_preview()
   
   if image_preview is None or not pdb.gimp_image_is_valid(image_preview):
     return None
   
   if not image_preview.layers:
     pg.pdbutils.try_delete_image(image_preview)
     return None
   
   if image_preview.base_type != gimpenums.RGB:
     pdb.gimp_image_convert_rgb(image_preview)
   
   layer_preview = image_preview.layers[0]
   
   if layer_preview.mask is not None:
     layer_preview.remove_mask(gimpenums.MASK_APPLY)
   
   # Recompute the size as the layer may have been resized during the export.
   self._preview_width, self._preview_height = self._get_preview_size(
     layer_preview.width, layer_preview.height)
   
   self._preview_width, self._preview_height, preview_data = self._get_preview_data(
     layer_preview, self._preview_width, self._preview_height)
   
   layer_preview_pixbuf = self._get_preview_pixbuf(
     layer_preview, self._preview_width, self._preview_height, preview_data)
   
   pdb.gimp_image_delete(image_preview)
   
   return layer_preview_pixbuf
コード例 #3
0
def try_delete_image(image):
  """
  Delete the specified image. If the image does not exist, do not raise any
  exception.
  """
  if pdb.gimp_image_is_valid(image):
    pdb.gimp_image_delete(image)
コード例 #4
0
def load_layer(filepath, image, strip_file_extension=False, layer_to_load_index=0):
  """
  Load an image as a layer given its file path to an existing `image`. Return
  the layer.
  
  The layer is loaded at the end of the image.
  
  Layers names are basenames of the corresponding files. If
  `strip_file_extension` is True, remove the file extension from layer names.
  
  If the file contains multiple layers, specify the index of the desired layer
  to load. Only top-level layers are supported (i.e. not layers inside layer
  groups). If the index is greater than the number of layers in the loaded
  image or is negative, load and return the last layer.
  """
  
  loaded_image = pdb.gimp_file_load(filepath, os.path.basename(filepath))
  
  if layer_to_load_index >= len(image.layers) or layer_to_load_index < 0:
    layer_to_load_index = -1
  
  layer = pdb.gimp_layer_new_from_drawable(
    loaded_image.layers[layer_to_load_index], image)
  layer.name = os.path.basename(filepath)
  if strip_file_extension:
    layer.name = os.path.splitext(layer.name)[0]
  
  pdb.gimp_image_insert_layer(image, layer, None, len(image.layers))
  
  pdb.gimp_image_delete(loaded_image)
  
  return layer
コード例 #5
0
    def tearDownClass(cls):
        pdb.gimp_image_delete(cls.test_image)
        for image in cls.expected_images.values():
            pdb.gimp_image_delete(image)

        pdb.gimp_context_pop()
        pdb.gimp_progress_end()
コード例 #6
0
def load_layer(filepath, image, strip_file_extension=False, layer_to_load_index=0):
  """
  Load an image as a layer given its file path to an existing `image`. Return
  the layer.
  
  The layer is loaded at the end of the image.
  
  Layers names are basenames of the corresponding files. If
  `strip_file_extension` is `True`, remove the file extension from layer names.
  
  If the file contains multiple layers, specify the index of the desired layer
  to load. Only top-level layers are supported (i.e. not layers inside layer
  groups). If the index is greater than the number of layers in the loaded
  image or is negative, load and return the last layer.
  """
  loaded_image = pdb.gimp_file_load(filepath, os.path.basename(filepath))
  
  if layer_to_load_index >= len(image.layers) or layer_to_load_index < 0:
    layer_to_load_index = -1
  
  layer = pdb.gimp_layer_new_from_drawable(
    loaded_image.layers[layer_to_load_index], image)
  layer.name = os.path.basename(filepath)
  if strip_file_extension:
    layer.name = os.path.splitext(layer.name)[0]
  
  pdb.gimp_image_insert_layer(image, layer, None, len(image.layers))
  
  pdb.gimp_image_delete(loaded_image)
  
  return layer
コード例 #7
0
def try_delete_image(image):
    """
  Delete the specified image. If the image does not exist, do not raise any
  exception.
  """
    if pdb.gimp_image_is_valid(image):
        pdb.gimp_image_delete(image)
コード例 #8
0
 def tearDownClass(cls):
   pdb.gimp_image_delete(cls.test_image)
   for image in cls.expected_images.values():
     pdb.gimp_image_delete(image)
   
   pdb.gimp_context_pop()
   pdb.gimp_progress_end()
コード例 #9
0
def main(settings=None):
  if not settings:
    settings = settings_plugin.create_settings()
  
  image = pdb.gimp_file_load(TEST_IMAGES_FILEPATH, os.path.basename(TEST_IMAGES_FILEPATH))
  
  layer_tree = pg.itemtree.LayerTree(image, name=pg.config.SOURCE_NAME, is_filtered=True)
  
  settings["special/image"].set_value(image)
  
  gui_main.ExportLayersDialog(layer_tree, settings, run_gui_func=take_screenshots)
  
  pdb.gimp_image_delete(image)
コード例 #10
0
def take_and_process_screenshot(
      screenshots_dirpath, filename, settings, decoration_offsets):
  #HACK: Wait a while until the window is fully shown.
  time.sleep(1)
  
  screenshot_image = take_screenshot()
  
  crop_to_dialog(screenshot_image, settings, decoration_offsets)
  
  pdb.gimp_file_save(
    screenshot_image,
    screenshot_image.active_layer,
    os.path.join(screenshots_dirpath, filename),
    filename)
  
  pdb.gimp_image_delete(screenshot_image)
コード例 #11
0
    def _cleanup(self, exception_occurred=False):
        if pygimplib.config.DEBUG_IMAGE_PROCESSING:
            pdb.gimp_display_delete(self._display_id)

        _copy_non_modifying_parasites(self._image_copy, self.image)

        pdb.gimp_image_undo_thaw(self._image_copy)
        if ((not self._keep_image_copy or self._use_another_image_copy)
                or exception_occurred):
            pdb.gimp_image_delete(self._image_copy)
            if self._use_another_image_copy:
                pdb.gimp_image_undo_thaw(self._another_image_copy)
                if exception_occurred:
                    pdb.gimp_image_delete(self._another_image_copy)

        for tagged_layer_copy in self._tagged_layer_copies.values():
            if tagged_layer_copy is not None:
                pdb.gimp_item_delete(tagged_layer_copy)

        pdb.gimp_context_pop()
コード例 #12
0
    def _get_in_memory_preview(self, layer):
        self._preview_width, self._preview_height = self._get_preview_size(
            layer.width, layer.height)
        self._preview_scaling_factor = self._preview_width / layer.width

        image_preview = self._get_image_preview()

        if image_preview is None or not pdb.gimp_image_is_valid(image_preview):
            return None

        if not image_preview.layers:
            pg.pdbutils.try_delete_image(image_preview)
            return None

        if image_preview.base_type != gimpenums.RGB:
            pdb.gimp_image_convert_rgb(image_preview)

        layer_preview = image_preview.layers[0]

        if layer_preview.mask is not None:
            layer_preview.remove_mask(gimpenums.MASK_APPLY)

        # Recompute the size as the layer may have been resized during the export.
        self._preview_width, self._preview_height = self._get_preview_size(
            layer_preview.width, layer_preview.height)

        self._preview_width, self._preview_height, preview_data = self._get_preview_data(
            layer_preview, self._preview_width, self._preview_height)

        layer_preview_pixbuf = self._get_preview_pixbuf(
            layer_preview, self._preview_width, self._preview_height,
            preview_data)

        pdb.gimp_image_delete(image_preview)

        return layer_preview_pixbuf
コード例 #13
0
def compare_layers(
      layers, compare_alpha_channels=True, compare_has_alpha=False,
      apply_layer_attributes=True, apply_layer_masks=True):
  """
  Return True if the contents of all specified layers are identical, False
  otherwise. Layer groups are also supported.
  
  The default values of the optional parameters correspond to how the layers are
  displayed in the image canvas.
  
  If `compare_alpha_channels` is True, perform comparison of alpha channels.
  
  If `compare_has_alpha` is True, compare the presence of alpha channels in all
  layers - if some layers have alpha channels and others don't, do not perform
  full comparison and return False.
  
  If `apply_layer_attributes` is True, take the layer attributes (opacity, mode)
  into consideration when comparing, otherwise ignore them.
  
  If `apply_layer_masks` is True, apply layer masks if they are enabled. If the
  masks are disabled or `apply_layer_masks` is False, layer masks are ignored.
  """
  
  def _copy_layers(image, layers, parent=None, position=0):
    layer_group = pdb.gimp_layer_group_new(image)
    pdb.gimp_image_insert_layer(image, layer_group, parent, position)
    
    for layer in layers:
      copy_and_paste_layer(layer, image, parent=layer_group)
    
    for layer in layer_group.children:
      layer.visible = True
    
    return layer_group
  
  def _process_layers(image, layer_group, apply_layer_attributes, apply_layer_masks):
    for layer in layer_group.children:
      if pdb.gimp_item_is_group(layer):
        layer = merge_layer_group(layer)
      else:
        if layer.opacity != 100.0 or layer.mode != gimpenums.NORMAL_MODE:
          if apply_layer_attributes:
            layer = _apply_layer_attributes(image, layer, layer_group)
          else:
            layer.opacity = 100.0
            layer.mode = gimpenums.NORMAL_MODE
        
        if layer.mask is not None:
          if apply_layer_masks and pdb.gimp_layer_get_apply_mask(layer):
            pdb.gimp_layer_remove_mask(layer, gimpenums.MASK_APPLY)
          else:
            pdb.gimp_layer_remove_mask(layer, gimpenums.MASK_DISCARD)
  
  def _is_identical(layer_group):
    layer_group.children[0].mode = gimpenums.DIFFERENCE_MODE
    
    for layer in layer_group.children[1:]:
      layer.visible = False
    
    for layer in layer_group.children[1:]:
      layer.visible = True
      
      histogram_data = pdb.gimp_histogram(layer_group, gimpenums.HISTOGRAM_VALUE, 1, 255)
      percentile = histogram_data[5]
      identical = percentile == 0.0
      
      if not identical:
        return False
      
      layer.visible = False
    
    return True
  
  def _set_mask_to_layer(layer):
    pdb.gimp_edit_copy(layer.mask)
    floating_sel = pdb.gimp_edit_paste(layer, True)
    pdb.gimp_floating_sel_anchor(floating_sel)
    pdb.gimp_layer_remove_mask(layer, gimpenums.MASK_DISCARD)
  
  def _apply_layer_attributes(image, layer, parent_group):
    temp_group = pdb.gimp_layer_group_new(image)
    pdb.gimp_image_insert_layer(image, temp_group, parent_group, 0)
    pdb.gimp_image_reorder_item(image, layer, temp_group, 0)
    layer = merge_layer_group(temp_group)
    
    return layer
  
  all_layers_have_same_size = (
    all(layers[0].width == layer.width for layer in layers[1:])
    and all(layers[0].height == layer.height for layer in layers[1:]))
  if not all_layers_have_same_size:
    return False
  
  all_layers_are_same_image_type = (
    all(layers[0].type == layer.type for layer in layers[1:]))
  if compare_has_alpha and not all_layers_are_same_image_type:
    return False
  
  image = gimp.Image(1, 1, gimpenums.RGB)
  layer_group = _copy_layers(image, layers)
  pdb.gimp_image_resize_to_layers(image)
  _process_layers(image, layer_group, apply_layer_attributes, apply_layer_masks)
  
  has_alpha = False
  for layer in layer_group.children:
    if pdb.gimp_drawable_has_alpha(layer):
      has_alpha = True
      # Extract alpha channel to the layer mask (to compare alpha channels).
      mask = pdb.gimp_layer_create_mask(layer, gimpenums.ADD_ALPHA_MASK)
      pdb.gimp_layer_add_mask(layer, mask)
      pdb.gimp_layer_set_apply_mask(layer, False)
      # Remove alpha channel
      pdb.gimp_layer_flatten(layer)
  
  identical = _is_identical(layer_group)
  
  if identical and compare_alpha_channels and has_alpha:
    for layer in layer_group.children:
      if layer.mask is not None:
        _set_mask_to_layer(layer)
      else:
        pdb.gimp_drawable_fill(layer, gimpenums.WHITE_FILL)
    
    identical = _is_identical(layer_group)
  
  pdb.gimp_image_delete(image)
  
  return identical
コード例 #14
0
def compare_layers(
      layers,
      compare_alpha_channels=True,
      compare_has_alpha=False,
      apply_layer_attributes=True,
      apply_layer_masks=True):
  """
  Return `True` if the contents of all specified layers are identical, `False`
  otherwise. Layer groups are also supported.
  
  The default values of the optional parameters correspond to how the layers are
  displayed in the image canvas.
  
  If `compare_alpha_channels` is `True`, perform comparison of alpha channels.
  
  If `compare_has_alpha` is `True`, compare the presence of alpha channels in
  all layers - if some layers have alpha channels and others do not, then do not
  perform full comparison and return `False`.
  
  If `apply_layer_attributes` is `True`, take the layer attributes (opacity,
  mode) into consideration when comparing, otherwise ignore them.
  
  If `apply_layer_masks` is `True`, apply layer masks if they are enabled. If
  the masks are disabled or `apply_layer_masks` is `False`, layer masks are
  ignored.
  """
  
  def _copy_layers(image, layers, parent=None, position=0):
    layer_group = pdb.gimp_layer_group_new(image)
    pdb.gimp_image_insert_layer(image, layer_group, parent, position)
    
    for layer in layers:
      copy_and_paste_layer(layer, image, parent=layer_group)
    
    for layer in layer_group.children:
      layer.visible = True
    
    return layer_group
  
  def _process_layers(image, layer_group, apply_layer_attributes, apply_layer_masks):
    for layer in layer_group.children:
      if pdb.gimp_item_is_group(layer):
        layer = merge_layer_group(layer)
      else:
        if layer.opacity != 100.0 or layer.mode != gimpenums.NORMAL_MODE:
          if apply_layer_attributes:
            layer = _apply_layer_attributes(image, layer, layer_group)
          else:
            layer.opacity = 100.0
            layer.mode = gimpenums.NORMAL_MODE
        
        if layer.mask is not None:
          if apply_layer_masks and pdb.gimp_layer_get_apply_mask(layer):
            pdb.gimp_layer_remove_mask(layer, gimpenums.MASK_APPLY)
          else:
            pdb.gimp_layer_remove_mask(layer, gimpenums.MASK_DISCARD)
  
  def _is_identical(layer_group):
    layer_group.children[0].mode = gimpenums.DIFFERENCE_MODE
    
    for layer in layer_group.children[1:]:
      layer.visible = False
    
    for layer in layer_group.children[1:]:
      layer.visible = True
      
      if gimp.version >= (2, 10):
        histogram_data = pdb.gimp_drawable_histogram(
          layer_group, gimpenums.HISTOGRAM_VALUE, 1 / 255, 1.0)
      else:
        histogram_data = pdb.gimp_histogram(
          layer_group, gimpenums.HISTOGRAM_VALUE, 1, 255)
      
      percentile = histogram_data[5]
      identical = percentile == 0.0
      
      if not identical:
        return False
      
      layer.visible = False
    
    return True
  
  def _set_mask_to_layer(layer):
    pdb.gimp_edit_copy(layer.mask)
    floating_sel = pdb.gimp_edit_paste(layer, True)
    pdb.gimp_floating_sel_anchor(floating_sel)
    pdb.gimp_layer_remove_mask(layer, gimpenums.MASK_DISCARD)
  
  def _apply_layer_attributes(image, layer, parent_group):
    temp_group = pdb.gimp_layer_group_new(image)
    pdb.gimp_image_insert_layer(image, temp_group, parent_group, 0)
    pdb.gimp_image_reorder_item(image, layer, temp_group, 0)
    layer = merge_layer_group(temp_group)
    
    return layer
  
  def _prepare_for_comparison_of_alpha_channels(layer):
    _extract_alpha_channel_to_layer_mask(layer)
    _remove_alpha_channel(layer)
  
  def _extract_alpha_channel_to_layer_mask(layer):
    mask = pdb.gimp_layer_create_mask(layer, gimpenums.ADD_ALPHA_MASK)
    pdb.gimp_layer_add_mask(layer, mask)
    pdb.gimp_layer_set_apply_mask(layer, False)
  
  def _remove_alpha_channel(layer):
    pdb.gimp_layer_flatten(layer)
  
  all_layers_have_same_size = (
    all(layers[0].width == layer.width for layer in layers[1:])
    and all(layers[0].height == layer.height for layer in layers[1:]))
  if not all_layers_have_same_size:
    return False
  
  all_layers_are_same_image_type = (
    all(layers[0].type == layer.type for layer in layers[1:]))
  if compare_has_alpha and not all_layers_are_same_image_type:
    return False
  
  image = gimp.Image(1, 1, gimpenums.RGB)
  layer_group = _copy_layers(image, layers)
  pdb.gimp_image_resize_to_layers(image)
  _process_layers(image, layer_group, apply_layer_attributes, apply_layer_masks)
  
  has_alpha = False
  for layer in layer_group.children:
    if pdb.gimp_drawable_has_alpha(layer):
      has_alpha = True
      _prepare_for_comparison_of_alpha_channels(layer)
  
  identical = _is_identical(layer_group)
  
  if identical and compare_alpha_channels and has_alpha:
    for layer in layer_group.children:
      if layer.mask is not None:
        _set_mask_to_layer(layer)
      else:
        pdb.gimp_drawable_fill(layer, gimpenums.WHITE_FILL)
    
    identical = _is_identical(layer_group)
  
  pdb.gimp_image_delete(image)
  
  return identical
コード例 #15
0
 def _reload_image(cls):
     pdb.gimp_image_delete(cls.test_image)
     cls.test_image = cls._load_image()
コード例 #16
0
    def tearDown(self):
        if self.image_with_results is not None:
            pdb.gimp_image_delete(self.image_with_results)

        if os.path.exists(self.output_dirpath):
            shutil.rmtree(self.output_dirpath)
コード例 #17
0
 def tearDown(self):
   if self.image_with_results is not None:
     pdb.gimp_image_delete(self.image_with_results)
   
   if os.path.exists(self.output_dirpath):
     shutil.rmtree(self.output_dirpath)
コード例 #18
0
 def tearDownClass(cls):
   pdb.gimp_image_delete(cls.image)
コード例 #19
0
 def _reload_image(cls):
   pdb.gimp_image_delete(cls.test_image)
   cls.test_image = cls._load_image()