mirror of
https://github.com/aseprite/aseprite.git
synced 2025-04-10 12:44:53 +00:00
Add --sheet-pack command line option to improve packing images
This commit is contained in:
parent
c0d35b16e0
commit
c9c8c6308f
@ -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;
|
||||
|
@ -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"))
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user