Fix bug saving tags in file sequences using -save-as "{tag}_1.png"

Now the equivalent was "{tag}_{frame1}.png", but it looks like a
regression reported here https://community.aseprite.org/t/17253 were
it was possible to just specify the frame number as in "{tag}_1.png"
This commit is contained in:
David Capello 2023-03-22 14:35:52 -03:00
parent 30a88c8e3d
commit e865374805
5 changed files with 109 additions and 10 deletions

View File

@ -682,6 +682,12 @@ FileOp* FileOp::createSaveDocumentOperation(const Context* context,
false, // Doesn't have layers false, // Doesn't have layers
false); // Doesn't have tags false); // Doesn't have tags
} }
// If the filename format is given, we have to check if the
// {frame} is specified, or in other case, if it's something like
// "..._1.png", replace the it with "..._{frame1}.png"
else if (fop->m_roi.selectedFrames().size() > 1) {
fn_format = replace_frame_number_with_frame_format(fn_format);
}
frame_t outputFrame = 0; frame_t outputFrame = 0;

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2022 Igara Studio S.A. // Copyright (C) 2022-2023 Igara Studio S.A.
// Copyright (C) 2001-2017 David Capello // Copyright (C) 2001-2017 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -50,6 +50,24 @@ static bool replace_frame(const char* frameKey, // E.g. = "{frame"
return false; return false;
} }
static bool autodetect_frame_format(const std::string& filename,
std::string& left,
std::string& frameFormat,
std::string& right,
int& frameBase)
{
int frameWidth = 0;
frameBase = split_filename(filename, left, right, frameWidth);
if (frameBase >= 0) {
std::vector<char> buf(32);
std::sprintf(&buf[0], "{frame%0*d}", frameWidth, frameBase);
frameFormat = std::string(&buf[0]);
return true;
}
else
return false;
}
bool get_frame_info_from_filename_format( bool get_frame_info_from_filename_format(
const std::string& format, int* frameBase, int* width) const std::string& format, int* frameBase, int* width)
{ {
@ -179,16 +197,14 @@ std::string get_default_filename_format(
// Check if we already have a frame number at the end of the // Check if we already have a frame number at the end of the
// filename (e.g. output01.png) // filename (e.g. output01.png)
int frameBase = -1, frameWidth = 0; int frameBase = -1, frameWidth = 0;
std::string left, right; std::string left, frameFormat, right;
if (autoFrameFromLastDigit)
frameBase = split_filename(filename, left, right, frameWidth);
if (frameBase >= 0) {
std::vector<char> buf(32);
std::sprintf(&buf[0], "{frame%0*d}", frameWidth, frameBase);
if (autoFrameFromLastDigit &&
autodetect_frame_format(
filename, left, frameFormat, right, frameBase)) {
if (hasLayer || hasTag) if (hasLayer || hasTag)
format += " "; format += " ";
format += &buf[0]; format += frameFormat;
// Remove the frame number from the filename part. // Remove the frame number from the filename part.
filename = left; filename = left;
@ -245,4 +261,26 @@ std::string get_default_tagname_format_for_sheet()
return "{tag}"; return "{tag}";
} }
std::string replace_frame_number_with_frame_format(const std::string& filename)
{
std::string result = filename;
if (is_static_image_format(filename) &&
filename.find("{frame") == std::string::npos &&
filename.find("{tagframe") == std::string::npos) {
std::string left, frameFormat, right;
int frameBase = -1;
if (!autodetect_frame_format(
filename, left, frameFormat, right, frameBase)) {
frameFormat = "{frame1}";
}
result = left;
result += frameFormat;
result += right;
}
return result;
}
} // namespace app } // namespace app

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2022 Igara Studio S.A. // Copyright (C) 2022-2023 Igara Studio S.A.
// Copyright (C) 2001-2017 David Capello // Copyright (C) 2001-2017 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -119,6 +119,17 @@ namespace app {
std::string get_default_tagname_format_for_sheet(); std::string get_default_tagname_format_for_sheet();
// Replaces "sprite1.png" with "sprite{frame1}.png". It's used to
// enable saving a sequence of images when the filename format
// doesn't specify {frame} but has some other formatting.
// E.g. -save-as "{tag}-1.png" will not use the default filename
// format (because the format is already specified in the filename,
// at least partially) but it still requires the {frame} format to
// avoid saving all frames into "...-1.png", so the result in this
// case must be: "{tag}-{frame1}.png".
std::string replace_frame_number_with_frame_format(
const std::string& filename);
} // namespace app } // namespace app
#endif #endif

View File

@ -1,4 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2023 Igara Studio S.A.
// Copyright (C) 2001-2016 David Capello // Copyright (C) 2001-2016 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -233,3 +234,20 @@ TEST(FilenameFormatter, DefaultFormat)
EXPECT_EQ("{path}/{title} #{tag} {frame}.{extension}", get_default_filename_format(fn, true, true, false, true)); EXPECT_EQ("{path}/{title} #{tag} {frame}.{extension}", get_default_filename_format(fn, true, true, false, true));
EXPECT_EQ("/path/hello1.png", fn); EXPECT_EQ("/path/hello1.png", fn);
} }
TEST(FilenameFormatter, DetectFrame)
{
std::string fn;
fn = "/path/hello.png";
EXPECT_EQ("/path/hello{frame1}.png", replace_frame_number_with_frame_format(fn));
fn = "/path/hello0.png";
EXPECT_EQ("/path/hello{frame0}.png", replace_frame_number_with_frame_format(fn));
fn = "/path/hello1.png";
EXPECT_EQ("/path/hello{frame1}.png", replace_frame_number_with_frame_format(fn));
fn = "/path/hello002.png";
EXPECT_EQ("/path/hello{frame002}.png", replace_frame_number_with_frame_format(fn));
}

View File

@ -1,5 +1,5 @@
#! /bin/bash #! /bin/bash
# Copyright (C) 2018-2021 Igara Studio S.A. # Copyright (C) 2018-2023 Igara Studio S.A.
function list_files() { function list_files() {
oldwd=$(pwd $PWDARG) oldwd=$(pwd $PWDARG)
@ -276,3 +276,29 @@ expect "groups2-1.png
groups3abc-1.png groups3abc-1.png
link-1.png link-1.png
link-2.png" "list_files $d" link-2.png" "list_files $d"
# Test regression with --save-as {tag}_1.png to interpret 1 as {frame1}
# https://community.aseprite.org/t/17253
d=$t/save-as-1-as-frame1-ok
$ASEPRITE -b sprites/1empty3.aseprite \
-save-as "$d/{tag}-{frame1}.png" || exit 1
expect "a-1.png
a-2.png
b-1.png" "list_files $d"
d=$t/save-as-1-as-frame1-regression
$ASEPRITE -b sprites/1empty3.aseprite \
-save-as "$d/{tag}-1.png" || exit 1
expect "a-1.png
a-2.png
b-1.png" "list_files $d"
# Test that -save-as {tag}.png will save with the frame number when needed
d=$t/save-as-with-format-but-without-frame
$ASEPRITE -b sprites/1empty3.aseprite \
-save-as "$d/{tag}.png" || exit 1
expect "a1.png
a2.png
b.png" "list_files $d"