Example #1
0
QImage MainWindow::PixToQImage(PIX *pixs) {
  // TODO: first check if pixs is PIX ;-) inputFormat(pix)

  // create color tables
  QVector<QRgb> _bwCT;
  _bwCT.append(qRgb(255,255,255));
  _bwCT.append(qRgb(0,0,0));

  QVector<QRgb> _grayscaleCT(256);
  for (int i = 0; i < 256; i++)  {
    _grayscaleCT.append(qRgb(i, i, i));
  }

  l_uint32 * s_data = pixGetData(pixEndianByteSwapNew(pixs));

  int width = pixGetWidth(pixs);
  int height = pixGetHeight(pixs);
  int depth = pixGetDepth(pixs);
  int bytesPerLine = pixGetWpl(pixs) * 4;

  QImage::Format format;
  if (depth == 1)
    format = QImage::Format_Mono;
  else if (depth == 8)
    format = QImage::Format_Indexed8;
  else
    format = QImage::Format_RGB32;

  QImage result((uchar*)s_data, width, height, bytesPerLine, format);
  if (depth == 1) {
    result.setColorTable(_bwCT);
  }  else if (depth == 8)  {
    result.setColorTable(_grayscaleCT);
  } else {
    result.setColorTable(_grayscaleCT);
  }

  if (result.isNull()) {
    static QImage none(0,0,QImage::Format_Invalid);
    qDebug() << "***Invalid format!!!";
    return none;
  }

  // QRgb *line = (QRgb*)(result.scanLine(0));
  // QColor color = QColor::fromRgb(result.pixel(0,0));
  return result.rgbSwapped();
}
Example #2
0
/*!
 *  pixWriteStreamPng()
 *
 *      Input:  stream
 *              pix
 *              gamma (use 0.0 if gamma is not defined)
 *      Return: 0 if OK; 1 on error
 *
 *  Notes:
 *      (1) If called from pixWriteStream(), the stream is positioned
 *          at the beginning of the file.
 *      (2) To do sequential writes of png format images to a stream,
 *          use pixWriteStreamPng() directly.
 *      (3) gamma is an optional png chunk.  If no gamma value is to be
 *          placed into the file, use gamma = 0.0.  Otherwise, if
 *          gamma > 0.0, its value is written into the header.
 *      (4) The use of gamma in png is highly problematic.  For an illuminating
 *          discussion, see:  http://hsivonen.iki.fi/png-gamma/
 *      (5) What is the effect/meaning of gamma in the png file?  This
 *          gamma, which we can call the 'source' gamma, is the
 *          inverse of the gamma that was used in enhance.c to brighten
 *          or darken images.  The 'source' gamma is supposed to indicate
 *          the intensity mapping that was done at the time the
 *          image was captured.  Display programs typically apply a
 *          'display' gamma of 2.2 to the output, which is intended
 *          to linearize the intensity based on the response of
 *          thermionic tubes (CRTs).  Flat panel LCDs have typically
 *          been designed to give a similar response as CRTs (call it
 *          "backward compatibility").  The 'display' gamma is
 *          in some sense the inverse of the 'source' gamma.
 *          jpeg encoders attached to scanners and cameras will lighten
 *          the pixels, applying a gamma corresponding to approximately
 *          a square-root relation of output vs input:
 *                output = input^(gamma)
 *          where gamma is often set near 0.4545  (1/gamma is 2.2).
 *          This is stored in the image file.  Then if the display
 *          program reads the gamma, it will apply a display gamma,
 *          typically about 2.2; the product is 1.0, and the
 *          display program produces a linear output.  This works because
 *          the dark colors were appropriately boosted by the scanner,
 *          as described by the 'source' gamma, so they should not
 *          be further boosted by the display program.
 *      (6) As an example, with xv and display, if no gamma is stored,
 *          the program acts as if gamma were 0.4545, multiplies this by 2.2,
 *          and does a linear rendering.  Taking this as a baseline
 *          brightness, if the stored gamma is:
 *              > 0.4545, the image is rendered lighter than baseline
 *              < 0.4545, the image is rendered darker than baseline
 *          In contrast, gqview seems to ignore the gamma chunk in png.
 *      (7) The only valid pixel depths in leptonica are 1, 2, 4, 8, 16
 *          and 32.  However, it is possible, and in some cases desirable,
 *          to write out a png file using an rgb pix that has 24 bpp.
 *          For example, the open source xpdf SplashBitmap class generates
 *          24 bpp rgb images.  Consequently, we anble writing 24 bpp pix.
 *          To generate such a pix, you can make a 24 bpp pix without data
 *          and assign the data array to the pix; e.g.,
 *              pix = pixCreateHeader(w, h, 24);
 *              pixSetData(pix, rgbdata);
 *          See pixConvert32To24() for an example, where we get rgbdata
 *          from the 32 bpp pix.  Caution: do not call pixSetPadBits(),
 *          because the alignment is wrong and you may erase part of the
 *          last pixel on each line.
 */
