[aseprite] 124/134: Add --trim command line option

Tobias Hansen thansen at moszumanska.debian.org
Sat Mar 14 17:10:17 UTC 2015


This is an automated email from the git hooks/post-receive script.

thansen pushed a commit to branch master
in repository aseprite.

commit 9546c0a5e3bcbc8e707a08ed83d9545a30c3c568
Author: David Capello <davidcapello at gmail.com>
Date:   Mon Feb 2 10:42:07 2015 -0300

    Add --trim command line option
---
 src/app/app.cpp                       |  38 ++++++++++--
 src/app/app_options.cpp               |   1 +
 src/app/app_options.h                 |   2 +
 src/app/commands/cmd_undo.cpp         |  12 ++--
 src/app/document_exporter.cpp         | 106 +++++++++++++++++++---------------
 src/app/document_exporter.h           |  13 ++++-
 src/app/settings/ui_settings_impl.cpp |   6 +-
 7 files changed, 117 insertions(+), 61 deletions(-)

diff --git a/src/app/app.cpp b/src/app/app.cpp
index 9119a06..7425a6b 100644
--- a/src/app/app.cpp
+++ b/src/app/app.cpp
@@ -1,5 +1,5 @@
 /* Aseprite
- * Copyright (C) 2001-2014  David Capello
+ * Copyright (C) 2001-2015  David Capello
  *
  * 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
@@ -213,6 +213,7 @@ void App::initialize(const AppOptions& options)
   PRINTF("Processing options...\n");
 
   bool ignoreEmpty = false;
+  bool trim = false;
 
   // Open file specified in the command line
   if (!options.values().empty()) {
@@ -267,6 +268,10 @@ void App::initialize(const AppOptions& options)
         else if (opt == &options.ignoreEmpty()) {
           ignoreEmpty = true;
         }
+        // --trim
+        else if (opt == &options.trim()) {
+          trim = true;
+        }
         // --filename-format
         else if (opt == &options.filenameFormat()) {
           filenameFormat = value.value();
@@ -285,7 +290,10 @@ void App::initialize(const AppOptions& options)
 
             std::string format = filenameFormat;
 
-            Command* command = CommandsModule::instance()->getCommandByName(CommandId::SaveFileCopyAs);
+            Command* saveAsCommand = CommandsModule::instance()->getCommandByName(CommandId::SaveFileCopyAs);
+            Command* trimCommand = CommandsModule::instance()->getCommandByName(CommandId::AutocropSprite);
+            Command* undoCommand = CommandsModule::instance()->getCommandByName(CommandId::Undo);
+
             if (splitLayersSaveAs) {
               std::vector<Layer*> layers;
               doc->sprite()->getLayersList(layers);
@@ -308,10 +316,21 @@ void App::initialize(const AppOptions& options)
                 fmt = filename_formatter(format,
                   value.value(), show->name(), -1, false);
 
+                // TODO --trim command with --save-as doesn't make too
+                // much sense as we lost the trim rectangle
+                // information (e.g. we don't have sheet .json) Also,
+                // we should trim each frame individually (a process
+                // that can be done only in fop_operate()).
+                if (trim)
+                  ctx->executeCommand(trimCommand);
+
                 Params params;
                 params.set("filename", fn.c_str());
                 params.set("filename-format", fmt.c_str());
-                ctx->executeCommand(command, &params);
+                ctx->executeCommand(saveAsCommand, &params);
+
+                if (trim)         // Undo trim command
+                  ctx->executeCommand(undoCommand);
               }
             }
             else {
@@ -324,10 +343,16 @@ void App::initialize(const AppOptions& options)
                   layer->setReadable(layer->name() == importLayerSaveAs);
               }
 
+              if (trim)
+                ctx->executeCommand(trimCommand);
+
               Params params;
               params.set("filename", value.value().c_str());
               params.set("filename-format", format.c_str());
-              ctx->executeCommand(command, &params);
+              ctx->executeCommand(saveAsCommand, &params);
+
+              if (trim)         // Undo trim command
+                ctx->executeCommand(undoCommand);
             }
           }
         }
@@ -400,12 +425,15 @@ void App::initialize(const AppOptions& options)
   }
 
   // Export
-  if (m_exporter != NULL) {
+  if (m_exporter) {
     PRINTF("Exporting sheet...\n");
 
     if (ignoreEmpty)
       m_exporter->setIgnoreEmptyCels(true);
 
+    if (trim)
+      m_exporter->setTrimCels(true);
+
     m_exporter->exportSheet();
     m_exporter.reset(NULL);
   }
diff --git a/src/app/app_options.cpp b/src/app/app_options.cpp
index 0557450..6438015 100644
--- a/src/app/app_options.cpp
+++ b/src/app/app_options.cpp
@@ -49,6 +49,7 @@ AppOptions::AppOptions(int argc, const char* argv[])
   , m_splitLayers(m_po.add("split-layers").description("Import each layer of the next given sprite as\na separated image in the sheet"))
   , m_importLayer(m_po.add("import-layer").requiresValue("<name>").description("Import just one layer of the next given sprite"))
   , m_ignoreEmpty(m_po.add("ignore-empty").description("Do not export empty frames/cels"))
+  , m_trim(m_po.add("trim").description("Trim all images before exporting"))
   , m_filenameFormat(m_po.add("filename-format").requiresValue("<fmt>").description("Special format to generate filenames"))
   , m_verbose(m_po.add("verbose").description("Explain what is being done"))
   , m_help(m_po.add("help").mnemonic('?').description("Display this help and exits"))
diff --git a/src/app/app_options.h b/src/app/app_options.h
index a9c5b8b..4a4d54b 100644
--- a/src/app/app_options.h
+++ b/src/app/app_options.h
@@ -57,6 +57,7 @@ public:
   const Option& splitLayers() const { return m_splitLayers; }
   const Option& importLayer() const { return m_importLayer; }
   const Option& ignoreEmpty() const { return m_ignoreEmpty; }
+  const Option& trim() const { return m_trim; }
   const Option& filenameFormat() const { return m_filenameFormat; }
 
   bool hasExporterParams() const;
@@ -85,6 +86,7 @@ private:
   Option& m_splitLayers;
   Option& m_importLayer;
   Option& m_ignoreEmpty;
+  Option& m_trim;
   Option& m_filenameFormat;
 
   Option& m_verbose;
diff --git a/src/app/commands/cmd_undo.cpp b/src/app/commands/cmd_undo.cpp
index 47b030f..954d000 100644
--- a/src/app/commands/cmd_undo.cpp
+++ b/src/app/commands/cmd_undo.cpp
@@ -103,11 +103,13 @@ void UndoCommand::onExecute(Context* context)
     }
   }
 
-  StatusBar::instance()
-    ->showTip(1000, "%s %s",
-              (m_type == Undo ? "Undid": "Redid"),
-              (m_type == Undo ? undo->getNextUndoLabel():
-                                undo->getNextRedoLabel()));
+  StatusBar* statusbar = StatusBar::instance();
+  if (statusbar)
+    statusbar->showTip(1000, "%s %s",
+      (m_type == Undo ? "Undid": "Redid"),
+      (m_type == Undo ?
+        undo->getNextUndoLabel():
+        undo->getNextRedoLabel()));
 
   // Effectively undo/redo.
   if (m_type == Undo)
diff --git a/src/app/document_exporter.cpp b/src/app/document_exporter.cpp
index dcbfd20..6b8ca01 100644
--- a/src/app/document_exporter.cpp
+++ b/src/app/document_exporter.cpp
@@ -1,5 +1,5 @@
 /* Aseprite
- * Copyright (C) 2001-2013  David Capello
+ * Copyright (C) 2001-2015  David Capello
  *
  * 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
@@ -59,7 +59,10 @@ public:
     m_sprite(sprite),
     m_layer(layer),
     m_frame(frame),
-    m_filename(filename) {
+    m_filename(filename),
+    m_originalSize(sprite->width(), sprite->height()),
+    m_trimmedBounds(0, 0, sprite->width(), sprite->height()),
+    m_inTextureBounds(0, 0, sprite->width(), sprite->height()) {
   }
 
   Document* document() const { return m_document; }
@@ -128,37 +131,39 @@ public:
     const Layer* oldLayer = NULL;
 
     gfx::Point framePt(0, 0);
+    gfx::Size rowSize(0, 0);
+
     for (auto& sample : samples) {
       const Sprite* sprite = sample.sprite();
       const Layer* layer = sample.layer();
-      gfx::Size size(sprite->width(), sprite->height());
+      gfx::Size size = sample.trimmedBounds().getSize();
 
       if (oldSprite) {
-          // If the user didn't specified a width for the texture, we put
-          // each sprite/layer in a different row.
-          if (width == 0) {
-              // New sprite or layer, go to next row.
-              if (oldSprite != sprite || oldLayer != layer) {
-                  framePt.x = 0;
-                  framePt.y += oldSprite->height(); // We're skipping the previous sprite height
-              }
-          }
-          // When a texture width is specified, we can put different
-          // sprites/layers in each row until we reach the texture
-          // right-border.
-          else if (framePt.x+size.w > width) {
-              framePt.x = 0;
-              framePt.y += oldSprite->height();
-              // TODO framePt.y+size.h > height ?
+        // If the user didn't specify a width for the texture, we put
+        // each sprite/layer in a different row.
+        if (width == 0) {
+          // New sprite or layer, go to next row.
+          if (oldSprite != sprite || oldLayer != layer) {
+            framePt.x = 0;
+            framePt.y += rowSize.h;
+            rowSize = size;
           }
+        }
+        // When a texture width is specified, we can put different
+        // sprites/layers in each row until we reach the texture
+        // right-border.
+        else if (framePt.x+size.w > width) {
+          framePt.x = 0;
+          framePt.y += rowSize.h;
+          rowSize = size;
+        }
       }
 
-      sample.setOriginalSize(size);
-      sample.setTrimmedBounds(gfx::Rect(gfx::Point(0, 0), size));
       sample.setInTextureBounds(gfx::Rect(framePt, size));
 
       // Next frame position.
       framePt.x += size.w;
+      rowSize = rowSize.createUnion(size);
 
       oldSprite = sprite;
       oldLayer = layer;
@@ -172,15 +177,8 @@ public:
   void layoutSamples(Samples& samples, int& width, int& height) override {
     gfx::PackingRects pr;
 
-    for (auto& sample : samples) {
-      const Sprite* sprite = sample.sprite();
-      gfx::Size size(sprite->width(), sprite->height());
-
-      sample.setOriginalSize(size);
-      sample.setTrimmedBounds(gfx::Rect(gfx::Point(0, 0), size));
-
-      pr.add(size);
-    }
+    for (auto& sample : samples)
+      pr.add(sample.trimmedBounds().getSize());
 
     if (width == 0 || height == 0) {
       gfx::Size sz = pr.bestFit();
@@ -208,6 +206,7 @@ DocumentExporter::DocumentExporter()
  , m_scale(1.0)
  , m_scaleMode(DefaultScaleMode)
  , m_ignoreEmptyCels(false)
+ , m_trimCels(false)
 {
 }
 
@@ -267,7 +266,6 @@ void DocumentExporter::exportSheet()
 
 void DocumentExporter::captureSamples(Samples& samples)
 {
-  ImageBufferPtr checkEmptyImageBuf;
   std::vector<char> buf(32);
 
   for (auto& item : m_documents) {
@@ -299,30 +297,39 @@ void DocumentExporter::captureSamples(Samples& samples)
 
       Sample sample(doc, sprite, layer, frame, filename);
 
-      if (m_ignoreEmptyCels) {
+      if (m_ignoreEmptyCels || m_trimCels) {
         if (layer && layer->isImage() &&
             !static_cast<LayerImage*>(layer)->getCel(frame)) {
           // Empty cel this sample completely
           continue;
         }
 
-        base::UniquePtr<Image> checkEmptyImage(
+        base::UniquePtr<Image> sampleRender(
           Image::create(sprite->pixelFormat(),
             sprite->width(),
             sprite->height(),
-            checkEmptyImageBuf));
+            m_sampleRenderBuf));
 
-        checkEmptyImage->setMaskColor(sprite->transparentColor());
-        clear_image(checkEmptyImage, sprite->transparentColor());
-        renderSample(sample, checkEmptyImage, 0, 0);
+        sampleRender->setMaskColor(sprite->transparentColor());
+        clear_image(sampleRender, sprite->transparentColor());
+        renderSample(sample, sampleRender);
 
         gfx::Rect frameBounds;
-        if (!algorithm::shrink_bounds(checkEmptyImage, frameBounds,
-            sprite->transparentColor())) {
+        raster::color_t refColor;
+
+        if (m_trimCels)
+          refColor = get_pixel(sampleRender, 0, 0);
+        else if (m_ignoreEmptyCels)
+          refColor = sprite->transparentColor();
+
+        if (!algorithm::shrink_bounds(sampleRender, frameBounds, refColor)) {
           // If shrink_bounds returns false, it's because the whole
           // image is transparent (equal to the mask color).
           continue;
         }
+
+        if (m_trimCels)
+          sample.setTrimmedBounds(frameBounds);
       }
 
       samples.addSample(sample);
@@ -388,10 +395,7 @@ void DocumentExporter::renderTexture(const Samples& samples, Image* textureImage
         DITHERING_NONE);
     }
 
-    int x = sample.inTextureBounds().x - sample.trimmedBounds().x;
-    int y = sample.inTextureBounds().y - sample.trimmedBounds().y;
-
-    renderSample(sample, textureImage, x, y);
+    renderSample(sample, textureImage);
   }
 }
 
@@ -446,14 +450,24 @@ void DocumentExporter::createDataFile(const Samples& samples, std::ostream& os,
      << "}\n";
 }
 
-void DocumentExporter::renderSample(const Sample& sample, raster::Image* dst, int x, int y)
+void DocumentExporter::renderSample(const Sample& sample, raster::Image* dst)
 {
+  gfx::Rect trimmed = sample.trimmedBounds();
+  base::UniquePtr<Image> tmp(
+    Image::create(sample.sprite()->pixelFormat(),
+      trimmed.w, trimmed.h,
+      m_sampleRenderBuf));
+
   if (sample.layer()) {
-    layer_render(sample.layer(), dst, x, y, sample.frame());
+    layer_render(sample.layer(), tmp, -trimmed.x, -trimmed.y, sample.frame());
   }
   else {
-    sample.sprite()->render(dst, x, y, sample.frame());
+    sample.sprite()->render(tmp, -trimmed.x, -trimmed.y, sample.frame());
   }
+
+  copy_image(dst, tmp,
+    sample.inTextureBounds().x,
+    sample.inTextureBounds().y);
 }
 
 } // namespace app
diff --git a/src/app/document_exporter.h b/src/app/document_exporter.h
index 7fce95a..007a36a 100644
--- a/src/app/document_exporter.h
+++ b/src/app/document_exporter.h
@@ -1,5 +1,5 @@
 /* Aseprite
- * Copyright (C) 2001-2014  David Capello
+ * Copyright (C) 2001-2015  David Capello
  *
  * 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
@@ -22,10 +22,11 @@
 
 #include "base/disable_copying.h"
 #include "gfx/fwd.h"
+#include "raster/image_buffer.h"
 
 #include <iosfwd>
-#include <vector>
 #include <string>
+#include <vector>
 
 namespace raster {
   class Image;
@@ -93,6 +94,10 @@ namespace app {
       m_ignoreEmptyCels = ignore;
     }
 
+    void setTrimCels(bool trim) {
+      m_trimCels = trim;
+    }
+
     void setFilenameFormat(const std::string& format) {
       m_filenameFormat = format;
     }
@@ -114,7 +119,7 @@ namespace app {
     Document* createEmptyTexture(const Samples& samples);
     void renderTexture(const Samples& samples, raster::Image* textureImage);
     void createDataFile(const Samples& samples, std::ostream& os, raster::Image* textureImage);
-    void renderSample(const Sample& sample, raster::Image* dst, int x, int y);
+    void renderSample(const Sample& sample, raster::Image* dst);
 
     class Item {
     public:
@@ -136,8 +141,10 @@ namespace app {
     double m_scale;
     ScaleMode m_scaleMode;
     bool m_ignoreEmptyCels;
+    bool m_trimCels;
     Items m_documents;
     std::string m_filenameFormat;
+    raster::ImageBufferPtr m_sampleRenderBuf;
 
     DISABLE_COPYING(DocumentExporter);
   };
diff --git a/src/app/settings/ui_settings_impl.cpp b/src/app/settings/ui_settings_impl.cpp
index 066298b..ea28029 100644
--- a/src/app/settings/ui_settings_impl.cpp
+++ b/src/app/settings/ui_settings_impl.cpp
@@ -382,12 +382,14 @@ bool UISettingsImpl::getAutoSelectLayer()
 
 app::Color UISettingsImpl::getFgColor()
 {
-  return ColorBar::instance()->getFgColor();
+  ColorBar* colorbar = ColorBar::instance();
+  return colorbar ? colorbar->getFgColor(): app::Color::fromMask();
 }
 
 app::Color UISettingsImpl::getBgColor()
 {
-  return ColorBar::instance()->getBgColor();
+  ColorBar* colorbar = ColorBar::instance();
+  return colorbar ? colorbar->getBgColor(): app::Color::fromMask();
 }
 
 tools::Tool* UISettingsImpl::getCurrentTool()

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/aseprite.git



More information about the Pkg-games-commits mailing list