示例#1
0
static UncompressedImage
CGImageToUncompressedImage(CGImageRef image)
{
  if (image == nullptr)
    return UncompressedImage();
  
  size_t width = CGImageGetWidth(image);
  size_t height = CGImageGetHeight(image);
  
  if ((0 == width) || (0 == height))
    return UncompressedImage();
  
  size_t bits_per_pixel = CGImageGetBitsPerPixel(image);
  size_t bits_per_component = CGImageGetBitsPerComponent(image);
  CGColorSpaceRef colorspace = CGImageGetColorSpace(image);
  
  size_t row_size;
  UncompressedImage::Format format;
  CGColorSpaceRef bitmap_colorspace;
  CGBitmapInfo bitmap_info;
  
  if ((8 == bits_per_pixel) &&
      (8 == bits_per_component) &&
      (CGColorSpaceGetModel(colorspace) == kCGColorSpaceModelMonochrome)) {
    row_size = width;
    format = UncompressedImage::Format::GRAY;
    static CGColorSpaceRef grey_colorspace = CGColorSpaceCreateDeviceGray();
    bitmap_colorspace = grey_colorspace;
    bitmap_info = 0;
  } else {
    static CGColorSpaceRef rgb_colorspace = CGColorSpaceCreateDeviceRGB();
    bitmap_colorspace = rgb_colorspace;
    if ((24 == bits_per_pixel) && (8 == bits_per_component)) {
      row_size = width * 3;
      format = UncompressedImage::Format::RGB;
      bitmap_info = kCGBitmapByteOrder32Big;
    } else {
      row_size = width * 4;
      format = UncompressedImage::Format::RGBA;
      bitmap_info = kCGImageAlphaPremultipliedLast |
                    kCGBitmapByteOrder32Big;
    }
  }
  
  std::unique_ptr<uint8_t[]> uncompressed(new uint8_t[height * row_size]);
  
  CGContextRef bitmap = CGBitmapContextCreate(uncompressed.get(), width, height,
                                              8, row_size, bitmap_colorspace,
                                              bitmap_info);
  if (nullptr == bitmap) {
    return UncompressedImage();
  }

  AtScopeExit(bitmap) { CFRelease(bitmap); };

  CGContextDrawImage(bitmap, CGRectMake(0, 0, width, height), image);
  
  return UncompressedImage(format, row_size, width, height,
                           std::move(uncompressed));
}
示例#2
0
文件: LibPNG.cpp 项目: Advi42/XCSoar
UncompressedImage
LoadPNG(Path path)
{
  FileMapping map(path);
  if (map.error())
    return UncompressedImage();

  return LoadPNG(map.data(), map.size());
}
示例#3
0
文件: LibPNG.cpp 项目: Advi42/XCSoar
UncompressedImage
LoadPNG(const void *data, size_t size)
{
  png_structp png_ptr =
    png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
  if (png_ptr == nullptr)
    return UncompressedImage();

  png_infop info_ptr = png_create_info_struct(png_ptr);
  if (info_ptr == nullptr) {
    png_destroy_read_struct(&png_ptr, nullptr, nullptr);
    return UncompressedImage();
  }

  UncompressedImage result = LoadPNG(png_ptr, info_ptr, data, size);
  png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);

  return result;
}
示例#4
0
static UncompressedImage
LoadTiff(TIFFRGBAImage &img)
{
  if (img.width > 8192 || img.height > 8192)
    throw std::runtime_error("TIFF file is too large");

  std::unique_ptr<uint8_t[]> data(new uint8_t[img.width * img.height * 4]);
  uint32_t *data32 = (uint32_t *)(void *)data.get();

  if (!TIFFRGBAImageGet(&img, data32, img.width, img.height))
    throw std::runtime_error("Failed to copy TIFF data");

  return UncompressedImage(UncompressedImage::Format::RGBA, img.width * 4,
                           img.width, img.height, std::move(data), true);
}
示例#5
0
UncompressedImage
LoadJPEGFile(Path path)
{
  CGDataProviderRef data_provider = CGDataProviderCreateWithFilename(path.c_str());
  if (nullptr == data_provider)
    return UncompressedImage();
  
  CGImageRef image =  CGImageCreateWithJPEGDataProvider(
      data_provider, nullptr, false, kCGRenderingIntentDefault);
  
  UncompressedImage result = CGImageToUncompressedImage(image);
  
  if (nullptr != image)
    CFRelease(image);
  CFRelease(data_provider);
  
  return result;
}
示例#6
0
UncompressedImage
LoadPNG(const void *data, size_t size)
{
  CGDataProviderRef data_provider = CGDataProviderCreateWithData(
      nullptr, data, size, nullptr);
  if (nullptr == data_provider)
    return UncompressedImage();
  
  CGImageRef image = CGImageCreateWithPNGDataProvider(
      data_provider, nullptr, false, kCGRenderingIntentDefault);
  
  UncompressedImage result = CGImageToUncompressedImage(image);
  
  if (nullptr != image)
    CFRelease(image);
  CFRelease(data_provider);
  
  return result;
}
示例#7
0
static UncompressedImage
LoadPNG(png_structp png_ptr, png_infop info_ptr,
        const void *data, size_t size)
{
  assert(data != nullptr);

  PNGCallbackContext ctx{(const uint8_t *)data};

  png_set_read_fn(png_ptr, &ctx, PNGReadCallback);

  png_read_info(png_ptr, info_ptr);

  png_uint_32 width, height;
  int bit_depth, color_type, interlace_type;
  png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,
               &color_type, &interlace_type, nullptr, nullptr);

  /* shrink 16 bit to 8 bit */
  png_set_strip_16(png_ptr);

  /* grow 1,2,4 bit to 8 bit */
  png_set_expand(png_ptr);

  if (color_type == PNG_COLOR_TYPE_PALETTE)
    /* no thanks, we don't want a palette, give us RGB or gray
       instead */
    png_set_palette_to_rgb(png_ptr);

  png_read_update_info(png_ptr, info_ptr);
  png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,
               &color_type, &interlace_type, nullptr, nullptr);

  /* check the color type */

  const UncompressedImage::Format format = ConvertColorType(color_type);
  if (format == UncompressedImage::Format::INVALID)
    return UncompressedImage::Invalid();

  /* allocate memory for the uncompressed pixels */

  const unsigned num_channels = png_get_channels(png_ptr, info_ptr);
  const unsigned pitch = (num_channels * bit_depth) / 8 * width;

  uint8_t *uncompressed = new uint8_t[pitch * height];
  if (uncompressed == nullptr)
    return UncompressedImage::Invalid();

  png_bytep *rows = new png_bytep[height];
  if (rows == nullptr) {
    delete[] uncompressed;
    return UncompressedImage::Invalid();
  }

  for (unsigned i = 0; i < height; ++i)
    rows[i] = uncompressed + i * pitch;

  /* uncompress and import into an OpenGL texture */

  png_read_image(png_ptr, rows);
  delete[] rows;

  return UncompressedImage(format, pitch, width, height, uncompressed);
}
示例#8
0
UncompressedImage
LoadPNGFile(const TCHAR *path) 
{

    FILE *file = _tfopen(path, _T("rb"));
    if (file == nullptr)
        return UncompressedImage::Invalid();

    /* Create and initialize the png_struct
     * with the desired error handler
     * functions.  If you want to use the
     * default stderr and longjump method,
     * you can supply NULL for the last
     * three parameters.  We also supply the
     * the compiler header file version, so
     * that we know if the application
     * was compiled with a compatible version
     * of the library.  REQUIRED
     */
    png_structp png_ptr =
            png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
    if (png_ptr == nullptr) {
        fclose(file);
        return UncompressedImage::Invalid();
    }

    /* Allocate/initialize the memory
     * for image information.  REQUIRED. */
    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == nullptr) {
        fclose(file);
        png_destroy_read_struct(&png_ptr, nullptr, nullptr);
        return UncompressedImage::Invalid();
    }
    /* Set error handling if you are
     * using the setjmp/longjmp method
     * (this is the normal method of
     * doing things with libpng).
     * REQUIRED unless you  set up
     * your own error handlers in
     * the png_create_read_struct()
     * earlier.
     */
    if (setjmp(png_jmpbuf(png_ptr))) {
        /* Free all of the memory associated
         * with the png_ptr and info_ptr */
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        fclose(file);
        /* If we get here, we had a
         * problem reading the file */
        return UncompressedImage::Invalid();
    }

    /* Set up the output control if
     * you are using standard C streams */
    png_init_io(png_ptr, file);

    /* If we have already
     * read some of the signature */
    unsigned int sig_read = 0;
    png_set_sig_bytes(png_ptr, sig_read);
    
    /*
     * If you have enough memory to read
     * in the entire image at once, and
     * you need to specify only
     * transforms that can be controlled
     * with one of the PNG_TRANSFORM_*
     * bits (this presently excludes
     * dithering, filling, setting
     * background, and doing gamma
     * adjustment), then you can read the
     * entire image (including pixels)
     * into the info structure with this
     * call
     *
     * PNG_TRANSFORM_STRIP_16 |
     * PNG_TRANSFORM_PACKING  forces 8 bit
     * PNG_TRANSFORM_EXPAND forces to
     *  expand a palette into RGB
     */
    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_GRAY_TO_RGB, NULL);

    png_uint_32 width, height;
    int bit_depth, color_type, interlace_type;
    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
            &interlace_type, NULL, NULL);

    /* check the color type */
    const UncompressedImage::Format format = ConvertColorType(color_type);
    if (format == UncompressedImage::Format::INVALID) {
        fclose(file);
        return UncompressedImage::Invalid();
    }

    /* allocate memory for the uncompressed pixels */
    unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
    uint8_t *uncompressed = new uint8_t[row_bytes * height];

    png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);

    for (png_uint_32 i = 0; i < height; ++i) {
        memcpy(uncompressed + (row_bytes * i), row_pointers[i], row_bytes);
    }

    /* Clean up after the read,
     * and free any memory allocated */
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

    /* Close the file */
    fclose(file);

    /* That's it */
    return UncompressedImage(format, row_bytes, width, height, uncompressed);
}
示例#9
0
 static UncompressedImage Invalid() {
   return UncompressedImage(Format::INVALID, 0, 0, 0, nullptr);
 }
