Add --sheet-pack command line option to improve packing images

This commit is contained in:
David Capello 2014-11-07 10:39:05 -03:00
parent c0d35b16e0
commit c9c8c6308f
5 changed files with 64 additions and 9 deletions

View File

@ -241,6 +241,11 @@ void App::initialize(int argc, const char* argv[])
if (m_exporter)
m_exporter->setTextureHeight(strtol(value.value().c_str(), NULL, 0));
}
// --sheet-pack
else if (opt == &options.sheetPack()) {
if (m_exporter)
m_exporter->setTexturePack(true);
}
// --split-layers
else if (opt == &options.splitLayers()) {
splitLayers = true;

View File

@ -39,15 +39,16 @@ AppOptions::AppOptions(int argc, const char* argv[])
, m_palette(m_po.add("palette").requiresValue("<filename>").description("Use a specific palette by default"))
, m_shell(m_po.add("shell").description("Start an interactive console to execute scripts"))
, m_batch(m_po.add("batch").description("Do not start the UI"))
, m_saveAs(m_po.add("save-as").requiresValue("<filename>").description("Save the last give document with other name/format"))
, m_scale(m_po.add("scale").requiresValue("<factor>").description("Scale all opened documents at the moment"))
, m_saveAs(m_po.add("save-as").requiresValue("<filename>").description("Save the last given document with other format"))
, m_scale(m_po.add("scale").requiresValue("<factor>").description("Resize all previous opened documents"))
, m_data(m_po.add("data").requiresValue("<filename.json>").description("File to store the sprite sheet metadata"))
, m_sheet(m_po.add("sheet").requiresValue("<filename.png>").description("Image file to save the texture"))
, m_sheetWidth(m_po.add("sheet-width").requiresValue("<pixels>").description("Sprite sheet width"))
, m_sheetHeight(m_po.add("sheet-height").requiresValue("<pixels>").description("Sprite sheet height"))
, m_splitLayers(m_po.add("split-layers").description("Import each layer of the next given sprite as\n a separated image in the sheet"))
, m_sheetPack(m_po.add("sheet-pack").description("Use a packing algorithm to avoid waste of space\nin the texture"))
, 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_verbose(m_po.add("verbose").description("Explain what is being done (in stderr or log file)"))
, 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"))
, m_version(m_po.add("version").description("Output version information and exit"))
{

View File

@ -53,6 +53,7 @@ public:
const Option& sheet() const { return m_sheet; }
const Option& sheetWidth() const { return m_sheetWidth; }
const Option& sheetHeight() const { return m_sheetHeight; }
const Option& sheetPack() const { return m_sheetPack; }
const Option& splitLayers() const { return m_splitLayers; }
const Option& importLayer() const { return m_importLayer; }
@ -78,6 +79,7 @@ private:
Option& m_sheet;
Option& m_sheetWidth;
Option& m_sheetHeight;
Option& m_sheetPack;
Option& m_splitLayers;
Option& m_importLayer;

View File

@ -29,6 +29,7 @@
#include "app/ui_context.h"
#include "base/path.h"
#include "base/unique_ptr.h"
#include "gfx/packing_rects.h"
#include "gfx/size.h"
#include "raster/cel.h"
#include "raster/dithering_method.h"
@ -113,13 +114,13 @@ private:
class DocumentExporter::LayoutSamples {
public:
virtual ~LayoutSamples() { }
virtual void layoutSamples(Samples& samples, int width, int height) = 0;
virtual void layoutSamples(Samples& samples, int& width, int& height) = 0;
};
class DocumentExporter::SimpleLayoutSamples :
public DocumentExporter::LayoutSamples {
public:
void layoutSamples(Samples& samples, int width, int height) override {
void layoutSamples(Samples& samples, int& width, int& height) override {
const Sprite* oldSprite = NULL;
const Layer* oldLayer = NULL;
@ -162,11 +163,45 @@ public:
}
};
class DocumentExporter::BestFitLayoutSamples :
public DocumentExporter::LayoutSamples {
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);
}
if (width == 0 || height == 0) {
gfx::Size sz = pr.bestFit();
width = sz.w;
height = sz.h;
}
else
pr.pack(gfx::Size(width, height));
auto it = samples.begin();
for (auto& rc : pr) {
ASSERT(it != samples.end());
it->setInTextureBounds(rc);
++it;
}
}
};
DocumentExporter::DocumentExporter()
: m_dataFormat(DefaultDataFormat)
, m_textureFormat(DefaultTextureFormat)
, m_textureWidth(0)
, m_textureHeight(0)
, m_texturePack(false)
, m_scaleMode(DefaultScaleMode)
, m_scale(1.0)
{
@ -196,8 +231,14 @@ void DocumentExporter::exportSheet()
}
// 2) Layout those samples in a texture field.
SimpleLayoutSamples layout;
layout.layoutSamples(samples, m_textureWidth, m_textureHeight);
if (m_texturePack) {
BestFitLayoutSamples layout;
layout.layoutSamples(samples, m_textureWidth, m_textureHeight);
}
else {
SimpleLayoutSamples layout;
layout.layoutSamples(samples, m_textureWidth, m_textureHeight);
}
// 3) Create and render the texture.
base::UniquePtr<Document> textureDocument(

View File

@ -1,5 +1,5 @@
/* Aseprite
* Copyright (C) 2001-2013 David Capello
* Copyright (C) 2001-2014 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
@ -77,6 +77,10 @@ namespace app {
m_textureHeight = height;
}
void setTexturePack(bool state) {
m_texturePack = state;
}
void setScale(double scale) {
m_scale = scale;
}
@ -96,6 +100,7 @@ namespace app {
class Samples;
class LayoutSamples;
class SimpleLayoutSamples;
class BestFitLayoutSamples;
void captureSamples(Samples& samples);
Document* createEmptyTexture(const Samples& samples);
@ -118,6 +123,7 @@ namespace app {
std::string m_textureFilename;
int m_textureWidth;
int m_textureHeight;
bool m_texturePack;
double m_scale;
ScaleMode m_scaleMode;
Items m_documents;