l_int32
pixWriteStreamPng(FILE      *fp,
                  PIX       *pix,
                  l_float32  gamma)
{
char         commentstring[] = "Comment";
l_int32      i, j, k;
l_int32      wpl, d, cmflag;
l_int32      ncolors;
l_int32     *rmap, *gmap, *bmap;
l_uint32    *data, *ppixel;
png_byte     bit_depth, color_type;
png_uint_32  w, h;
png_uint_32  xres, yres;
png_bytep   *row_pointers;
png_bytep    rowbuffer;
png_structp  png_ptr;
png_infop    info_ptr;
png_colorp   palette;
PIX         *pixt;
PIXCMAP     *cmap;
char        *text;

    PROCNAME("pixWriteStreamPng");

    if (!fp)
        return ERROR_INT("stream not open", procName, 1);
    if (!pix)
        return ERROR_INT("pix not defined", procName, 1);

        /* Allocate the 2 data structures */
    if ((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
                   (png_voidp)NULL, NULL, NULL)) == NULL)
        return ERROR_INT("png_ptr not made", procName, 1);

    if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
        png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
        return ERROR_INT("info_ptr not made", procName, 1);
    }

        /* Set up png setjmp error handling */
    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_write_struct(&png_ptr, &info_ptr);
        return ERROR_INT("internal png error", procName, 1);
    }

    png_init_io(png_ptr, fp);

        /* With best zlib compression (9), get between 1 and 10% improvement
         * over default (5), but the compression is 3 to 10 times slower.
         * Our default compression is the zlib default (5). */
    png_set_compression_level(png_ptr, var_ZLIB_COMPRESSION);

    w = pixGetWidth(pix);
    h = pixGetHeight(pix);
    d = pixGetDepth(pix);
    if ((cmap = pixGetColormap(pix)))
        cmflag = 1;
    else
        cmflag = 0;

        /* Set the color type and bit depth. */
    if (d == 32 && var_PNG_WRITE_ALPHA == 1) {
        bit_depth = 8;
        color_type = PNG_COLOR_TYPE_RGBA;   /* 6 */
        cmflag = 0;  /* ignore if it exists */
    }
    else if (d == 24 || d == 32) {
        bit_depth = 8;
        color_type = PNG_COLOR_TYPE_RGB;   /* 2 */
        cmflag = 0;  /* ignore if it exists */
    }
    else {
        bit_depth = d;
        color_type = PNG_COLOR_TYPE_GRAY;  /* 0 */
    }
    if (cmflag)
        color_type = PNG_COLOR_TYPE_PALETTE;  /* 3 */

#if  DEBUG
    fprintf(stderr, "cmflag = %d, bit_depth = %d, color_type = %d\n",
            cmflag, bit_depth, color_type);