示例#10
0
UncompressedImage
LoadJPEGFile(const char *path)
{
  FILE *file = fopen(path, "rb");
  if (file == nullptr)
    return UncompressedImage::Invalid();

  struct jpeg_decompress_struct cinfo;

  JPEGErrorManager err;
  cinfo.err = jpeg_std_error(&err.base);
  if (setjmp(err.setjmp_buffer)) {
    jpeg_destroy_decompress(&cinfo);
    fclose(file);
    return UncompressedImage::Invalid();
  }

  jpeg_create_decompress(&cinfo);
  jpeg_stdio_src(&cinfo, file);
  jpeg_read_header(&cinfo, (boolean)true);

  if (cinfo.num_components != 3) {
    jpeg_destroy_decompress(&cinfo);
    fclose(file);
    return UncompressedImage::Invalid();
  }

  cinfo.out_color_space = JCS_RGB;
  cinfo.quantize_colors = (boolean)false;
  jpeg_calc_output_dimensions(&cinfo);

  jpeg_start_decompress(&cinfo);

  const unsigned width = cinfo.output_width;
  const unsigned height = cinfo.output_height;

  const size_t row_size = 3 * width;
  const size_t image_buffer_size = row_size * height;
  const size_t row_buffer_size = row_size;
  /* allocate a buffer that holds the uncompressed image plus a row
     buffer with packed 24 bit samples (for libjpeg) */
  uint8_t *const image_buffer =
    new uint8_t[image_buffer_size + row_buffer_size];
  if (image_buffer == nullptr) {
    jpeg_destroy_decompress(&cinfo);
    fclose(file);
    return UncompressedImage::Invalid();
  }

  uint8_t *const row = image_buffer + image_buffer_size;
  JSAMPROW rowptr[1] = { row };

  uint8_t *p = image_buffer;
  while (cinfo.output_scanline < height) {
    jpeg_read_scanlines(&cinfo, rowptr, (JDIMENSION)1);

    p = std::copy(row, row + row_size, p);
  }

  assert(p == image_buffer + image_buffer_size);

  jpeg_finish_decompress(&cinfo);
  jpeg_destroy_decompress(&cinfo);

  fclose(file);

  return UncompressedImage(UncompressedImage::Format::RGB,
                           row_size, width, height,
                           image_buffer);
}