mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 13:06:59 -04:00
add bleed edge option, get_card_export_settings function
This commit is contained in:
@@ -151,7 +151,7 @@ CardsOnClipboard::CardsOnClipboard(const SetP& set, const String id, const vecto
|
||||
img = export_image(set, cards[0]);
|
||||
}
|
||||
else {
|
||||
img = export_image(set, cards, true, 0, 1.0, 0.0);
|
||||
img = export_image(set, cards);
|
||||
}
|
||||
String temp_path = wxFileName::CreateTempFileName(_("mse")) + _(".png");
|
||||
img.SaveFile(temp_path, wxBITMAP_TYPE_PNG);
|
||||
|
||||
@@ -88,15 +88,11 @@ FileFormatP mtg_editor_file_format();
|
||||
|
||||
// ----------------------------------------------------------------------------- : Other ways to export
|
||||
|
||||
/// Generate a wxBitmap of one or more cards
|
||||
Bitmap export_bitmap(const SetP& set, const CardP& card, const double zoom = 1.0, const Radians angle_radians = 0.0);
|
||||
Bitmap export_bitmap(const SetP& set, const vector<CardP>& cards, bool scale_to_lowest_dpi, int padding, const double zoom, const Radians angle_radians, vector<double>& scales_out, vector<int>& offsets_out);
|
||||
|
||||
/// Generate a wxImage of one or more cards
|
||||
Image export_image(const SetP& set, const CardP& card, const double zoom = 1.0, const Radians angle_radians = 0.0);
|
||||
Image export_image(const SetP& set, const vector<CardP>& cards, bool scale_to_lowest_dpi = false, int padding = 0, const double zoom = 1.0, const Radians angle_radians = 0.0);
|
||||
Image export_image(const SetP& set, const CardP& card, const bool write_metadata = true, const double zoom = 1.0, const Radians angle_radians = 0.0, const double bleed_pixels = 0.0);
|
||||
Image export_image(const SetP& set, const vector<CardP>& cards, const int padding = 2, const double global_zoom = 1.0, const bool use_zoom_setting = true, const bool use_rotation_setting = true, const bool use_bleed_setting = false);
|
||||
|
||||
/// Export the image of one or more cards to a given filename, using the app's zoom and rotation settings
|
||||
/// Export the image of one or more cards to a given filename, using the app's zoom, rotation and bleed settings, and including metadata
|
||||
void export_image(const SetP& set, const CardP& card, const String& filename);
|
||||
void export_image(const SetP& set, const vector<CardP>& cards, const String& path, const String& filename_template, FilenameConflicts conflicts);
|
||||
|
||||
|
||||
+238
-150
@@ -20,157 +20,160 @@
|
||||
#include <render/card/viewer.hpp>
|
||||
#include <wx/filename.h>
|
||||
|
||||
// ----------------------------------------------------------------------------- : Card export
|
||||
|
||||
class UnzoomedDataViewer : public DataViewer {
|
||||
class ZoomedUnrotatedDataViewer : public DataViewer {
|
||||
public:
|
||||
UnzoomedDataViewer();
|
||||
UnzoomedDataViewer(double zoom, Radians angle);
|
||||
virtual ~UnzoomedDataViewer() {};
|
||||
Rotation getRotation() const override;
|
||||
private:
|
||||
ZoomedUnrotatedDataViewer(double zoom) : zoom(zoom) {};
|
||||
virtual ~ZoomedUnrotatedDataViewer() {};
|
||||
Rotation getRotation() const override;
|
||||
private:
|
||||
double zoom;
|
||||
double angle;
|
||||
bool declared_values;
|
||||
};
|
||||
|
||||
UnzoomedDataViewer::UnzoomedDataViewer()
|
||||
: zoom(1.0)
|
||||
, angle(0.0)
|
||||
, declared_values(false)
|
||||
{}
|
||||
|
||||
UnzoomedDataViewer::UnzoomedDataViewer(const double zoom, const Radians angle = 0.0)
|
||||
: zoom(zoom)
|
||||
, angle(angle)
|
||||
, declared_values(true)
|
||||
{}
|
||||
|
||||
Rotation UnzoomedDataViewer::getRotation() const {
|
||||
if (!stylesheet) stylesheet = set->stylesheet;
|
||||
if (declared_values) {
|
||||
return Rotation(angle, stylesheet->getCardRect(), zoom, 1.0, ROTATION_ATTACH_TOP_LEFT);
|
||||
}
|
||||
|
||||
double export_zoom = settings.exportZoomSettingsFor(set->stylesheetFor(card));
|
||||
bool use_viewer_rotation = !settings.stylesheetSettingsFor(set->stylesheetFor(card)).card_normal_export();
|
||||
|
||||
if (use_viewer_rotation) {
|
||||
return Rotation(DataViewer::getRotation().getAngle(), stylesheet->getCardRect(), export_zoom, 1.0, ROTATION_ATTACH_TOP_LEFT);
|
||||
} else {
|
||||
return Rotation(angle, stylesheet->getCardRect(), export_zoom, 1.0, ROTATION_ATTACH_TOP_LEFT);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : wxBitmap export
|
||||
|
||||
Bitmap export_bitmap(const SetP& set, const CardP& card, const double zoom, const Radians angle_radians) {
|
||||
if (!set) throw Error(_("no set"));
|
||||
UnzoomedDataViewer viewer = UnzoomedDataViewer(zoom, angle_radians);
|
||||
viewer.setSet(set);
|
||||
viewer.setCard(card);
|
||||
// size of cards
|
||||
RealSize size = viewer.getRotation().getExternalSize();
|
||||
// create bitmap & dc
|
||||
Bitmap bitmap((int)size.width, (int)size.height);
|
||||
if (!bitmap.Ok()) throw InternalError(_("Unable to create bitmap"));
|
||||
wxMemoryDC dc;
|
||||
dc.SelectObject(bitmap);
|
||||
// draw
|
||||
viewer.draw(dc);
|
||||
dc.SelectObject(wxNullBitmap);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
Bitmap export_bitmap(const SetP& set, const vector<CardP>& cards, bool scale_to_lowest_dpi, int padding, const double zoom, const Radians angle_radians, vector<double>& scales_out, vector<int>& offsets_out) {
|
||||
if (!set) throw Error(_("no set"));
|
||||
vector<Bitmap> bitmaps;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
double lowest_dpi = 1200.0;
|
||||
if (scale_to_lowest_dpi) {
|
||||
FOR_EACH(card, cards) {
|
||||
lowest_dpi = min(lowest_dpi, set->stylesheetFor(card).card_dpi);
|
||||
}
|
||||
lowest_dpi = max(lowest_dpi, 150.0);
|
||||
}
|
||||
// Draw card bitmaps
|
||||
FOR_EACH(card, cards) {
|
||||
double scale = zoom;
|
||||
if (scale_to_lowest_dpi) {
|
||||
double dpi = max(set->stylesheetFor(card).card_dpi, 150.0);
|
||||
scale *= lowest_dpi / dpi;
|
||||
}
|
||||
scales_out.push_back(scale);
|
||||
UnzoomedDataViewer viewer = UnzoomedDataViewer(scale, angle_radians);
|
||||
viewer.setSet(set);
|
||||
viewer.setCard(card);
|
||||
RealSize size = viewer.getRotation().getExternalSize();
|
||||
Bitmap bitmap((int)size.width, (int)size.height);
|
||||
if (!bitmap.Ok()) throw InternalError(_("Unable to create bitmap"));
|
||||
wxMemoryDC bufferDC;
|
||||
bufferDC.SelectObject(bitmap);
|
||||
clearDC(bufferDC, *wxWHITE_BRUSH);
|
||||
viewer.draw(bufferDC);
|
||||
bufferDC.SelectObject(wxNullBitmap);
|
||||
width += (int)size.width;
|
||||
height = max(height, (int)size.height);
|
||||
bitmaps.push_back(bitmap);
|
||||
}
|
||||
// Draw global bitmap
|
||||
Bitmap global_bitmap(width + (bitmaps.size()-1) * padding, height);
|
||||
if (!global_bitmap.Ok()) throw InternalError(_("Unable to create bitmap"));
|
||||
wxMemoryDC globalDC;
|
||||
globalDC.SelectObject(global_bitmap);
|
||||
clearDC(globalDC, *wxWHITE_BRUSH);
|
||||
int offset = 0;
|
||||
FOR_EACH(bitmap, bitmaps) {
|
||||
offsets_out.push_back(offset);
|
||||
globalDC.SetDeviceOrigin(offset, 0);
|
||||
globalDC.DrawBitmap(bitmap, 0, 0);
|
||||
offset += bitmap.GetWidth() + padding;
|
||||
}
|
||||
globalDC.SelectObject(wxNullBitmap);
|
||||
return global_bitmap;
|
||||
Rotation ZoomedUnrotatedDataViewer::getRotation() const {
|
||||
return Rotation(0.0, stylesheet->getCardRect(), zoom);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : wxImage export
|
||||
|
||||
Image export_image(const SetP& set, const CardP& card, const double zoom, const Radians angle_radians) {
|
||||
Bitmap bitmap = export_bitmap(set, card, zoom, angle_radians);
|
||||
Image img = bitmap.ConvertToImage();
|
||||
String data = _("<mse-data-start>[");
|
||||
IndexMap<FieldP, ValueP>& card_data = card->data;
|
||||
boost::json::object& cardv = mse_to_json(card, set.get());
|
||||
boost::json::object& cardv_data = cardv["data"].as_object();
|
||||
StyleSheetP stylesheet = set->stylesheetForP(card);
|
||||
if (!settings.stylesheetSettingsFor(*stylesheet).card_notes_export()) cardv["notes"] = "";
|
||||
for(IndexMap<FieldP, ValueP>::iterator it = card_data.begin() ; it != card_data.end() ; ++it) {
|
||||
ImageValue* value = dynamic_cast<ImageValue*>(it->get());
|
||||
if (value && !value->filename.empty()) {
|
||||
FieldP field = (*it)->fieldP;
|
||||
StyleP style = stylesheet->card_style.at(field->index);
|
||||
if (style) {
|
||||
style->update(set->getContext(card));
|
||||
std::string rect = style->getExternalRectString(zoom, 0).ToStdString();
|
||||
cardv_data[field->name.ToStdString()] = rect;
|
||||
Image export_image(const SetP& set, const CardP& card, const bool write_metadata, const double zoom, const Radians angle_radians, const double bleed_pixels) {
|
||||
if (!set) throw Error(_("no set"));
|
||||
/// create and zoom
|
||||
ZoomedUnrotatedDataViewer viewer = ZoomedUnrotatedDataViewer(zoom);
|
||||
viewer.setSet(set);
|
||||
viewer.setCard(card);
|
||||
RealSize size = viewer.getRotation().getExternalSize();
|
||||
int bleed = lround(bleed_pixels);
|
||||
Bitmap bitmap((int)size.width + 2 * bleed, (int)size.height + 2 * bleed);
|
||||
if (!bitmap.Ok()) throw InternalError(_("Unable to create bitmap"));
|
||||
wxMemoryDC dc;
|
||||
dc.SelectObject(bitmap);
|
||||
dc.SetDeviceOrigin(bleed, bleed);
|
||||
viewer.draw(dc);
|
||||
dc.SelectObject(wxNullBitmap);
|
||||
Image img = bitmap.ConvertToImage();
|
||||
|
||||
/// rotate
|
||||
img = rotate_image(img, angle_radians);
|
||||
int width = img.GetWidth(), height = img.GetHeight();
|
||||
|
||||
/// add print bleed edge
|
||||
if (size.width < 1.0 || size.height < 1.0) {
|
||||
queue_message(MESSAGE_ERROR, _("Cannot add bleed edge to empty image"));
|
||||
}
|
||||
else {
|
||||
if (!img.HasAlpha()) img.InitAlpha();
|
||||
Byte* pixels = img.GetData();
|
||||
Byte* alpha = img.GetAlpha();
|
||||
// fill top left corner
|
||||
int pixel;
|
||||
int x_start = 0;
|
||||
int y_start = 0;
|
||||
int ref = bleed + bleed * width;
|
||||
for (int y = 0; y < bleed; ++y) {
|
||||
for (int x = 0; x < bleed; ++x) {
|
||||
pixel = x_start + x + (y_start + y) * width;
|
||||
pixels[3 * pixel + 0] = pixels[3 * ref + 0];
|
||||
pixels[3 * pixel + 1] = pixels[3 * ref + 1];
|
||||
pixels[3 * pixel + 2] = pixels[3 * ref + 2];
|
||||
alpha[pixel] = alpha[ref];
|
||||
}
|
||||
}
|
||||
}
|
||||
data += json_ugly_print(cardv) + _("]<mse-data-end>");
|
||||
img.SetOption(wxIMAGE_OPTION_PNG_DESCRIPTION, data);
|
||||
return img;
|
||||
}
|
||||
|
||||
Image export_image(const SetP& set, const vector<CardP>& cards, bool scale_to_lowest_dpi, int padding, const double zoom, const Radians angle_radians) {
|
||||
vector<double> scales;
|
||||
vector<int> offsets;
|
||||
Bitmap bitmap = export_bitmap(set, cards, scale_to_lowest_dpi, padding, zoom, angle_radians, scales, offsets);
|
||||
Image img = bitmap.ConvertToImage();
|
||||
String data = _("<mse-data-start>[");
|
||||
for (int i = 0; i < cards.size(); ++i) {
|
||||
if (i > 0) data += _(",");
|
||||
CardP card = cards[i];
|
||||
// fill top right corner
|
||||
x_start = width - bleed;
|
||||
y_start = 0;
|
||||
ref = x_start - 1 + bleed * width;
|
||||
for (int y = 0; y < bleed; ++y) {
|
||||
for (int x = 0; x < bleed; ++x) {
|
||||
pixel = x_start + x + (y_start + y) * width;
|
||||
pixels[3 * pixel + 0] = pixels[3 * ref + 0];
|
||||
pixels[3 * pixel + 1] = pixels[3 * ref + 1];
|
||||
pixels[3 * pixel + 2] = pixels[3 * ref + 2];
|
||||
alpha[pixel] = alpha[ref];
|
||||
}
|
||||
}
|
||||
// fill bottom left corner
|
||||
x_start = 0;
|
||||
y_start = height - bleed;
|
||||
ref = bleed + (y_start - 1) * width;
|
||||
for (int y = 0; y < bleed; ++y) {
|
||||
for (int x = 0; x < bleed; ++x) {
|
||||
pixel = x_start + x + (y_start + y) * width;
|
||||
pixels[3 * pixel + 0] = pixels[3 * ref + 0];
|
||||
pixels[3 * pixel + 1] = pixels[3 * ref + 1];
|
||||
pixels[3 * pixel + 2] = pixels[3 * ref + 2];
|
||||
alpha[pixel] = alpha[ref];
|
||||
}
|
||||
}
|
||||
// fill bottom right corner
|
||||
x_start = width - bleed;
|
||||
y_start = height - bleed;
|
||||
ref = (x_start - 1) + (y_start - 1) * width;
|
||||
for (int y = 0; y < bleed; ++y) {
|
||||
for (int x = 0; x < bleed; ++x) {
|
||||
pixel = x_start + x + (y_start + y) * width;
|
||||
pixels[3 * pixel + 0] = pixels[3 * ref + 0];
|
||||
pixels[3 * pixel + 1] = pixels[3 * ref + 1];
|
||||
pixels[3 * pixel + 2] = pixels[3 * ref + 2];
|
||||
alpha[pixel] = alpha[ref];
|
||||
}
|
||||
}
|
||||
// fill left border
|
||||
x_start = 0;
|
||||
y_start = bleed;
|
||||
for (int y = 0; y < height - bleed - bleed; ++y) {
|
||||
ref = bleed + (y_start + y) * width;
|
||||
for (int x = 0; x < bleed; ++x) {
|
||||
pixel = x_start + x + (y_start + y) * width;
|
||||
pixels[3 * pixel + 0] = pixels[3 * ref + 0];
|
||||
pixels[3 * pixel + 1] = pixels[3 * ref + 1];
|
||||
pixels[3 * pixel + 2] = pixels[3 * ref + 2];
|
||||
alpha[pixel] = alpha[ref];
|
||||
}
|
||||
}
|
||||
// fill top border
|
||||
x_start = bleed;
|
||||
y_start = 0;
|
||||
for (int y = 0; y < bleed; ++y) {
|
||||
for (int x = 0; x < width - bleed - bleed; ++x) {
|
||||
pixel = x_start + x + (y_start + y) * width;
|
||||
ref = x_start + x + bleed * width;
|
||||
pixels[3 * pixel + 0] = pixels[3 * ref + 0];
|
||||
pixels[3 * pixel + 1] = pixels[3 * ref + 1];
|
||||
pixels[3 * pixel + 2] = pixels[3 * ref + 2];
|
||||
alpha[pixel] = alpha[ref];
|
||||
}
|
||||
}
|
||||
// fill right border
|
||||
x_start = width - bleed;
|
||||
y_start = bleed;
|
||||
for (int y = 0; y < height - bleed - bleed; ++y) {
|
||||
ref = width - bleed - 1 + (y_start + y) * width;
|
||||
for (int x = 0; x < bleed; ++x) {
|
||||
pixel = x_start + x + (y_start + y) * width;
|
||||
pixels[3 * pixel + 0] = pixels[3 * ref + 0];
|
||||
pixels[3 * pixel + 1] = pixels[3 * ref + 1];
|
||||
pixels[3 * pixel + 2] = pixels[3 * ref + 2];
|
||||
alpha[pixel] = alpha[ref];
|
||||
}
|
||||
}
|
||||
// fill bottom border
|
||||
x_start = bleed;
|
||||
y_start = height - bleed;
|
||||
for (int y = 0; y < bleed; ++y) {
|
||||
for (int x = 0; x < width - bleed - bleed; ++x) {
|
||||
pixel = x_start + x + (y_start + y) * width;
|
||||
ref = x_start + x + (height - bleed - 1) * width;
|
||||
pixels[3 * pixel + 0] = pixels[3 * ref + 0];
|
||||
pixels[3 * pixel + 1] = pixels[3 * ref + 1];
|
||||
pixels[3 * pixel + 2] = pixels[3 * ref + 2];
|
||||
alpha[pixel] = alpha[ref];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// add metadata
|
||||
if (write_metadata) {
|
||||
String metadata = _("<mse-card-data>[");
|
||||
IndexMap<FieldP, ValueP>& card_data = card->data;
|
||||
boost::json::object& cardv = mse_to_json(card, set.get());
|
||||
boost::json::object& cardv_data = cardv["data"].as_object();
|
||||
@@ -183,24 +186,109 @@ Image export_image(const SetP& set, const vector<CardP>& cards, bool scale_to_lo
|
||||
StyleP style = stylesheet->card_style.at(field->index);
|
||||
if (style) {
|
||||
style->update(set->getContext(card));
|
||||
std::string rect = style->getExternalRectString(scales[i], offsets[i]).ToStdString();
|
||||
std::string rect = style->getExternalRectString(zoom, angle_radians, bleed_pixels, width, height, 0).ToStdString();
|
||||
cardv_data[field->name.ToStdString()] = rect;
|
||||
}
|
||||
}
|
||||
}
|
||||
data += json_ugly_print(cardv);
|
||||
}
|
||||
data += _("]<mse-data-end>");
|
||||
img.SetOption(wxIMAGE_OPTION_PNG_DESCRIPTION, data);
|
||||
metadata += json_ugly_print(cardv) + _("]</mse-card-data>");
|
||||
img.SetOption(wxIMAGE_OPTION_PNG_DESCRIPTION, metadata);
|
||||
}
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
Image export_image( const SetP& set, const vector<CardP>& cards,
|
||||
const int padding,
|
||||
const double global_zoom,
|
||||
const bool use_zoom_setting,
|
||||
const bool use_rotation_setting,
|
||||
const bool use_bleed_setting) {
|
||||
if (!set) throw Error(_("no set"));
|
||||
if (cards.size() == 0) throw Error(_("no cards"));
|
||||
vector<Image> imgs;
|
||||
vector<int> offsets;
|
||||
vector<double> zooms;
|
||||
vector<double> angles;
|
||||
vector<double> bleeds;
|
||||
// Draw card images
|
||||
FOR_EACH(card, cards) {
|
||||
Settings::ExportSettings card_settings = settings.exportSettingsFor(set->stylesheetFor(card));
|
||||
double zoom = use_zoom_setting ? global_zoom * card_settings.zoom : global_zoom;
|
||||
double angle = use_rotation_setting ? card_settings.angle_radians : 0.0;
|
||||
double bleed = use_bleed_setting ? card_settings.bleed_pixels : 0.0;
|
||||
imgs.push_back(export_image(set, card, false, zoom, angle, bleed));
|
||||
zooms.push_back(zoom);
|
||||
angles.push_back(angle);
|
||||
bleeds.push_back(bleed);
|
||||
}
|
||||
int global_width = 0;
|
||||
int global_height = 0;
|
||||
vector<int> widths;
|
||||
vector<int> heights;
|
||||
FOR_EACH(img, imgs) {
|
||||
int width = img.GetWidth();
|
||||
int height = img.GetHeight();
|
||||
widths.push_back(width);
|
||||
heights.push_back(height);
|
||||
offsets.push_back(global_width);
|
||||
global_width += padding + width;
|
||||
global_height = max(global_height, height);
|
||||
}
|
||||
global_width -= padding;
|
||||
// Draw global image
|
||||
Image global_img = Image(global_width, global_height);
|
||||
if (!global_img.Ok()) throw InternalError(_("Unable to create image"));
|
||||
global_img.InitAlpha();
|
||||
Byte* pixels = global_img.GetData();
|
||||
Byte* alpha = global_img.GetAlpha();
|
||||
// fill with transparent
|
||||
for (UInt i = 0; i < global_width*global_height; ++i) {
|
||||
pixels[3 * i + 0] = 0;
|
||||
pixels[3 * i + 1] = 0;
|
||||
pixels[3 * i + 2] = 0;
|
||||
alpha[i] = 0;
|
||||
}
|
||||
// Paste card images
|
||||
FOR_EACH_2(img, imgs, offset, offsets) {
|
||||
global_img.Paste(img, offset, 0);
|
||||
}
|
||||
// Write metadata
|
||||
String metadata = _("<mse-card-data>[");
|
||||
for (int i = 0; i < cards.size(); ++i) {
|
||||
if (i > 0) metadata += _(",");
|
||||
CardP card = cards[i];
|
||||
IndexMap<FieldP, ValueP>& card_data = card->data;
|
||||
boost::json::object& cardv = mse_to_json(card, set.get());
|
||||
boost::json::object& cardv_data = cardv["data"].as_object();
|
||||
StyleSheetP stylesheet = set->stylesheetForP(card);
|
||||
if (!settings.stylesheetSettingsFor(*stylesheet).card_notes_export()) cardv["notes"] = "";
|
||||
for(IndexMap<FieldP, ValueP>::iterator it = card_data.begin() ; it != card_data.end() ; ++it) {
|
||||
ImageValue* value = dynamic_cast<ImageValue*>(it->get());
|
||||
if (value && !value->filename.empty()) {
|
||||
FieldP field = (*it)->fieldP;
|
||||
StyleP style = stylesheet->card_style.at(field->index);
|
||||
if (style) {
|
||||
style->update(set->getContext(card));
|
||||
Rotation rotation();
|
||||
std::string rect = style->getExternalRectString(zooms[i], angles[i], bleeds[i], widths[i], heights[i], offsets[i]).ToStdString();
|
||||
cardv_data[field->name.ToStdString()] = rect;
|
||||
}
|
||||
}
|
||||
}
|
||||
metadata += json_ugly_print(cardv);
|
||||
}
|
||||
metadata += _("]</mse-card-data>");
|
||||
global_img.SetOption(wxIMAGE_OPTION_PNG_DESCRIPTION, metadata);
|
||||
|
||||
return global_img;
|
||||
}
|
||||
|
||||
void export_image(const SetP& set, const CardP& card, const String& filename) {
|
||||
const StyleSheet& stylesheet = set->stylesheetFor(card);
|
||||
StyleSheetSettings& stylesheet_settings = settings.stylesheetSettingsFor(stylesheet);
|
||||
double zoom = settings.exportZoomSettingsFor(stylesheet);
|
||||
Radians angle = stylesheet_settings.card_normal_export() ? 0.0 : deg_to_rad(stylesheet_settings.card_angle());
|
||||
Image img = export_image(set, card, zoom, angle);
|
||||
StyleSheetSettings& stylesheet_settings = settings.stylesheetSettingsFor(stylesheet);
|
||||
Settings::ExportSettings export_settings = settings.exportSettingsFor(stylesheet);
|
||||
Image img = export_image(set, card, true, export_settings.zoom, export_settings.angle_radians, export_settings.bleed_pixels);
|
||||
img.SaveFile(filename);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user