#endif  /* DEBUG */

    png_set_IHDR(png_ptr, info_ptr, w, h, bit_depth, color_type,
                 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
                 PNG_FILTER_TYPE_BASE);

        /* Store resolution in ppm, if known */
    xres = (png_uint_32)(39.37 * (l_float32)pixGetXRes(pix) + 0.5);
    yres = (png_uint_32)(39.37 * (l_float32)pixGetYRes(pix) + 0.5);
    if ((xres == 0) || (yres == 0))
        png_set_pHYs(png_ptr, info_ptr, 0, 0, PNG_RESOLUTION_UNKNOWN);
    else
        png_set_pHYs(png_ptr, info_ptr, xres, yres, PNG_RESOLUTION_METER);

    if (cmflag) {
        pixcmapToArrays(cmap, &rmap, &gmap, &bmap);
        ncolors = pixcmapGetCount(cmap);

            /* Make and save the palette */
        if ((palette = (png_colorp)(CALLOC(ncolors, sizeof(png_color))))
                == NULL)
            return ERROR_INT("palette not made", procName, 1);

        for (i = 0; i < ncolors; i++) {
            palette[i].red = (png_byte)rmap[i];
            palette[i].green = (png_byte)gmap[i];
            palette[i].blue = (png_byte)bmap[i];
        }

        png_set_PLTE(png_ptr, info_ptr, palette, (int)ncolors);
        FREE(rmap);
        FREE(gmap);
        FREE(bmap);
    }

        /* 0.4545 is treated as the default by some image
         * display programs (not gqview).  A value > 0.4545 will
         * lighten an image as displayed by xv, display, etc. */
    if (gamma > 0.0)
        png_set_gAMA(png_ptr, info_ptr, (l_float64)gamma);

    if ((text = pixGetText(pix))) {
        png_text text_chunk;
        text_chunk.compression = PNG_TEXT_COMPRESSION_NONE;
        text_chunk.key = commentstring;
        text_chunk.text = text;
        text_chunk.text_length = strlen(text);
#ifdef PNG_ITXT_SUPPORTED
        text_chunk.itxt_length = 0;
        text_chunk.lang = NULL;
        text_chunk.lang_key = NULL;
#endif
        png_set_text(png_ptr, info_ptr, &text_chunk, 1);
    }

        /* Write header and palette info */
    png_write_info(png_ptr, info_ptr);

    if ((d != 32) && (d != 24)) {  /* not rgb color */
            /* Generate a temporary pix with bytes swapped.
             * For a binary image, there are two conditions in
             * which you must first invert the data for writing png:
             *    (a) no colormap
             *    (b) colormap with BLACK set to 0
             * png writes binary with BLACK = 0, unless contradicted
             * by a colormap.  If the colormap has BLACK = "1"
             * (typ. about 255), do not invert the data.  If there
             * is no colormap, you must invert the data to store
             * in default BLACK = 0 state.  */
        if (d == 1 &&
            (!cmap || (cmap && ((l_uint8 *)(cmap->array))[0] == 0x0))) {
            pixt = pixInvert(NULL, pix);
            pixEndianByteSwap(pixt);
        }
        else
            pixt = pixEndianByteSwapNew(pix);
        if (!pixt) {
            png_destroy_write_struct(&png_ptr, &info_ptr);
            return ERROR_INT("pixt not made", procName, 1);
        }

            /* Make and assign array of image row pointers */
        if ((row_pointers = (png_bytep *)CALLOC(h, sizeof(png_bytep))) == NULL)
            return ERROR_INT("row-pointers not made", procName, 1);
        wpl = pixGetWpl(pixt);
        data = pixGetData(pixt);
        for (i = 0; i < h; i++)
            row_pointers[i] = (png_bytep)(data + i * wpl);
        png_set_rows(png_ptr, info_ptr, row_pointers);

            /* Transfer the data */
        png_write_image(png_ptr, row_pointers);
        png_write_end(png_ptr, info_ptr);

        if (cmflag)
            FREE(palette);
        FREE(row_pointers);
        pixDestroy(&pixt);
        png_destroy_write_struct(&png_ptr, &info_ptr);
        return 0;
    }

        /* For rgb, compose and write a row at a time */
    data = pixGetData(pix);
    wpl = pixGetWpl(pix);
    if (d == 24) {  /* See note 7 above: special case of 24 bpp rgb */
        for (i = 0; i < h; i++) {
            ppixel = data + i * wpl;
            png_write_rows(png_ptr, (png_bytepp)&ppixel, 1);
        }
    }
    else {  /* 32 bpp rgb and rgba */
        if ((rowbuffer = (png_bytep)CALLOC(w, 4)) == NULL)
            return ERROR_INT("rowbuffer not made", procName, 1);
        for (i = 0; i < h; i++) {
            ppixel = data + i * wpl;
            for (j = k = 0; j < w; j++) {
                rowbuffer[k++] = GET_DATA_BYTE(ppixel, COLOR_RED);
                rowbuffer[k++] = GET_DATA_BYTE(ppixel, COLOR_GREEN);
                rowbuffer[k++] = GET_DATA_BYTE(ppixel, COLOR_BLUE);
                if (var_PNG_WRITE_ALPHA == 1)
                    rowbuffer[k++] = GET_DATA_BYTE(ppixel, L_ALPHA_CHANNEL);
                ppixel++;
            }

            png_write_rows(png_ptr, &rowbuffer, 1);
        }
        FREE(rowbuffer);
    }

    png_write_end(png_ptr, info_ptr);

    if (cmflag)
        FREE(palette);
    png_destroy_write_struct(&png_ptr, &info_ptr);
    return 0;

}