828e18dedab727a70100512daa1c13ecb3a243a2
braney
  Wed Jul 8 09:09:16 2026 -0700
moved pngToLolly out of the kent tree

diff --git src/utils/pngToLolly/pngToLolly.c src/utils/pngToLolly/pngToLolly.c
deleted file mode 100644
index 65e6e621c42..00000000000
--- src/utils/pngToLolly/pngToLolly.c
+++ /dev/null
@@ -1,545 +0,0 @@
-/* pngToLolly - turn a PNG image into a "stemless lolly" bigLolly track, so the
- * Genome Browser renders the picture as a mosaic of colored dots.  Each opaque
- * pixel becomes one lolly: its column maps to a genomic position, its row maps
- * to the lolly value (vertical position), and its color becomes itemRgb.  The
- * lolly's size can be varied by the amount of local detail (variation) in that
- * part of the image.
- *
- * The program writes everything needed for a self-contained assembly hub
- * (BED, autoSql, chrom.sizes, a blank synthetic genome, trackDb, hub.txt,
- * genomes.txt) plus a tiny makeHub.sh that runs faToTwoBit and bedToBigBed. */
-
-/* png.h must come before common.h because of setjmp checking in pngconf.h */
-#include "png.h"
-#include <sys/stat.h>
-#include "common.h"
-#include "linefile.h"
-#include "portable.h"
-#include "hash.h"
-#include "options.h"
-#include "dystring.h"
-#include "obscure.h"
-
-/* The synthetic single-chromosome assembly the dots live on. */
-#define CHROM_NAME "chrImg"
-#define GENOME_DB  "lollyImg"
-
-void usage()
-/* Explain usage and exit. */
-{
-errAbort(
-  "pngToLolly - render a PNG as a stemless-lolly bigLolly track (a dot mosaic).\n"
-  "usage:\n"
-  "   pngToLolly in.png outDir\n"
-  "Writes a ready-to-build assembly hub into outDir.  Then:\n"
-  "   cd outDir && ./makeHub.sh\n"
-  "   # move outDir under ~/public_html and load the printed hubUrl\n"
-  "options:\n"
-  "   -maxDim=N     longest side of the image after downscaling (default 64).\n"
-  "                 Smaller values give smoother lolly-size variation; larger\n"
-  "                 values give more spatial detail.\n"
-  "   -dotSize=N    on-screen dot diameter in pixels (default 8).\n"
-  "   -sizeVar=N    neighborhood radius used to measure local variation\n"
-  "                 (default 1, i.e. a 3x3 window).  0 turns off size variation.\n"
-  "   -sizeLo=F     smallest dot radius, as a fraction of the tiling radius\n"
-  "                 (default 0.65); used for ordinarily-busy areas.\n"
-  "   -sizeBusy=F   extra-small dot radius fraction for the very busiest areas\n"
-  "                 (default 0.4).  The dots shrink from sizeLo toward this only\n"
-  "                 at the high end of busyness, so fine detail stays sharp.\n"
-  "                 Set equal to sizeLo to turn the extra shrink off.\n"
-  "   -sizeHi=F     largest dot radius fraction (default 2.3); by default used\n"
-  "                 for the flattest areas.  Raise sizeLo toward ~1.45 if you want\n"
-  "                 the busy areas to stay overlapped (no white).\n"
-  "   -invertSize   flip it: make busy areas big and flat areas small (default is\n"
-  "                 busier -> smaller dot).\n"
-  "   -jitter=F     random horizontal nudge per dot, as a fraction of a column\n"
-  "                 (default 0.3).  Together with row stagger this breaks up the\n"
-  "                 obvious vertical columns.  0 turns it off.\n"
-  "   -alpha=N      skip pixels whose alpha is below N (0-255, default 128).\n"
-  "   -name=string  short label for the track (default derived from outDir).\n"
-  "   -db=database  instead of a synthetic assembly, emit a track hub for this\n"
-  "                 existing assembly (e.g. hg38).  Requires -pos.\n"
-  "   -pos=chr:s-e  genomic window the mosaic is spread across, when -db is set\n"
-  "                 (e.g. chr19:11089417-11133830).  The image fills the window.\n"
-  );
-}
-
-static struct optionSpec options[] = {
-   {"maxDim", OPTION_INT},
-   {"dotSize", OPTION_INT},
-   {"sizeVar", OPTION_INT},
-   {"sizeLo", OPTION_FLOAT},
-   {"sizeBusy", OPTION_FLOAT},
-   {"sizeHi", OPTION_FLOAT},
-   {"invertSize", OPTION_BOOLEAN},
-   {"jitter", OPTION_FLOAT},
-   {"alpha", OPTION_INT},
-   {"name", OPTION_STRING},
-   {"db", OPTION_STRING},
-   {"pos", OPTION_STRING},
-   {NULL, 0},
-};
-
-/* horizontal sub-column resolution: each dot column spans this many bp, so a
- * dot can be placed at a fraction of a column to break up the grid. */
-#define SUB 64
-
-/* command line options, with defaults */
-int clMaxDim = 64;
-int clDotSize = 8;
-int clSizeVar = 1;
-double clSizeLo = 0.65;
-double clSizeBusy = 0.4;
-double clSizeHi = 2.3;
-boolean clInvertSize = FALSE;
-double clJitter = 0.3;
-int clAlpha = 128;
-char *clName = NULL;
-char *clDb = NULL;
-char *clPos = NULL;
-
-static double hashJitter(int x, int y)
-/* Deterministic pseudo-random value in [-1,1) from the pixel coordinates, so
- * the dot scatter is stable across runs without needing a RNG. */
-{
-unsigned h = ((unsigned)x * 73856093u) ^ ((unsigned)y * 19349663u);
-h = h * 2654435761u + 0x9e3779b9u;
-return ((double)((h >> 8) & 0xffff) / 32768.0) - 1.0;
-}
-
-static unsigned char *readPngRgba(char *fileName, int *retWidth, int *retHeight)
-/* Read a PNG into a freshly allocated row-major RGBA buffer (4 bytes/pixel). */
-{
-png_image image;
-zeroBytes(&image, sizeof(image));
-image.version = PNG_IMAGE_VERSION;
-
-if (!png_image_begin_read_from_file(&image, fileName))
-    errAbort("Can't read PNG %s: %s", fileName, image.message);
-image.format = PNG_FORMAT_RGBA;
-
-unsigned char *buffer = needLargeMem(PNG_IMAGE_SIZE(image));
-if (!png_image_finish_read(&image, NULL, buffer, 0, NULL))
-    {
-    png_image_free(&image);
-    errAbort("Error decoding PNG %s: %s", fileName, image.message);
-    }
-*retWidth = image.width;
-*retHeight = image.height;
-return buffer;
-}
-
-static unsigned char *downscale(unsigned char *src, int sw, int sh, int maxDim,
-                                int *retW, int *retH)
-/* Box-average src down so its longest side is at most maxDim.  Averaging is
- * alpha-weighted so transparent pixels don't darken their neighbors.  Returns a
- * new RGBA buffer (caller frees); the source dimensions are returned when no
- * scaling is needed. */
-{
-int big = (sw > sh) ? sw : sh;
-if (maxDim <= 0 || big <= maxDim)
-    {
-    *retW = sw;
-    *retH = sh;
-    return cloneMem(src, (size_t)sw * sh * 4);
-    }
-double scale = (double)maxDim / big;
-int dw = round(sw * scale);
-int dh = round(sh * scale);
-if (dw < 1) dw = 1;
-if (dh < 1) dh = 1;
-
-unsigned char *dst = needLargeMem((size_t)dw * dh * 4);
-int dx, dy;
-for (dy = 0; dy < dh; ++dy)
-    {
-    int sy0 = (int)((double)dy * sh / dh);
-    int sy1 = (int)((double)(dy + 1) * sh / dh);
-    if (sy1 <= sy0) sy1 = sy0 + 1;
-    for (dx = 0; dx < dw; ++dx)
-        {
-        int sx0 = (int)((double)dx * sw / dw);
-        int sx1 = (int)((double)(dx + 1) * sw / dw);
-        if (sx1 <= sx0) sx1 = sx0 + 1;
-        double sumR = 0, sumG = 0, sumB = 0, sumA = 0;
-        int n = 0;
-        int x, y;
-        for (y = sy0; y < sy1; ++y)
-            for (x = sx0; x < sx1; ++x)
-                {
-                unsigned char *p = src + ((size_t)y * sw + x) * 4;
-                double a = p[3];
-                sumR += p[0] * a;
-                sumG += p[1] * a;
-                sumB += p[2] * a;
-                sumA += a;
-                ++n;
-                }
-        unsigned char *o = dst + ((size_t)dy * dw + dx) * 4;
-        if (sumA > 0)
-            {
-            o[0] = (unsigned char)(sumR / sumA + 0.5);
-            o[1] = (unsigned char)(sumG / sumA + 0.5);
-            o[2] = (unsigned char)(sumB / sumA + 0.5);
-            o[3] = (unsigned char)(sumA / n + 0.5);
-            }
-        else
-            o[0] = o[1] = o[2] = o[3] = 0;
-        }
-    }
-*retW = dw;
-*retH = dh;
-return dst;
-}
-
-static double *luminanceMap(unsigned char *img, int w, int h)
-/* Return a w*h array of luminance values (0-255), -1 for transparent pixels. */
-{
-double *lum = needLargeMem((size_t)w * h * sizeof(double));
-int i;
-for (i = 0; i < w * h; ++i)
-    {
-    unsigned char *p = img + (size_t)i * 4;
-    if (p[3] < clAlpha)
-        lum[i] = -1;
-    else
-        lum[i] = 0.299 * p[0] + 0.587 * p[1] + 0.114 * p[2];
-    }
-return lum;
-}
-
-static double localVariation(double *lum, int w, int h, int x, int y, int radius)
-/* Standard deviation of luminance over the window around (x,y), considering
- * only opaque pixels.  Returns 0 when there isn't enough to compare. */
-{
-double sum = 0, sumSq = 0;
-int n = 0;
-int dx, dy;
-for (dy = -radius; dy <= radius; ++dy)
-    for (dx = -radius; dx <= radius; ++dx)
-        {
-        int nx = x + dx, ny = y + dy;
-        if (nx < 0 || nx >= w || ny < 0 || ny >= h)
-            continue;
-        double v = lum[(size_t)ny * w + nx];
-        if (v < 0)
-            continue;
-        sum += v;
-        sumSq += v * v;
-        ++n;
-        }
-if (n < 2)
-    return 0;
-double mean = sum / n;
-double var = sumSq / n - mean * mean;
-if (var < 0)
-    var = 0;
-return sqrt(var);
-}
-
-void pngToLolly(char *inPng, char *outDir)
-/* Read the PNG, downscale, and write the hub files into outDir. */
-{
-int sw, sh;
-unsigned char *raw = readPngRgba(inPng, &sw, &sh);
-verbose(1, "read %s: %dx%d\n", inPng, sw, sh);
-
-int w = 0, h = 0;
-unsigned char *img = downscale(raw, sw, sh, clMaxDim, &w, &h);
-freez(&raw);
-verbose(1, "rendering as %dx%d dots\n", w, h);
-
-double *lum = (clSizeVar > 0) ? luminanceMap(img, w, h) : NULL;
-
-/* Geometry.  Adjacent dot columns are dotSize pixels apart, and rows are
- * dotSize pixels apart vertically.  Each column spans SUB bp so a dot can be
- * placed at a fraction of a column; the genome is therefore w*SUB bp wide and
- * 1 bp == dotSize/SUB pixels.  See lollyTrack.c for how the value maps onto
- * usableHeight = trackHeight - LOLLY_DIAMETER - fontHeight. */
-double tileRadius = clDotSize / 2.0;             /* radius that exactly tiles */
-/* The largest dot fraction sets the pixel radius used for the top/bottom
- * margin and the maxHeightPixels we emit. */
-double maxFrac = (clSizeHi > 1.0) ? clSizeHi : 1.0;
-int maxRadius = (int)ceil(tileRadius * (lum != NULL ? maxFrac : 1.0));
-int lollyDiameter = 2 * (maxRadius + 2);         /* matches LOLLY_DIAMETER */
-int fontHeight = 9;                              /* tl.fontHeight + 1, default font */
-int trackHeight = (h - 1) * clDotSize + lollyDiameter + fontHeight;
-if (trackHeight < lollyDiameter + fontHeight + clDotSize)
-    trackHeight = lollyDiameter + fontHeight + clDotSize;
-int pix = w * clDotSize;
-
-/* Where the dots live.  By default a synthetic single-chromosome assembly with
- * each column spanning SUB bp.  With -db/-pos the dots instead spread across a
- * real genomic window on an existing assembly, so the image fills that window. */
-char *chromName = CHROM_NAME;
-long winStart = 0;
-int chromSize = w * SUB;                          /* synthetic chrom length */
-double colSpacing = SUB;                          /* bp between dot columns */
-if (clDb != NULL)
-    {
-    if (clPos == NULL)
-        errAbort("-db requires -pos (e.g. -pos=chr19:11089417-11133830)");
-    /* parse chr:start-end, tolerating commas in the numbers */
-    char *spec = cloneString(clPos);
-    stripChar(spec, ',');
-    char *colon = strrchr(spec, ':');
-    char *dash = colon ? strchr(colon, '-') : NULL;
-    if (colon == NULL || dash == NULL)
-        errAbort("can't parse -pos=%s (expected chr:start-end)", clPos);
-    *colon = *dash = '\0';
-    long e = atol(dash + 1);
-    winStart = atol(colon + 1) - 1;               /* 1-based display -> 0-based */
-    if (winStart < 0)
-        winStart = 0;
-    if (e <= winStart)
-        errAbort("-pos end must be greater than start: %s", clPos);
-    chromName = cloneString(spec);
-    colSpacing = (double)(e - winStart) / w;
-    chromSize = e;                                /* only used for clamping */
-    }
-
-makeDirsOnPath(outDir);
-char path[PATH_LEN];
-
-/* The BED: bed9 + a lolly-size field.  Color comes from itemRgb (field 9);
- * the score field carries the row value that becomes the vertical position. */
-safef(path, sizeof(path), "%s/img.bed", outDir);
-FILE *bed = mustOpen(path, "w");
-int x, y;
-long dots = 0;
-int minSize = BIGNUM, maxSize = 0;
-for (y = 0; y < h; ++y)
-    {
-    for (x = 0; x < w; ++x)
-        {
-        unsigned char *p = img + ((size_t)y * w + x) * 4;
-        if (p[3] < clAlpha)
-            continue;
-        int val = (h - 1) - y;                   /* top row -> highest value */
-
-        /* lolly radius in pixels, from local variation.  By default busier
-         * areas (more variation) get smaller dots, flat areas get bigger ones;
-         * -invertSize flips that. */
-        double radius = tileRadius;
-        double busy = 0.5;
-        if (lum != NULL)
-            {
-            busy = localVariation(lum, w, h, x, y, clSizeVar) / 80.0;
-            if (busy > 1.0) busy = 1.0;
-            busy = pow(busy, 0.6);               /* push more areas toward small */
-            if (clInvertSize) busy = 1.0 - busy;
-            double frac = clSizeHi + (clSizeLo - clSizeHi) * busy;
-            /* The very busiest areas shrink further, from sizeLo toward sizeBusy.
-             * The cubic concentrates this at the high end so ordinarily-busy
-             * areas keep their sizeLo dots. */
-            if (clSizeBusy < clSizeLo)
-                frac -= (clSizeLo - clSizeBusy) * pow(busy, 3.0);
-            radius = tileRadius * frac;
-            }
-        /* The browser renders the lolly radius as sizeField * trackHeight / 100
-         * (see lollyTrack.c), so convert our desired pixel radius into that
-         * percent-of-height unit.  trackHeight is large, so this quantizes to a
-         * few integer levels - that is an inherent limit of the percent scheme. */
-        int sizeVal = round(radius * 100.0 / trackHeight);
-        if (sizeVal < 1)
-            sizeVal = 1;
-        if (sizeVal < minSize) minSize = sizeVal;
-        if (sizeVal > maxSize) maxSize = sizeVal;
-
-        /* Horizontal placement, in fractions of a column.  Stagger alternate
-         * rows by half a column and add a size-weighted random nudge so the
-         * dots don't line up into obvious vertical stripes. */
-        double offset = (y & 1) ? 0.5 : 0.0;
-        offset += clJitter * (1.0 + busy) * hashJitter(x, y);
-        double centerBp = winStart + (x + 0.5 + offset) * colSpacing;
-        long start = (long)floor(centerBp);      /* lolly center uses start+0.5 */
-        if (start < winStart)
-            start = winStart;
-        if (start > chromSize - 1)
-            start = chromSize - 1;
-
-        fprintf(bed, "%s\t%ld\t%ld\tp%d_%d\t%d\t.\t%ld\t%ld\t%d,%d,%d\t%d\n",
-            chromName, start, start + 1, x, y, val, start, start + 1,
-            p[0], p[1], p[2], sizeVal);
-        ++dots;
-        }
-    }
-carefulClose(&bed);
-verbose(1, "wrote %ld dots; %d size level(s), rendered radius %g-%g px\n",
-    dots, maxSize - minSize + 1, minSize * trackHeight / 100.0,
-    maxSize * trackHeight / 100.0);
-
-/* autoSql for the bed9+1 */
-safef(path, sizeof(path), "%s/lolly.as", outDir);
-FILE *as = mustOpen(path, "w");
-fprintf(as,
-    "table lolly\n"
-    "\"stemless lolly mosaic\"\n"
-    "    (\n"
-    "    string chrom;      \"Reference sequence chromosome\"\n"
-    "    uint   chromStart; \"Start position in chromosome\"\n"
-    "    uint   chromEnd;   \"End position in chromosome\"\n"
-    "    string name;       \"Pixel id\"\n"
-    "    uint   score;      \"Row value (vertical position)\"\n"
-    "    char[1] strand;    \"Unused\"\n"
-    "    uint   thickStart; \"Unused\"\n"
-    "    uint   thickEnd;   \"Unused\"\n"
-    "    uint   itemRgb;    \"Pixel color\"\n"
-    "    uint   lollySize;  \"Dot size (percent of track height *100)\"\n"
-    "    )\n");
-carefulClose(&as);
-
-/* chrom.sizes and a blank synthetic genome.  For a track hub on an existing
- * assembly we skip these; makeHub.sh fetches the real chrom.sizes instead. */
-if (clDb == NULL)
-    {
-    safef(path, sizeof(path), "%s/chrom.sizes", outDir);
-    FILE *cs = mustOpen(path, "w");
-    fprintf(cs, "%s\t%d\n", CHROM_NAME, chromSize);
-    carefulClose(&cs);
-
-    safef(path, sizeof(path), "%s/img.fa", outDir);
-    FILE *fa = mustOpen(path, "w");
-    fprintf(fa, ">%s\n", CHROM_NAME);
-    int col;
-    for (col = 0; col < chromSize; ++col)
-        {
-        fputc('N', fa);
-        if ((col % 60) == 59)
-            fputc('\n', fa);
-        }
-    if ((chromSize % 60) != 0)
-        fputc('\n', fa);
-    carefulClose(&fa);
-    }
-
-char *name = clName;
-if (name == NULL)
-    {
-    char dir[PATH_LEN], base[FILENAME_LEN], ext[FILEEXT_LEN];
-    splitPath(outDir, dir, base, ext);
-    name = cloneString(base[0] ? base : "lollyImg");
-    }
-
-/* trackDb.txt.  Squish visibility gives clean filled dots (no black outline).
- * Squish halves the configured height, so maxHeightPixels is set to 2*height.
- * lollyMaxSize is the biggest rendered radius (maxSize * trackHeight / 100), so
- * the top/bottom margin (LOLLY_DIAMETER) leaves room for the largest dot. */
-int lollyMaxSizePx = (int)ceil(maxSize * trackHeight / 100.0);
-safef(path, sizeof(path), "%s/trackDb.txt", outDir);
-FILE *tdb = mustOpen(path, "w");
-fprintf(tdb,
-    "track %s\n"
-    "type bigLolly\n"
-    "shortLabel %s\n"
-    "longLabel %s lolly mosaic\n"
-    "bigDataUrl img.bb\n"
-    "visibility squish\n"
-    "lollyNoStems on\n"
-    "lollySizeField lollySize\n"
-    "lollyMaxSize %d\n"
-    "yAxisNumLabels off\n"
-    "autoScale off\n"
-    "viewLimits 0:%d\n"
-    "maxHeightPixels %d:%d:1\n"
-    "itemRgb on\n",
-    GENOME_DB, name, name, lollyMaxSizePx, h - 1, 2 * trackHeight, 2 * trackHeight);
-carefulClose(&tdb);
-
-/* hub.txt and genomes.txt for a single-genome assembly hub */
-safef(path, sizeof(path), "%s/hub.txt", outDir);
-FILE *hub = mustOpen(path, "w");
-fprintf(hub,
-    "hub %sLolly\n"
-    "shortLabel %s lolly\n"
-    "longLabel %s rendered as a stemless lolly mosaic\n"
-    "genomesFile genomes.txt\n"
-    "email %s\n",
-    name, name, name, "genome-www@soe.ucsc.edu");
-carefulClose(&hub);
-
-safef(path, sizeof(path), "%s/genomes.txt", outDir);
-FILE *gen = mustOpen(path, "w");
-if (clDb != NULL)
-    fprintf(gen,
-        "genome %s\n"
-        "trackDb trackDb.txt\n",
-        clDb);
-else
-    fprintf(gen,
-        "genome %s\n"
-        "trackDb trackDb.txt\n"
-        "twoBitPath img.2bit\n"
-        "organism Lolly art\n"
-        "scientificName %s\n"
-        "description %s lolly mosaic\n"
-        "defaultPos %s:1-%d\n",
-        GENOME_DB, name, name, CHROM_NAME, chromSize);
-carefulClose(&gen);
-
-/* makeHub.sh - turns the text/data files into the 2bit and bigBed */
-safef(path, sizeof(path), "%s/makeHub.sh", outDir);
-FILE *shf = mustOpen(path, "w");
-if (clDb != NULL)
-    fprintf(shf,
-        "#!/bin/sh\n"
-        "# Build the bigLolly for this track hub.  Run from this directory.\n"
-        "set -e\n"
-        "fetchChromSizes %s > chrom.sizes\n"
-        "bedToBigBed -sort -as=lolly.as -type=bed9+1 -tab img.bed chrom.sizes img.bb\n"
-        "echo 'done - move this directory under ~/public_html and load hub.txt'\n",
-        clDb);
-else
-    fprintf(shf,
-        "#!/bin/sh\n"
-        "# Build the 2bit and bigLolly for this hub.  Run from this directory.\n"
-        "set -e\n"
-        "faToTwoBit img.fa img.2bit\n"
-        "bedToBigBed -sort -as=lolly.as -type=bed9+1 -tab img.bed chrom.sizes img.bb\n"
-        "echo 'done - move this directory under ~/public_html and load hub.txt'\n");
-carefulClose(&shf);
-chmod(path, 0755);
-
-verbose(1, "wrote hub to %s\n", outDir);
-printf("\n");
-printf("Next steps:\n");
-printf("  cd %s && ./makeHub.sh\n", outDir);
-printf("  # then move %s under ~/public_html and load:\n", outDir);
-if (clDb != NULL)
-    printf("  https://hgwdev-braney.gi.ucsc.edu/cgi-bin/hgTracks?"
-           "db=%s&hubUrl=<your-public-url>/%s/hub.txt"
-           "&position=%s:%ld-%d&pix=%d&%s=squish\n",
-           clDb, name, chromName, winStart + 1, chromSize, pix, GENOME_DB);
-else
-    printf("  https://hgwdev-braney.gi.ucsc.edu/cgi-bin/hgTracks?"
-           "hubUrl=<your-public-url>/%s/hub.txt"
-           "&genome=%s&position=%s:1-%d&pix=%d&%s=squish\n",
-           name, GENOME_DB, CHROM_NAME, chromSize, pix, GENOME_DB);
-
-freez(&img);
-freez(&lum);
-}
-
-int main(int argc, char *argv[])
-/* Process command line. */
-{
-optionInit(&argc, argv, options);
-if (argc != 3)
-    usage();
-clMaxDim = optionInt("maxDim", clMaxDim);
-clDotSize = optionInt("dotSize", clDotSize);
-clSizeVar = optionInt("sizeVar", clSizeVar);
-clSizeLo = optionFloat("sizeLo", clSizeLo);
-clSizeBusy = optionFloat("sizeBusy", clSizeBusy);
-clSizeHi = optionFloat("sizeHi", clSizeHi);
-clInvertSize = optionExists("invertSize");
-clJitter = optionFloat("jitter", clJitter);
-clAlpha = optionInt("alpha", clAlpha);
-clName = optionVal("name", clName);
-clDb = optionVal("db", clDb);
-clPos = optionVal("pos", clPos);
-if (clDotSize < 2)
-    errAbort("-dotSize must be at least 2");
-pngToLolly(argv[1], argv[2]);
-return 0;
-}