123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664 |
- /*
- Copyright (C) 2010-2015 Matthias Kretz <kretz@kde.org>
- Permission to use, copy, modify, and distribute this software
- and its documentation for any purpose and without fee is hereby
- granted, provided that the above copyright notice appear in all
- copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
- */
- #include "main.h"
- #include "../tsc.h"
- #include <complex>
- #include <cmath>
- #include <QApplication>
- #include <QTextStream>
- #include <QTimer>
- #include <QtCore/QtDebug>
- #include <QPainter>
- #include <QProgressBar>
- #ifdef Scalar
- typedef float float_v;
- typedef int int_v;
- typedef bool int_m;
- #ifdef _MSC_VER
- #define Vc_CDECL __cdecl
- #else
- #define Vc_CDECL
- #endif
- #else
- #include <Vc/Vc>
- using Vc::float_v;
- using Vc::float_m;
- using int_v = Vc::SimdArray<int, float_v::size()>;
- using int_m = int_v::mask_type;
- #endif
- ProgressWriter::ProgressWriter()
- : m_out(stdout)
- {
- }
- void ProgressWriter::setValue(float vf)
- {
- static int lastPercent = -1;
- static int lastHash = 0;
- int p = static_cast<int>(vf + 0.5f);
- int h = static_cast<int>(vf * 0.78f + 0.5f);
- bool flush = false;
- if (p != lastPercent) {
- flush = true;
- if (lastPercent == -1) {
- m_out << "\033[80D\033[K"
- << "[ ";
- m_out.setFieldWidth(3);
- m_out << p;
- m_out.setFieldWidth(0);
- m_out << "% ]"
- << "\033[79D";
- } else {
- m_out << "\033[s\033[80D\033[37C";
- m_out.setFieldWidth(3);
- m_out << p;
- m_out.setFieldWidth(0);
- m_out << "\033[u";
- }
- lastPercent = p;
- }
- for (; lastHash < h; ++lastHash) {
- flush = true;
- if (lastHash < 36 || lastHash > 39) {
- m_out << '#';
- } else {
- m_out << "\033[1C";
- }
- }
- if (flush) {
- m_out.flush();
- }
- }
- void ProgressWriter::done()
- {
- setValue(100.f);
- m_out << "\033[2C";
- m_out.flush();
- }
- Baker::Baker()
- {
- }
- void Baker::setSize(int w, int h)
- {
- m_y = -1.f;
- m_height = 2.f;
- m_width = w * m_height / h;
- m_x = m_width * -0.667f;
- m_image = QImage(w, h, QImage::Format_RGB32);
- }
- void Baker::setFilename(const QString &filename)
- {
- m_filename = filename;
- }
- struct Z
- {
- using value_type = float_v;
- value_type real, imag;
- };
- inline Z operator*(Z a, Z b)
- {
- return {a.real * b.real - a.imag * b.imag, a.real * b.imag + a.imag * b.real};
- }
- inline Z operator+(Z a, Z b)
- {
- return {a.real + b.real, a.imag + b.imag};
- }
- static inline Z P(Z z, Z c)
- {
- return z * z + c;
- }
- static inline Z::value_type fastNorm(const Z &z)
- {
- return z.real * z.real + z.imag * z.imag;
- }
- template<typename T> static inline T square(T a) { return a * a; }
- template<typename T> static inline T minOf(T a, T b) { return a < b ? a : b; }
- template<typename T> static inline T maxOf(T a, T b) { return a < b ? b : a; }
- template<typename T> static inline T clamp(T min, T value, T max)
- {
- if (value > max) {
- return max;
- }
- return value < min ? min : value;
- }
- struct Pixel
- {
- float blue;
- float green;
- float red;
- };
- static const Pixel NULL_PIXEL = { 0, 0, 0 };
- class Canvas
- {
- public:
- Canvas(int h, int w);
- void addDot(float x, float y, int red, int green, int blue);
- void toQImage(QImage *);
- private:
- void addDot(int x, int y, float red, float green, float blue) {
- Pixel &p = m_pixels[x + y * m_width];
- p.blue += blue;
- p.green += green;
- p.red += red;
- }
- const int m_width;
- std::vector<Pixel> m_pixels;
- };
- Canvas::Canvas(int h, int w)
- : m_width(w), m_pixels(h * w, NULL_PIXEL)
- {
- }
- void Canvas::addDot(float x, float y, int red, int green, int blue)
- {
- const int x1 = static_cast<int>(std::floor(x));
- const int x2 = static_cast<int>(std::ceil (x));
- const int y1 = static_cast<int>(std::floor(y));
- const int y2 = static_cast<int>(std::ceil (y));
- const float xfrac = x - std::floor(x);
- const float yfrac = y - std::floor(y);
- const float r = red;
- const float g = green;
- const float b = blue;
- const float frac11 = (1.f - xfrac) * (1.f - yfrac);
- const float frac12 = (1.f - xfrac) * yfrac;
- const float frac21 = xfrac * (1.f - yfrac);
- const float frac22 = xfrac * yfrac;
- addDot(x1, y1, r * frac11, g * frac11, b * frac11);
- addDot(x2, y1, r * frac21, g * frac21, b * frac21);
- addDot(x1, y2, r * frac12, g * frac12, b * frac12);
- addDot(x2, y2, r * frac22, g * frac22, b * frac22);
- }
- #define BUDDHABROT_USE_FUNCTION1
- #ifdef BUDDHABROT_USE_FUNCTION2
- static inline uchar reduceRange(float x, float m, float h)
- {
- /* m: max, h: median
- * +- -+
- * | 3 3 2 |
- * | 510 h + 127 m - 765 h m |
- * | -------------------------- |
- * | 3 3 2 2 |
- * | h m + h m - 2 h m |
- * | |
- * | 3 3 2 |
- * | - 255 h - 254 m + 765 h m |
- * | ---------------------------- |
- * | 4 2 3 3 2 |
- * | h m - 2 h m + h m |
- * | |
- * | 2 2 |
- * | - 510 h m + 255 h + 127 m |
- * | --------------------------- |
- * | 4 2 3 3 2 |
- * | h m - 2 h m + h m |
- * +- -+
- */
- const float h2 = h * h;
- const float h3 = h2 * h;
- const float m2 = m * m;
- const float m3 = m2 * m;
- const float denom = h * m * square(m - h);
- return minOf(255.f, 0.5f //rounding
- + x / denom * (
- 510.f * h3 + 127.f * m3 - 765.f * h2 * m
- + x / m * (
- 765.f * h * m2 - 255.f * h3 - 254.f * m3
- + x * (
- 255.f * h2 + 127.f * m2 - 510.f * h * m)
- )));
- }
- #elif defined(BUDDHABROT_USE_FUNCTION1)
- static inline unsigned int reduceRange(float x, float m, float h)
- {
- if (x <= m) {
- return 0.5f // rounding
- + 4.f / 255.f * h * h / m * x
- + square(x) * (h / square(m)) * (4.f - 8.f / 255.f * h);
- } else {
- return 0.5f // rounding
- + 255.f - 4.f * h + 4.f / 255.f * square(h)
- + x / m * (16.f * h - 1020.f - 12.f / 255.f * square(h))
- + square(x / m) * (1020.f - 12.f * h + 8.f / 255.f * square(h));
- }
- }
- #endif
- void Canvas::toQImage(QImage *img)
- {
- uchar *line = img->scanLine(0);
- const Pixel *p = &m_pixels[0];
- #ifdef BUDDHABROT_USE_FUNCTION2
- float max [3] = { 0.f, 0.f, 0.f };
- std::vector<float> sorted[3];
- for (int i = 0; i < 3; ++i) {
- sorted[i].reserve(m_pixels.size());
- }
- for (unsigned int i = 0; i < m_pixels.size(); ++i) {
- max[0] = maxOf(max[0], m_pixels[i].red);
- max[1] = maxOf(max[1], m_pixels[i].green);
- max[2] = maxOf(max[2], m_pixels[i].blue);
- if (m_pixels[i].red > 1.f) {
- sorted[0].push_back(m_pixels[i].red);
- }
- if (m_pixels[i].green > 1.f) {
- sorted[1].push_back(m_pixels[i].green);
- }
- if (m_pixels[i].blue > 1.f) {
- sorted[2].push_back(m_pixels[i].blue);
- }
- }
- for (int i = 0; i < 3; ++i) {
- std::sort(sorted[i].begin(), sorted[i].end());
- }
- const float median[3] = {
- sorted[0][sorted[0].size() / 2],
- sorted[1][sorted[1].size() / 2],
- sorted[2][sorted[2].size() / 2]
- };
- /*
- int hist[3][2];
- for (int i = 0; i < 3; ++i) {
- hist[i][0] = hist[i][1] = 0;
- }
- for (unsigned int i = 0; i < m_pixels.size(); ++i) {
- ++hist[0][reduceRange(m_pixels[i].red , max[0], median[0]) / 128];
- ++hist[1][reduceRange(m_pixels[i].green, max[1], median[1]) / 128];
- ++hist[2][reduceRange(m_pixels[i].blue , max[2], median[2]) / 128];
- }
- qDebug() << "Histogram:\n red:"
- << median[0] << hist[0][0] << hist[0][1] << "\ngreen:"
- << median[1] << hist[1][0] << hist[1][1] << "\n blue:"
- << median[2] << hist[2][0] << hist[2][1];
- */
- for (int yy = 0; yy < img->height(); ++yy) {
- for (int xx = 0; xx < img->width(); ++xx) {
- line[0] = reduceRange(p->blue , max[2], median[2]);
- line[1] = reduceRange(p->green, max[1], median[1]);
- line[2] = reduceRange(p->red , max[0], median[0]);
- line += 4;
- ++p;
- }
- }
- #elif defined(BUDDHABROT_USE_FUNCTION1)
- float max[3] = { 0.f, 0.f, 0.f };
- for (unsigned int i = 0; i < m_pixels.size(); ++i) {
- max[0] = maxOf(max[0], m_pixels[i].red);
- max[1] = maxOf(max[1], m_pixels[i].green);
- max[2] = maxOf(max[2], m_pixels[i].blue);
- }
- float h[3] = { 220.f, 220.f, 220.f };
- /*
- int hist[3][2];
- for (int i = 0; i < 3; ++i) {
- hist[i][0] = hist[i][1] = 0;
- }
- for (unsigned int i = 0; i < m_pixels.size(); ++i) {
- ++hist[0][reduceRange(m_pixels[i].red , max[0], h[0]) / 128];
- ++hist[1][reduceRange(m_pixels[i].green, max[1], h[1]) / 128];
- ++hist[2][reduceRange(m_pixels[i].blue , max[2], h[2]) / 128];
- }
- qDebug() << "Histogram:\n red:"
- << hist[0][0] << hist[0][1] << "\ngreen:"
- << hist[1][0] << hist[1][1] << "\n blue:"
- << hist[2][0] << hist[2][1];
- */
- for (int yy = 0; yy < img->height(); ++yy) {
- for (int xx = 0; xx < img->width(); ++xx) {
- line[0] = reduceRange(p->blue , max[2], h[2]);
- line[1] = reduceRange(p->green, max[1], h[1]);
- line[2] = reduceRange(p->red , max[0], h[0]);
- line += 4;
- ++p;
- }
- }
- #else
- float max [3] = { 0.f, 0.f, 0.f };
- float mean [3] = { 0.f, 0.f, 0.f };
- float stddev[3] = { 0.f, 0.f, 0.f };
- for (unsigned int i = 0; i < m_pixels.size(); ++i) {
- max[0] = maxOf(max[0], m_pixels[i].red);
- max[1] = maxOf(max[1], m_pixels[i].green);
- max[2] = maxOf(max[2], m_pixels[i].blue);
- mean[0] += m_pixels[i].red;
- mean[1] += m_pixels[i].green;
- mean[2] += m_pixels[i].blue;
- stddev[0] += square(m_pixels[i].red);
- stddev[1] += square(m_pixels[i].green);
- stddev[2] += square(m_pixels[i].blue);
- }
- const float normalization = 1.f / m_pixels.size();
- mean[0] *= normalization;
- mean[1] *= normalization;
- mean[2] *= normalization;
- stddev[0] = std::sqrt(stddev[0] * normalization - square(mean[0]));
- stddev[1] = std::sqrt(stddev[1] * normalization - square(mean[1]));
- stddev[2] = std::sqrt(stddev[2] * normalization - square(mean[2]));
- qDebug() << " max:" << max[0] << max[1] << max[2];
- qDebug() << " mean:" << mean[0] << mean[1] << mean[2];
- qDebug() << "stddev:" << stddev[0] << stddev[1] << stddev[2];
- // colors have the range 0..max at this point
- // they should be transformed such that for the resulting mean and stddev:
- // mean - stddev = 0
- // mean + stddev = min(min(2 * mean, max), 255)
- //
- // newColor = (c - mean) * min(min(2 * mean, max), 255) * 0.5 / stddev + 127.5
- const float center[3] = {
- minOf(minOf(2.f * mean[0], max[0]), 255.f) * 0.5f,
- minOf(minOf(2.f * mean[1], max[1]), 255.f) * 0.5f,
- minOf(minOf(2.f * mean[2], max[2]), 255.f) * 0.5f
- };
- const float sdFactor[3] = { 2.f, 2.f, 2.f };
- const float redFactor = center[0] / (sdFactor[0] * stddev[0]);
- const float greenFactor = center[1] / (sdFactor[1] * stddev[1]);
- const float blueFactor = center[2] / (sdFactor[2] * stddev[2]);
- for (int yy = 0; yy < img->height(); ++yy) {
- for (int xx = 0; xx < img->width(); ++xx) {
- line[0] = clamp(0, static_cast<int>(center[2] + (p->blue - mean[2]) * blueFactor ), 255);
- line[1] = clamp(0, static_cast<int>(center[1] + (p->green - mean[1]) * greenFactor), 255);
- line[2] = clamp(0, static_cast<int>(center[0] + (p->red - mean[0]) * redFactor ), 255);
- line += 4;
- ++p;
- }
- }
- #endif
- }
- Baker::Options::Options()
- {
- red[0] = 2;
- red[1] = 10;
- green[0] = 0;
- green[1] = 1;
- blue[0] = 11;
- blue[1] = 20;
- it[0] = 10000;
- it[1] = 50000;
- steps[0] = steps[1] = -1;
- }
- void Baker::createImage()
- {
- const int iHeight = m_image.height();
- const int iWidth = m_image.width();
- // Parameters Begin
- const float S = 4.f;
- const float nSteps[2] = {
- static_cast<float>(m_opt.steps[0] == -1 ? std::sqrt(iWidth) * iWidth : m_opt.steps[0]),
- static_cast<float>(m_opt.steps[1] == -1 ? std::sqrt(iHeight) * iHeight : m_opt.steps[1])
- };
- const int upperBound[3] = { m_opt.red[1], m_opt.green[1], m_opt.blue[1] };
- const int lowerBound[3] = { m_opt.red[0], m_opt.green[0], m_opt.blue[0] };
- int overallLowerBound = m_opt.it[0];
- int maxIterations = m_opt.it[1];// maxOf(maxOf(overallLowerBound, upperBound[0]), maxOf(upperBound[1], upperBound[2]));
- float realMin = -2.102613f;
- float realMax = 1.200613f;
- float imagMin = 0.f;
- float imagMax = 1.23971f;
- // Parameters End
- TimeStampCounter timer;
- timer.start();
- // helper constants
- const int overallUpperBound = maxOf(upperBound[0], maxOf(upperBound[1], upperBound[2]));
- const float maxX = static_cast<float>(iWidth ) - 1.f;
- const float maxY = static_cast<float>(iHeight) - 1.f;
- const float xFact = iWidth / m_width;
- const float yFact = iHeight / m_height;
- const float realStep = (realMax - realMin) / nSteps[0];
- const float imagStep = (imagMax - imagMin) / nSteps[1];
- Canvas canvas(iHeight, iWidth);
- #ifdef Scalar
- for (float real = realMin; real <= realMax; real += realStep) {
- m_progress.setValue(99.f * (real - realMin) / (realMax - realMin));
- for (float imag = imagMin; imag <= imagMax; imag += imagStep) {
- Z c{real, imag};
- Z c2{1.08f * real + 0.15f, imag};
- if (fastNorm(Z{real + 1.f, imag}) < 0.06f ||
- (c2.real < 0.42f && fastNorm(c2) < 0.417f)) {
- continue;
- }
- Z z = c;
- int n;
- for (n = 0; n <= maxIterations && fastNorm(z) < S; ++n) {
- z = P(z, c);
- }
- if (n <= maxIterations && n >= overallLowerBound) {
- // point is outside of the Mandelbrot set and required enough (overallLowerBound)
- // iterations to reach the cut-off value S
- Z cn{real, -imag};
- Z zn = cn;
- z = c;
- for (int i = 0; i <= overallUpperBound; ++i) {
- const float y2 = (z.imag - m_y) * yFact;
- const float yn2 = (zn.imag - m_y) * yFact;
- if (y2 >= 0.f && y2 < maxY && yn2 >= 0.f && yn2 < maxY) {
- const float x2 = (z.real - m_x) * xFact;
- if (x2 >= 0.f && x2 < maxX) {
- const int red = (i >= lowerBound[0] && i <= upperBound[0]) ? 1 : 0;
- const int green = (i >= lowerBound[1] && i <= upperBound[1]) ? 1 : 0;
- const int blue = (i >= lowerBound[2] && i <= upperBound[2]) ? 1 : 0;
- canvas.addDot(x2, y2 , red, green, blue);
- canvas.addDot(x2, yn2, red, green, blue);
- }
- }
- z = P(z, c);
- zn = P(zn, cn);
- if (fastNorm(z) >= S) { // optimization: skip some useless looping
- break;
- }
- }
- }
- }
- }
- #else
- const float imagStep2 = imagStep * float_v::Size;
- const float_v imagMin2 = imagMin + imagStep * float_v::IndexesFromZero();
- for (float real = realMin; real <= realMax; real += realStep) {
- m_progress.setValue(99.f * (real - realMin) / (realMax - realMin));
- for (float_v imag = imagMin2; all_of(imag <= imagMax); imag += imagStep2) {
- // FIXME: extra "tracks" if nSteps[1] is not a multiple of float_v::Size
- Z c{real, imag};
- Z c2 = Z{1.08f * real + 0.15f, imag};
- if (all_of(fastNorm(Z{real + 1.f, imag}) < 0.06f ||
- (c2.real < 0.42f && fastNorm(c2) < 0.417f))) {
- continue;
- }
- Z z = c;
- int_v n(Vc::Zero);
- int_m inside = fastNorm(z) < S;
- while (!(inside && n <= maxIterations).isEmpty()) {
- z = P(z, c);
- ++n(inside);
- inside &= fastNorm(z) < S;
- }
- inside |= n < overallLowerBound;
- if (inside.isFull()) {
- continue;
- }
- Z cn{real, -imag};
- Z zn = cn;
- z = c;
- for (int i = 0; i <= overallUpperBound; ++i) {
- const float_v y2 = (z.imag - m_y) * yFact;
- const float_v yn2 = (zn.imag - m_y) * yFact;
- const float_v x2 = (z.real - m_x) * xFact;
- z = P(z, c);
- zn = P(zn, cn);
- const float_m drawMask = !inside && y2 >= 0.f && x2 >= 0.f && y2 < maxY && x2 < maxX && yn2 >= 0.f && yn2 < maxY;
- const int red = (i >= lowerBound[0] && i <= upperBound[0]) ? 1 : 0;
- const int green = (i >= lowerBound[1] && i <= upperBound[1]) ? 1 : 0;
- const int blue = (i >= lowerBound[2] && i <= upperBound[2]) ? 1 : 0;
- for(int j : where(drawMask)) {
- canvas.addDot(x2[j], y2 [j], red, green, blue);
- canvas.addDot(x2[j], yn2[j], red, green, blue);
- }
- if (all_of(fastNorm(z) >= S)) { // optimization: skip some useless looping
- break;
- }
- }
- }
- }
- #endif
- canvas.toQImage(&m_image);
- timer.stop();
- m_progress.done();
- qDebug() << timer.cycles() << "cycles";
- if (m_filename.isEmpty()) {
- m_filename = QString("r%1-%2_g%3-%4_b%5-%6_s%7-%8_i%9-%10_%11x%12.png")
- .arg(lowerBound[0]).arg(upperBound[0])
- .arg(lowerBound[1]).arg(upperBound[1])
- .arg(lowerBound[2]).arg(upperBound[2])
- .arg(nSteps[0]).arg(nSteps[1])
- .arg(overallLowerBound).arg(maxIterations)
- .arg(m_image.width()).arg(m_image.height());
- }
- m_image.save(m_filename);
- }
- static void usage(const char *argv0)
- {
- Baker::Options o;
- QTextStream out(stdout);
- out << "Usage: " << argv0 << " [options] [<filename>]\n\n"
- << "Options:\n"
- << " -h|--help This message.\n"
- << " -s|--size <w> <h> Specify the width and height of the resulting image file. [1024 768]\n"
- << " -r|--red <int> <int> Specify lower and upper iteration bounds for a red trace. ["
- << o.red[0] << ' ' << o.red[1] << "]\n"
- << " -g|--green <int> <int> Specify lower and upper iteration bounds for a green trace. ["
- << o.green[0] << ' ' << o.green[1] << "]\n"
- << " -b|--blue <int> <int> Specify lower and upper iteration bounds for a blue trace. ["
- << o.blue[0] << ' ' << o.blue[1] << "]\n"
- << " --steps <int> <int> Specify the steps in real and imaginary direction. [width^1.5 height^1.5]\n"
- << " --minIt <int> Overall lower iteration bound. [" << o.it[0] << "]\n"
- << " --maxIt <int> Overall upper iteration bound. [" << o.it[1] << "]\n"
- ;
- }
- int Vc_CDECL main(int argc, char **argv)
- {
- QCoreApplication app(argc, argv);
- const QStringList &args = QCoreApplication::arguments();
- if (args.contains("--help") || args.contains("-h")) {
- usage(argv[0]);
- return 0;
- }
- Baker b;
- Baker::Options opt;
- int width = 1024;
- int height = 768;
- // parse args
- for (int i = 1; i < args.size(); ++i) {
- const QString &arg = args[i];
- bool ok = true;
- if (arg == QLatin1String("--red") || arg == QLatin1String("-r")) {
- opt.red[0] = args[++i].toInt(&ok);
- if (ok) {
- opt.red[1] = args[++i].toInt(&ok);
- }
- } else if (arg == QLatin1String("--green") || arg == QLatin1String("-g")) {
- opt.green[0] = args[++i].toInt(&ok);
- if (ok) {
- opt.green[1] = args[++i].toInt(&ok);
- }
- } else if (arg == QLatin1String("--blue") || arg == QLatin1String("-b")) {
- opt.blue[0] = args[++i].toInt(&ok);
- if (ok) {
- opt.blue[1] = args[++i].toInt(&ok);
- }
- } else if (arg == QLatin1String("--steps")) {
- opt.steps[0] = args[++i].toInt(&ok);
- if (ok) {
- opt.steps[1] = args[++i].toInt(&ok);
- }
- } else if (arg == QLatin1String("--minIt")) {
- opt.it[0] = args[++i].toInt(&ok);
- } else if (arg == QLatin1String("--maxIt")) {
- opt.it[1] = args[++i].toInt(&ok);
- } else if (arg == QLatin1String("--size") || arg == QLatin1String("-s")) {
- width = args[++i].toInt(&ok);
- if (ok) {
- height = args[++i].toInt(&ok);
- }
- } else {
- static bool filenameSet = false;
- ok = !filenameSet;
- filenameSet = true;
- b.setFilename(arg);
- }
- if (!ok) {
- usage(argv[0]);
- return 1;
- }
- }
- b.setOptions(opt);
- b.setSize(width, height);
- b.createImage();
- return 0;
- }
|