Beispiel #1
0
void png_load_from_memory(aasset_buffer_t& buf, raw_bitmap_t* out_bitmap)
{
    //png header - 8 bytes
    if (png_sig_cmp(buf.data(), 0, 8))
    {
        my_assert(false && "Couldn't load texture. It isn't png file.");
        return;
    }

    auto png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    my_assert(png_ptr && "Couldn't load texture. Png load error.");
    MAKE_GUARD(png_ptr, [](decltype(png_ptr) ptr)
    {   png_destroy_read_struct(&ptr, (png_infopp)NULL, (png_infopp)NULL);});

    auto info_ptr = png_create_info_struct(png_ptr);
    my_assert(info_ptr && "Couldn't load texture. Png load error.");
    auto info_deleter = [png_ptr](decltype(info_ptr) ptr)
    {   png_destroy_info_struct(png_ptr, &ptr);};
    MAKE_GUARD(info_ptr, info_deleter);

    // the code in this if statement gets called if libpng encounters an error
    if (setjmp((long*) png_jmpbuf(png_ptr)))
    {
        my_assert(false && "error from libpng");
        return;
    }

    png_set_read_fn(png_ptr, &buf, read_from_aasset_buffer);
    // tell libpng we already read the signature
    png_set_sig_bytes(png_ptr, 8);
    buf.seek(8);

    png_read_info(png_ptr, info_ptr);

    png_uint_32 width = 0;
    png_uint_32 height = 0;
    int bitDepth = 0;
    int colorType = -1;
    auto res = png_get_IHDR(png_ptr, info_ptr, &width, &height, &bitDepth, &colorType, NULL, NULL, NULL);
    my_assert(res == 1);

    bool transparency = false;
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
    {
        png_set_tRNS_to_alpha(png_ptr);
        transparency = true;
    }
    // Expands PNG with less than 8bits per channel to 8bits.
    if (bitDepth < 8)
    {
        png_set_packing(png_ptr);
        // Shrinks PNG with 16bits per color channel down to 8bits.
    }
    else if (bitDepth == 16)
    {
        png_set_strip_16(png_ptr);
    }

    uint32_t format = 0;
    switch (colorType)
    {
        case PNG_COLOR_TYPE_RGB:
            format = transparency ? GL_RGBA : GL_RGB;
            break;

        case PNG_COLOR_TYPE_RGBA:
            format = GL_RGBA;
            break;

        case PNG_COLOR_TYPE_PALETTE:
        {
            png_set_palette_to_rgb(png_ptr);
            format = transparency ? GL_RGBA : GL_RGB;
            break;
        }
        default:
            my_assert(false && "Png read error. Uknown color type");
            return;
    }
    //apply transformations
    png_read_update_info(png_ptr, info_ptr);

    out_bitmap->init(width, height, format);

    auto row_size = png_get_rowbytes(png_ptr, info_ptr);
    my_assert(row_size > 0);
    my_assert(row_size == width * out_bitmap->bytes_per_pixel());

    auto row_ptrs = new png_bytep[height];
    MAKE_GUARD(row_ptrs, [](decltype(row_ptrs) ptr)
    {   delete[] ptr;});

    for (int32_t i = 0; i < height; ++i)
    {
        row_ptrs[height - (i + 1)] = out_bitmap->get_row(i);
    }

    png_read_image(png_ptr, row_ptrs);
}
Beispiel #2
0
TypedImage LoadPng(const std::string& filename)
{
#ifdef HAVE_PNG
    FILE *in = fopen(filename.c_str(), "rb");
    
    if( in )  {
        //check the header
        const size_t nBytes = 8;
        png_byte header[nBytes];
        size_t nread = fread(header, 1, nBytes, in);
        int nIsPNG = png_sig_cmp(header, 0, nread);
        
        if ( nIsPNG != 0 )  {
            throw std::runtime_error( filename + " is not a PNG file" );
        }
        
        //set up initial png structs
        png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, &PngWarningsCallback);
        if (!png_ptr) {
            throw std::runtime_error( "PNG Init error 1" );
        }
        
        png_infop info_ptr = png_create_info_struct(png_ptr);
        if (!info_ptr)  {
            png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
            throw std::runtime_error( "PNG Init error 2" );
        }
        
        png_infop end_info = png_create_info_struct(png_ptr);
        if (!end_info) {
            png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
            throw std::runtime_error( "PNG Init error 3" );
        }
        
        png_init_io(png_ptr, in);
        png_set_sig_bytes(png_ptr, nBytes);
        
        //read the file
        png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
        
        if( png_get_bit_depth(png_ptr, info_ptr) == 1)  {
            //Unpack bools to bytes to ease loading.
            png_set_packing(png_ptr);
        } else if( png_get_bit_depth(png_ptr, info_ptr) < 8) {
            //Expand nonbool colour depths up to 8bpp
            png_set_expand_gray_1_2_4_to_8(png_ptr);
        }
        
        //Get rid of palette, by transforming it to RGB
        if(png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE) {
            png_set_palette_to_rgb(png_ptr);
        }
        
        if( png_get_interlace_type(png_ptr,info_ptr) != PNG_INTERLACE_NONE) {
            throw std::runtime_error( "Interlace not yet supported" );
        }
        
        const size_t w = png_get_image_width(png_ptr,info_ptr);
        const size_t h = png_get_image_height(png_ptr,info_ptr);
        const size_t pitch = png_get_rowbytes(png_ptr, info_ptr);
        
        TypedImage img;
        img.Alloc(w, h, PngFormat(png_ptr, info_ptr), pitch);
        
        png_bytepp rows = png_get_rows(png_ptr, info_ptr);
        for( unsigned int r = 0; r < h; r++) {
            memcpy( img.ptr + pitch*r, rows[r], pitch );
        }
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        
        fclose(in);
        return img;
    }
    
    throw std::runtime_error("Unable to load PNG file, '" + filename + "'");    
    
#else
    throw std::runtime_error("PNG Support not enabled. Please rebuild Pangolin.");
#endif
}
Beispiel #3
0
void png::load(const std::string& file_name)
{
    // unfortunately, we need to break down to the C-code level here, since
    // libpng is written in C itself

    // we need to open the file in binary mode
    FILE* fp = fopen(file_name.c_str(), "rb");
    if (!fp)
    {
        throw std::runtime_error{"failed to open " + file_name};
    }

    // read in the header (max size of 8), use it to validate this as a png file
    png_byte header[8];
    fread(header, 1, 8, fp);
    if (png_sig_cmp(header, 0, 8))
    {
        fclose(fp);
        throw std::runtime_error{file_name + " is not a valid png file"};
    }

    // set up libpng structs for reading info
    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr,
                                                 nullptr, nullptr);
    if (!png_ptr)
    {
        fclose(fp);
        throw std::runtime_error{"Failed to create libpng read struct"};
    }

    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        png_destroy_read_struct(&png_ptr, nullptr, nullptr);
        fclose(fp);
        throw std::runtime_error{"Failed to create libpng info struct"};
    }

    // set error handling to not abort the entire program
    if (setjmp(png_jmpbuf(png_ptr)))
    {
        png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
        fclose(fp);
        throw std::runtime_error{"Error reading png metadata"};
    }

    // initialize png reading
    png_init_io(png_ptr, fp);
    // let it know we've already read the first 8 bytes
    png_set_sig_bytes(png_ptr, 8);

    // read in the basic image info
    png_read_info(png_ptr, info_ptr);

    // convert to 8 bits
    png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);
    if (bit_depth == 16)
        png_set_strip_16(png_ptr);

    // verify this is in RGBA format, and if not, convert it to RGBA
    png_byte color_type = png_get_color_type(png_ptr, info_ptr);
    if (color_type != PNG_COLOR_TYPE_RGBA && color_type != PNG_COLOR_TYPE_RGB)
    {
        if (color_type == PNG_COLOR_TYPE_GRAY || color_type
                                                 == PNG_COLOR_TYPE_GRAY_ALPHA)
        {
            if (bit_depth < 8)
                png_set_expand(png_ptr);
            png_set_gray_to_rgb(png_ptr);
        }
        if (color_type == PNG_COLOR_TYPE_PALETTE)
            png_set_palette_to_rgb(png_ptr);
    }
    // convert tRNS to alpha channel
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
        png_set_tRNS_to_alpha(png_ptr);

    size_t width = png_get_image_width(png_ptr, info_ptr);
    size_t height = png_get_image_height(png_ptr, info_ptr);
    rgba_pixel* newpix = nullptr;
    png_byte* row = nullptr;

    png_read_update_info(png_ptr, info_ptr);

    // begin reading in the image
    if (setjmp(png_jmpbuf(png_ptr)))
    {
        delete[] newpix;
        delete[] row;
        png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
        fclose(fp);
        throw std::runtime_error{"Error reading image with libpng"};
    }

    int bpr = png_get_rowbytes(png_ptr, info_ptr); // number of bytes in a row

    // initialize our image storage
    newpix = new rgba_pixel[height * width];
    row = new png_byte[bpr];

    int numchannels = png_get_channels(png_ptr, info_ptr);
    for (size_t y = 0; y < height; y++)
    {
        png_read_row(png_ptr, row, nullptr);
        png_byte* pix = row;
        for (size_t x = 0; x < width; x++)
        {
            rgba_pixel& px = newpix[width * y + x];
            if (numchannels == 1 || numchannels == 2)
            {
                // monochrome
                unsigned char color = (unsigned char)*pix++;
                px.red = color;
                px.green = color;
                px.blue = color;
                if (numchannels == 2)
                    px.alpha = (unsigned char)*pix++;
                else
                    px.alpha = 255;
            }
            else if (numchannels == 3 || numchannels == 4)
            {
                px.red = (unsigned char)*pix++;
                px.green = (unsigned char)*pix++;
                px.blue = (unsigned char)*pix++;
                if (numchannels == 4)
                    px.alpha = (unsigned char)*pix++;
                else
                    px.alpha = 255;
            }
        }
    }

    // replace image
    delete[] pixels_;
    pixels_ = newpix;
    width_ = width;
    height_ = height;

    // cleanup
    delete[] row;
    png_read_end(png_ptr, nullptr);
    png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
    fclose(fp);
}
Beispiel #4
0
Py::Object
_image_module::readpng(const Py::Tuple& args) {
  
  args.verify_length(1);
  std::string fname = Py::String(args[0]);
  
  png_byte header[8];	// 8 is the maximum size that can be checked

  FILE *fp = fopen(fname.c_str(), "rb");
  if (!fp)
    throw Py::RuntimeError("_image_module::readpng could not open PNG file for reading");

  fread(header, 1, 8, fp);
  if (png_sig_cmp(header, 0, 8))
    throw Py::RuntimeError("_image_module::readpng: file not recognized as a PNG file");
  
  
  /* initialize stuff */
  png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  
  if (!png_ptr)
    throw Py::RuntimeError("_image_module::readpng:  png_create_read_struct failed");
  
  png_infop info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr)
    throw Py::RuntimeError("_image_module::readpng:  png_create_info_struct failed");
  
  if (setjmp(png_jmpbuf(png_ptr)))
    throw Py::RuntimeError("_image_module::readpng:  error during init_io");
  
  png_init_io(png_ptr, fp);
  png_set_sig_bytes(png_ptr, 8);
  
  png_read_info(png_ptr, info_ptr);
  
  png_uint_32 width = info_ptr->width;
  png_uint_32 height = info_ptr->height;

  // convert misc color types to rgb for simplicity
  if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY ||
      info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
    png_set_gray_to_rgb(png_ptr);  
  else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
    png_set_palette_to_rgb(png_ptr);


  int bit_depth = info_ptr->bit_depth;
  if (bit_depth == 16)  png_set_strip_16(png_ptr);


  png_set_interlace_handling(png_ptr);
  png_read_update_info(png_ptr, info_ptr);
  
  bool rgba = info_ptr->color_type == PNG_COLOR_TYPE_RGBA;
  if ( (info_ptr->color_type != PNG_COLOR_TYPE_RGB) && !rgba) {
    std::cerr << "Found color type " << (int)info_ptr->color_type  << std::endl;
    throw Py::RuntimeError("_image_module::readpng: cannot handle color_type");
  }
  
  /* read file */
  if (setjmp(png_jmpbuf(png_ptr)))
    throw Py::RuntimeError("_image_module::readpng: error during read_image");
  
   png_bytep row_pointers[height];

   for (png_uint_32 row = 0; row < height; row++)
     row_pointers[row] = new png_byte[png_get_rowbytes(png_ptr,info_ptr)];
  
  png_read_image(png_ptr, row_pointers);
  

  
  int dimensions[3];
  dimensions[0] = height;  //numrows
  dimensions[1] = width;   //numcols
  dimensions[2] = 4;

  PyArrayObject *A = (PyArrayObject *) PyArray_FromDims(3, dimensions, PyArray_FLOAT);

  
  for (png_uint_32 y = 0; y < height; y++) {
    png_byte* row = row_pointers[y];
    for (png_uint_32 x = 0; x < width; x++) {
      
      png_byte* ptr = (rgba) ? &(row[x*4]) : &(row[x*3]);
      size_t offset = y*A->strides[0] + x*A->strides[1];
      //if ((y<10)&&(x==10)) std::cout << "r = " << ptr[0] << " " << ptr[0]/255.0 << std::endl;
      *(float*)(A->data + offset + 0*A->strides[2]) = ptr[0]/255.0;
      *(float*)(A->data + offset + 1*A->strides[2]) = ptr[1]/255.0;
      *(float*)(A->data + offset + 2*A->strides[2]) = ptr[2]/255.0;
      *(float*)(A->data + offset + 3*A->strides[2]) = rgba ? ptr[3]/255.0 : 1.0;
    }
  }
  
  //free the png memory
  png_read_end(png_ptr, info_ptr);
  png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
  fclose(fp);
  for (png_uint_32 row = 0; row < height; row++)
    delete [] row_pointers[row];
  return Py::asObject((PyObject*)A);
}
Beispiel #5
0
uint32_t * load_png(struct load_image *args)
{
	png_structp png;
	png_infop info;
	int color_type;
	void *rgb_data;
	png_bytep *pointers;
	int i;
	png_uint_32 w,h;
	int depth;
	struct png_context context;
	png_uint_32 stride;
	
	if(png_sig_cmp(args->data, 0, 8)) {
		DEBUG_PUTS("not png");
		return 0;
	}
	png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
	info = png_create_info_struct(png);
	context.data = args->data;
	context.len = args->length;
	context.pos = 8;
	png_set_read_fn(png, &context, &read_callback);
	png_set_sig_bytes(png, 8);
	png_read_info(png, info);
	png_get_IHDR(png, info, &w, &h, &depth, &color_type, 0, 0, 0);
	DEBUG_PRINTF("w: %d\n", w);
	DEBUG_PRINTF("h: %d\n", h);
	switch (color_type) {
		case PNG_COLOR_TYPE_PALETTE:
		DEBUG_PUTS("pallete");
		png_set_palette_to_rgb(png);
		break;
		case PNG_COLOR_TYPE_RGB_ALPHA:
		DEBUG_PUTS("rgba");
		break;
		default:
		rgb_data = 0;
		goto out;
	};
	png_set_filler(png, 0xff, PNG_FILLER_AFTER);
	pointers = (png_bytep *) malloc(h * sizeof(*pointers));
	if (!pointers) {
		rgb_data = 0;
		goto out;
	}
	stride = png_get_rowbytes(png, info);
	rgb_data = malloc(stride * 4 * h);
	if (!rgb_data) {
		rgb_data = 0;
		goto out;
	}
	for (i = 0; i < h; i++)
		pointers[i] = rgb_data + w * 4 * i;
	png_read_image(png, pointers);
	*args->w = w;
	*args->h = h;
out:
	png_destroy_read_struct(&png, &info, 0);
	
	return rgb_data;
}
/* return -2 if file cannot be opened
 * return -1 if file data is corrupted
 * return  0 if file format is not valid
 * return  1 if file successfully loaded
 */
int read_image_file_png (const char* filename, ImageData *imagedata)
{
    int i, width, height, BPP;
    unsigned char* pixelArray = NULL;
    png_bytep* row_pointers;
    png_byte color_type;
    png_infop info_ptr;
    png_structp png_ptr;
    png_byte header[8];
    FILE *fp;


    /* open file for reading-bytes */
    fp = fopen (filename, "rb");

    if(!fp) ABORT("Read Error: file '%s' could not be opened for reading.", filename, -2)

    /* Test if file type is png */
    /* 8 bytes is the maximum size that can be checked */
    if(fread(header, 1, 8, fp) != 8
    || png_sig_cmp(header, 0, 8))
        ABORT("Read Error: file '%s' is not recognized as a PNG file.", filename, 0)


    /* initialise - prepare for parsing */
    png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if(!png_ptr)
        ABORT("Read Error: file '%s' is corrupted. png_create_read_struct failed.", filename, -1)

    info_ptr = png_create_info_struct (png_ptr);
    if(!info_ptr)
        ABORT("Read Error: file '%s' is corrupted. png_create_info_struct failed.", filename, -1)

    if(setjmp(png_jmpbuf(png_ptr)))
        ABORT("Read Error: file '%s' is corrupted. setjmp(png_jmpbuf(png_ptr)) failed.", filename, -1)

    png_init_io (png_ptr, fp);
    png_set_sig_bytes (png_ptr, 8);
    png_read_info (png_ptr, info_ptr);


    /* ensure 3-byte colour depth */
    color_type = png_get_color_type (png_ptr, info_ptr);
    if(color_type == PNG_COLOR_TYPE_GRAY ||
        color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
          png_set_gray_to_rgb (png_ptr);

    /* ensure Alpha channel present */
    png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER);

    /*png_get_bit_depth(png_ptr, info_ptr) = 8... why so? */
    height = png_get_image_height(png_ptr, info_ptr);
    width  = png_get_image_width (png_ptr, info_ptr);
    BPP    = 4;

    /* ensure BGRA and not ARGB */
    png_set_bgr(png_ptr);

    /* make libpng to handle expansion of the interlaced image */
    png_set_interlace_handling (png_ptr);

    /* reflect requested transformations */
    png_read_update_info (png_ptr, info_ptr);


    /* prepare to read file */
    if(setjmp(png_jmpbuf(png_ptr)))
        ABORT("Read Error: file '%s' is corrupted. setjmp(png_jmpbuf(png_ptr)) failed.", filename, -1)

    /* allocate memory needed to hold the image */
    pixelArray = (unsigned char*) malloc (height*width*BPP);

    row_pointers = (png_bytep*) malloc (height * sizeof(*row_pointers));

    for(i = 0; i < height; i++)
        row_pointers[i] = (png_bytep) (pixelArray + i*width*BPP);

    /* finally... read image file... */
    png_read_image(png_ptr, row_pointers);

    /* free resources */
    free(row_pointers);
    fclose(fp);


    /* success */
    imagedata->pixelArray = pixelArray;
    imagedata->height = height;
    imagedata->width = width;
    imagedata->bpp = BPP*8;
    return 1;
}
int res_create_surface_png(const char* name, gr_surface* pSurface) {
    GGLSurface* surface = NULL;
    int result = 0;
    unsigned char header[8];
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;

    FILE* fp = fopen(name, "rb");
    if (fp == NULL) {
        char resPath[256];

        snprintf(resPath, sizeof(resPath)-1, "/res/images/%s.png", name);
        resPath[sizeof(resPath)-1] = '\0';
        fp = fopen(resPath, "rb");
        if (fp == NULL)
        {
            result = -1;
            goto exit;
        }
    }

    size_t bytesRead = fread(header, 1, sizeof(header), fp);
    if (bytesRead != sizeof(header)) {
        result = -2;
        goto exit;
    }

    if (png_sig_cmp(header, 0, sizeof(header))) {
        result = -3;
        goto exit;
    }

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr) {
        result = -4;
        goto exit;
    }

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        result = -5;
        goto exit;
    }

    if (setjmp(png_jmpbuf(png_ptr))) {
        result = -6;
        goto exit;
    }

    png_set_packing(png_ptr);

    png_init_io(png_ptr, fp);
    png_set_sig_bytes(png_ptr, sizeof(header));
    png_read_info(png_ptr, info_ptr);

    size_t width = info_ptr->width;
    size_t height = info_ptr->height;
    size_t stride = 4 * width;
    size_t pixelSize = stride * height;

    int color_type = info_ptr->color_type;
    int bit_depth = info_ptr->bit_depth;
    int channels = info_ptr->channels;
    if (!(bit_depth == 8 &&
          ((channels == 3 && color_type == PNG_COLOR_TYPE_RGB) ||
           (channels == 4 && color_type == PNG_COLOR_TYPE_RGBA) ||
           (channels == 1 && color_type == PNG_COLOR_TYPE_PALETTE)))) {
        return -7;
        goto exit;
    }

    surface = malloc(sizeof(GGLSurface) + pixelSize);
    if (surface == NULL) {
        result = -8;
        goto exit;
    }
    unsigned char* pData = (unsigned char*) (surface + 1);
    surface->version = sizeof(GGLSurface);
    surface->width = width;
    surface->height = height;
    surface->stride = width; /* Yes, pixels, not bytes */
    surface->data = pData;
    surface->format = (channels == 3) ?
            GGL_PIXEL_FORMAT_RGBX_8888 : GGL_PIXEL_FORMAT_RGBA_8888;

    if (color_type == PNG_COLOR_TYPE_PALETTE) {
        png_set_palette_to_rgb(png_ptr);
    }

    int x;
    size_t y;
    if (channels == 3) {
        for (y = 0; y < height; ++y) {
            unsigned char* pRow = pData + y * stride;
            png_read_row(png_ptr, pRow, NULL);

            for(x = width - 1; x >= 0; x--) {
                int sx = x * 3;
                int dx = x * 4;
                unsigned char r = pRow[sx];
                unsigned char g = pRow[sx + 1];
                unsigned char b = pRow[sx + 2];
                unsigned char a = 0xff;
                pRow[dx    ] = r; // r
                pRow[dx + 1] = g; // g
                pRow[dx + 2] = b; // b
                pRow[dx + 3] = a;
            }
        }
    } else {
        for (y = 0; y < height; ++y) {
            unsigned char* pRow = pData + y * stride;
            png_read_row(png_ptr, pRow, NULL);
#ifdef PIXELS_BGRA
            if (channels == 4) {
              for (x = width - 1; x >= 0; x--) {
                 int dx = x * 4;
                 unsigned char r = pRow[dx];
                 pRow[dx] = pRow[dx + 2];
                 pRow[dx + 2] = r;
              }
            }
#endif
        }
    }

    *pSurface = (gr_surface) surface;

exit:
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

    if (fp != NULL) {
        fclose(fp);
    }
    if (result < 0) {
        if (surface) {
            free(surface);
        }
    }
    return result;
}
Beispiel #8
0
void* replaceBootImage(AbstractFile* imageWrapper, const unsigned int* key, const unsigned int* iv, AbstractFile* png, size_t *fileSize) {
	AbstractFile* imageFile;
	unsigned char header[8];
	InfoIBootIM* info;
	png_uint_32 i;
	png_bytepp row_pointers;
	
	uint8_t* imageBuffer;
	void* buffer;

	png->read(png, header, 8);
	if(png_sig_cmp(header, 0, 8) != 0) {
		XLOG(0, "error: not a valid png file\n");
		return NULL;
	}
	png->seek(png, 0);

	png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, pngError, pngWarn);
	if (!png_ptr) {
		return NULL;
	}

	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
	{
		png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
		return NULL;
	}

	png_infop end_info = png_create_info_struct(png_ptr);
	if (!end_info)
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
		return NULL;
	}

	if (setjmp(png_jmpbuf(png_ptr)))
	{
		XLOG(0, "error reading png\n");
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		free(buffer);
		return NULL;
	}

	png_set_read_fn(png_ptr, png, pngRead);

	png_read_info(png_ptr, info_ptr);
	
	if(info_ptr->bit_depth > 8) {
		XLOG(0, "warning: bit depth per channel is greater than 8 (%d). Attempting to strip, but image quality will be degraded.\n", info_ptr->bit_depth);
	}
	
	if(info_ptr->color_type == PNG_COLOR_TYPE_GRAY || info_ptr->color_type == PNG_COLOR_TYPE_RGB) {
		XLOG(0, "notice: attempting to add dummy transparency channel\n");
	}
	
	if(info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) {
		XLOG(0, "notice: attempting to expand palette into full rgb\n");
	}
	
	png_set_expand(png_ptr);
	png_set_strip_16(png_ptr);
	png_set_bgr(png_ptr);
	png_set_add_alpha(png_ptr, 0x0, PNG_FILLER_AFTER);
	png_set_invert_alpha(png_ptr);
	
	png_read_update_info(png_ptr, info_ptr);
	

	if(info_ptr->width > 320 || info_ptr->height > 480) {
		XLOG(0, "error: dimensions out of range, must be within 320x480, not %lux%lu\n", info_ptr->width, info_ptr->height);
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		return NULL;
	}

	if(info_ptr->bit_depth != 8) {
		XLOG(0, "error: bit depth per channel must be 8 not %d!\n", info_ptr->bit_depth);
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		return NULL;
	}

	if(info_ptr->color_type != PNG_COLOR_TYPE_GRAY_ALPHA && info_ptr->color_type != PNG_COLOR_TYPE_RGB_ALPHA) {
		XLOG(0, "error: incorrect color type, must be greyscale with alpha, or rgb with alpha\n");
		if(info_ptr->color_type == PNG_COLOR_TYPE_GRAY || info_ptr->color_type == PNG_COLOR_TYPE_RGB) {
			XLOG(0, "It appears you're missing an alpha channel. Add transparency to your image\n");
		}
		if(info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) {
			XLOG(0, "This PNG is saved with the palette color type rather than ARGB.\n");
		}
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);

		return NULL;
	}

	row_pointers = (png_bytepp) malloc(sizeof(png_bytep) * info_ptr->height);
	imageBuffer = malloc(info_ptr->height * info_ptr->rowbytes);
	for(i = 0; i < info_ptr->height; i++) {
		row_pointers[i] = imageBuffer + (info_ptr->rowbytes * i);
	}

	png_read_image(png_ptr, row_pointers);
	png_read_end(png_ptr, end_info);
	
	buffer = malloc(1);
	*fileSize = 0;

	if(key != NULL) {
		imageFile = duplicateAbstractFile2(imageWrapper, createAbstractFileFromMemoryFile((void**)&buffer, fileSize), key, iv, NULL);
	} else {	
		imageFile = duplicateAbstractFile(imageWrapper, createAbstractFileFromMemoryFile((void**)&buffer, fileSize));
	}
	info = (InfoIBootIM*) (imageFile->data);
	
	info->header.width = (uint16_t) info_ptr->width;
	info->header.height = (uint16_t) info_ptr->height;
	if(info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
		info->header.format = IBOOTIM_GREY;
	} else {
		info->header.format = IBOOTIM_ARGB;
	}
	
	imageFile->write(imageFile, imageBuffer, info_ptr->height * info_ptr->rowbytes);
	
	imageFile->close(imageFile);

	png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);

	png->close(png);
	
	free(row_pointers);

	free(imageBuffer);

	return buffer;
}
// load in the image data
IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const
{
#ifdef _IRR_COMPILE_WITH_LIBPNG_
	if (!file)
		return 0;

	video::IImage* image = 0;
	//Used to point to image rows
	u8** RowPointers = 0;

	png_byte buffer[8];
	// Read the first few bytes of the PNG file
	if( file->read(buffer, 8) != 8 )
	{
		os::Printer::log("LOAD PNG: can't read file\n", file->getFileName(), ELL_ERROR);
		return 0;
	}

	// Check if it really is a PNG file
	if( png_sig_cmp(buffer, 0, 8) )
	{
		os::Printer::log("LOAD PNG: not really a png\n", file->getFileName(), ELL_ERROR);
		return 0;
	}

	// Allocate the png read struct
	png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
		NULL, (png_error_ptr)png_cpexcept_error, NULL);
	if (!png_ptr)
	{
		os::Printer::log("LOAD PNG: Internal PNG create read struct failure\n", file->getFileName(), ELL_ERROR);
		return 0;
	}

	// Allocate the png info struct
	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
	{
		os::Printer::log("LOAD PNG: Internal PNG create info struct failure\n", file->getFileName(), ELL_ERROR);
		png_destroy_read_struct(&png_ptr, NULL, NULL);
		return 0;
	}

	// for proper error handling
	if (setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		if (RowPointers)
			delete [] RowPointers;
		return 0;
	}

	// changed by zola so we don't need to have public FILE pointers
	png_set_read_fn(png_ptr, file, user_read_data_fcn);

	png_set_sig_bytes(png_ptr, 8); // Tell png that we read the signature

	png_read_info(png_ptr, info_ptr); // Read the info section of the png file

	u32 Width;
	u32 Height;
	s32 BitDepth;
	s32 ColorType;
	{
		// Use temporary variables to avoid passing casted pointers
		png_uint_32 w,h;
		// Extract info
		png_get_IHDR(png_ptr, info_ptr,
			&w, &h,
			&BitDepth, &ColorType, NULL, NULL, NULL);
		Width=w;
		Height=h;
	}

	// Convert palette color to true color
	if (ColorType==PNG_COLOR_TYPE_PALETTE)
		png_set_palette_to_rgb(png_ptr);

	// Convert low bit colors to 8 bit colors
	if (BitDepth < 8)
	{
		if (ColorType==PNG_COLOR_TYPE_GRAY || ColorType==PNG_COLOR_TYPE_GRAY_ALPHA)
#if (PNG_LIBPNG_VER_MAJOR > 1) || (PNG_LIBPNG_VER_MINOR > 3)
			png_set_expand_gray_1_2_4_to_8(png_ptr);
#else
			png_set_gray_1_2_4_to_8(png_ptr);
#endif
		else
			png_set_packing(png_ptr);
	}
Beispiel #10
0
GLuint png_texture_load(const char * file_name, int  width, int  height)
{
    png_uint_32 temp_width, temp_height;
    int bit_depth, color_type, i;

    png_byte header[8];
    GLuint texture;

    FILE *fp = fopen(file_name, "rb");
    if (fp == 0)
    {
        perror(file_name);
        return 0;
    }

    // read the header
    fread(header, 1, 8, fp);

    if (png_sig_cmp(header, 0, 8))
    {
        fprintf(stderr, "error: %s is not a PNG.\n", file_name);
        fclose(fp);
        return 0;
    }

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr)
    {
        fprintf(stderr, "error: png_create_read_struct returned 0.\n");
        fclose(fp);
        return 0;
    }

    // create png info struct
    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        fprintf(stderr, "error: png_create_info_struct returned 0.\n");
        png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
        fclose(fp);
        return 0;
    }

    // create png info struct
    end_info = png_create_info_struct(png_ptr);
    if (!end_info)
    {
        fprintf(stderr, "error: png_create_info_struct returned 0.\n");
        png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
        fclose(fp);
        return 0;
    }

    // the code in this if statement gets called if libpng encounters an error
    if (setjmp(png_jmpbuf(png_ptr))) {
        fprintf(stderr, "error from libpng\n");
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        fclose(fp);
        return 0;
    }

    // init png reading
    png_init_io(png_ptr, fp);

    // let libpng know you already read the first 8 bytes
    png_set_sig_bytes(png_ptr, 8);

    // read all the info up to the image data
    png_read_info(png_ptr, info_ptr);

    // variables to pass to get info



    // get info about png
    png_get_IHDR(png_ptr, info_ptr, &temp_width, &temp_height, &bit_depth, &color_type, NULL, NULL, NULL);

#if 0
    if (width ) {
        width = temp_width;
    }
    if (height ) {
        height = temp_height;
    }
#endif
    // Update the png info struct.
    png_read_update_info(png_ptr, info_ptr);

    // Row size in bytes.
    rowbytes = png_get_rowbytes(png_ptr, info_ptr);

    // glTexImage2d requires rows to be 4-byte aligned
    rowbytes += 3 - ((rowbytes-1) % 4);

    // Allocate the image_data as a big block, to be given to opengl

    image_data = (png_byte*)malloc(rowbytes * temp_height * sizeof(png_byte)+15);
    if (image_data == NULL)
    {
        fprintf(stderr, "error: could not allocate memory for PNG image data\n");
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        fclose(fp);
        return 0;
    }

    // row_pointers is for pointing to image_data for reading the png with libpng
    row_pointers =  (png_bytep*)malloc(temp_height * sizeof(png_bytep));
    if (row_pointers == NULL)
    {
        fprintf(stderr, "error: could not allocate memory for PNG row pointers\n");
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        free(image_data);
        fclose(fp);
        return 0;
    }

    // set the individual row_pointers to point at the correct offsets of image_data

    for (i = 0; i < temp_height; i++)
    {
        row_pointers[temp_height - 1 - i] = image_data + i * rowbytes;
    }

    // read the png into image_data through row_pointers
    png_read_image(png_ptr, row_pointers);

    // Generate the OpenGL texture object

    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, temp_width, temp_height, 0, GL_RGB, GL_UNSIGNED_BYTE, image_data);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    // clean up
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    free(image_data);
    free(row_pointers);
    fclose(fp);
    return texture;
}
Beispiel #11
0
GLuint read_png_file(char* file_name)
{

    unsigned char header[8];    // 8 is the maximum size that can be checked

    /* open file and test for it being a png */
    FILE *fp = fopen(file_name, "rb");
    if (!fp)
        abort_("[read_png_file] File %s could not be opened for reading", file_name);

    fread(header, 1, 8, fp);
    if (png_sig_cmp(header, 0, 8))
        abort_("[read_png_file] File %s is not recognized as a PNG file", file_name);

    /* initialize stuff */
    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

    if (!png_ptr)
        abort_("[read_png_file] png_create_read_struct failed");

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
        abort_("[read_png_file] png_create_info_struct failed");


    end_info = png_create_info_struct(png_ptr);
    if (!end_info)
        abort_("[read_png_file] png_create_end_info_struct failed");


    if (setjmp(png_jmpbuf(png_ptr)))
        abort_("[read_png_file] Error during init_io");


    png_init_io(png_ptr, fp);
    png_set_sig_bytes(png_ptr, 8);

    png_read_info(png_ptr, info_ptr);

    width = png_get_image_width(png_ptr, info_ptr);
    height = png_get_image_height(png_ptr, info_ptr);
    color_type = png_get_color_type(png_ptr, info_ptr);
    bit_depth = png_get_bit_depth(png_ptr, info_ptr);

    number_of_passes = png_set_interlace_handling(png_ptr);

    png_read_update_info(png_ptr, info_ptr);

    // Row size in bytes.
    rowbytes = png_get_rowbytes(png_ptr, info_ptr);

    // glTexImage2d requires rows to be 4-byte aligned
    rowbytes += 3 - ((rowbytes-1) % 4);

    // Allocate the image_data as a big block, to be given to opengl

    image_data = (png_byte*)malloc(rowbytes * height * sizeof(png_byte)+15);
    if (image_data == NULL)
        abort_("[read_png_file] png_create_end_info_struct failed");

    if (setjmp(png_jmpbuf(png_ptr)))
        abort_("[read_png_file] Error during read_image");


    row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);

    if (bit_depth == 16)
        rowbytes = width*8;
    else
        rowbytes = width*4;

    for (y=0; y<height; y++)
        row_pointers[y] = (png_byte*) malloc(rowbytes);

    png_read_image(png_ptr, row_pointers);


    glGenTextures(1, &Texture);
    glBindTexture(GL_TEXTURE_2D, Texture);
    glTexImage2D(GL_TEXTURE_2D,0, GL_RGB, width, height, 0,
                 GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*) image_data );
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    // clean up
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    free(image_data);
    free(row_pointers);
    fclose(fp);
    return Texture;
}
Beispiel #12
0
ImageNode *LoadPNGImage(const char *fileName)
{

   static ImageNode *result;
   static FILE *fd;
   static unsigned char **rows;
   static png_structp pngData;
   static png_infop pngInfo;
   static png_infop pngEndInfo;

   unsigned char header[8];
   unsigned long rowBytes;
   int bitDepth, colorType;
   unsigned int x, y;
   png_uint_32 width;
   png_uint_32 height;

   Assert(fileName);

   result = NULL;
   fd = NULL;
   rows = NULL;
   pngData = NULL;
   pngInfo = NULL;
   pngEndInfo = NULL;

   fd = fopen(fileName, "rb");
   if(!fd) {
      return NULL;
   }

   x = fread(header, 1, sizeof(header), fd);
   if(x != sizeof(header) || png_sig_cmp(header, 0, sizeof(header))) {
      fclose(fd);
      return NULL;
   }

   pngData = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
   if(JUNLIKELY(!pngData)) {
      fclose(fd);
      Warning(_("could not create read struct for PNG image: %s"), fileName);
      return NULL;
   }

   if(JUNLIKELY(setjmp(png_jmpbuf(pngData)))) {
      png_destroy_read_struct(&pngData, &pngInfo, &pngEndInfo);
      if(fd) {
         fclose(fd);
      }
      if(rows) {
         ReleaseStack(rows);
      }
      DestroyImage(result);
      Warning(_("error reading PNG image: %s"), fileName);
      return NULL;
   }

   pngInfo = png_create_info_struct(pngData);
   if(JUNLIKELY(!pngInfo)) {
      png_destroy_read_struct(&pngData, NULL, NULL);
      fclose(fd);
      Warning(_("could not create info struct for PNG image: %s"), fileName);
      return NULL;
   }

   pngEndInfo = png_create_info_struct(pngData);
   if(JUNLIKELY(!pngEndInfo)) {
      png_destroy_read_struct(&pngData, &pngInfo, NULL);
      fclose(fd);
      Warning("could not create end info struct for PNG image: %s", fileName);
      return NULL;
   }

   png_init_io(pngData, fd);
   png_set_sig_bytes(pngData, sizeof(header));

   png_read_info(pngData, pngInfo);

   png_get_IHDR(pngData, pngInfo, &width, &height,
                &bitDepth, &colorType, NULL, NULL, NULL);
   result = CreateImage(width, height, 0);

   png_set_expand(pngData);

   if(bitDepth == 16) {
      png_set_strip_16(pngData);
   } else if(bitDepth < 8) {
      png_set_packing(pngData);
   }

   png_set_swap_alpha(pngData);
   png_set_filler(pngData, 0xFF, PNG_FILLER_BEFORE);

   if(colorType == PNG_COLOR_TYPE_GRAY
      || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) {
      png_set_gray_to_rgb(pngData);
   }

   png_read_update_info(pngData, pngInfo);

   rowBytes = png_get_rowbytes(pngData, pngInfo);
   rows = AllocateStack(result->height * sizeof(result->data));
   y = 0;
   for(x = 0; x < result->height; x++) {
      rows[x] = &result->data[y];
      y += rowBytes;
   }

   png_read_image(pngData, rows);

   png_read_end(pngData, pngInfo);
   png_destroy_read_struct(&pngData, &pngInfo, &pngEndInfo);

   fclose(fd);

   ReleaseStack(rows);
   rows = NULL;

   return result;

}
static void read_png_file_low(const char* file_name, png_image_data_t *png_image_data)
{
    png_structp png_ptr;
    int number_of_passes;
	char header[8];	// 8 is the maximum size that can be checked
    int y;

	/* open file and test for it being a png */
	FILE *fp = fopen(file_name, "rb");
	if (!fp)
		abort_("[read_png_file] File %s could not be opened for reading", file_name);
	fread(header, 1, 8, fp);
	if (png_sig_cmp(header, 0, 8))
		abort_("[read_png_file] File %s is not recognized as a PNG file", file_name);


	/* initialize stuff */
	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	
	if (!png_ptr)
		abort_("[read_png_file] png_create_read_struct failed");

	png_image_data->info_ptr = png_create_info_struct(png_ptr);
	if (!png_image_data->info_ptr)
		abort_("[read_png_file] png_create_info_struct failed");

	if (setjmp(png_jmpbuf(png_ptr)))
		abort_("[read_png_file] Error during init_io");
	png_init_io(png_ptr, fp);

	png_set_sig_bytes(png_ptr, 8); /* 8 == sig_read ? */

	png_read_info(png_ptr, png_image_data->info_ptr);

    /* set transformations */
/*
	if ((png_image_data->info_ptr->color_type & PNG_COLOR_TYPE_RGB) == 0)
        transforms |= PNG_TRANSFORM_BGR;
*/
   if (png_get_valid(png_ptr, png_image_data->info_ptr, PNG_INFO_sBIT))
   {
      png_color_8p sig_bit;

      png_get_sBIT(png_ptr, png_image_data->info_ptr, &sig_bit);
      printf("sig_bit: %d\n", sig_bit);
      png_set_shift(png_ptr, sig_bit);
   }

    /* TODO DFG: is this needed? */
	number_of_passes = png_set_interlace_handling(png_ptr);
	png_read_update_info(png_ptr, png_image_data->info_ptr);





	/* read file */
	if (setjmp(png_jmpbuf(png_ptr)))
		abort_("[read_png_file] Error during read_image");

#if 1
	png_image_data->row_pointers = (png_bytep*) qemu_malloc(sizeof(png_bytep) * png_image_data->info_ptr->height);
	for (y=0; y < png_image_data->info_ptr->height; y++)
		png_image_data->row_pointers[y] = (png_byte*) qemu_malloc(png_image_data->info_ptr->rowbytes);

	png_read_image(png_ptr, png_image_data->row_pointers);
#endif
    /* DFG TODO: Cleanup */

/*    png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); */

    fclose(fp);
}
static void read_png_file(const char* file_name, png_image_data_t *png_image_data, int max_width, int max_height)
{
    png_structp png_ptr;
    png_infop info_ptr;
    png_bytep *row_pointers;
	char header[8];	// 8 is the maximum size that can be checked
    int y;
    char* dest;

	/* open file and test for it being a png */
	FILE *fp = fopen(file_name, "rb");
	if (!fp)
		abort_("[read_png_file] File %s could not be opened for reading", file_name);
	fread(header, 1, 8, fp);
	if (png_sig_cmp(header, 0, 8))
		abort_("[read_png_file] File %s is not recognized as a PNG file", file_name);


	/* initialize stuff */
	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	
	if (!png_ptr)
		abort_("[read_png_file] png_create_read_struct failed");

    if (max_width > 0 && max_height > 0)
        png_set_user_limits(png_ptr, max_width, max_height);

	info_ptr = png_create_info_struct(png_ptr);

	if (setjmp(png_jmpbuf(png_ptr)))
		abort_("[read_png_file] Error during init_io");
	png_init_io(png_ptr, fp);

	if (setjmp(png_jmpbuf(png_ptr)))
		abort_("[read_png_file] Error during init_io");
   png_set_sig_bytes(png_ptr, sizeof(header));

	if (setjmp(png_jmpbuf(png_ptr)))
		abort_("[read_png_file] Error during init_io");
   png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_ALPHA, png_voidp_NULL);

	if (setjmp(png_jmpbuf(png_ptr)))
		abort_("[read_png_file] Error during init_io");

    row_pointers = png_get_rows(png_ptr, info_ptr);

    png_image_data->height = png_get_image_height(png_ptr, info_ptr);
    png_image_data->width = png_get_image_width(png_ptr, info_ptr);

    png_image_data->image4c = (void*)qemu_malloc(png_image_data->width * png_image_data->height * 4);

    dest = (char*)png_image_data->image4c;

    /* transform this from 3 channels to a (fake for now) 4 channels */
	for (y=0; y < png_image_data->height; y++) {
        char* src = row_pointers[y];
        int x;
        for (x = 0; x < png_image_data->width; x++) {
            *dest = *src; dest++, src++;
            *dest = *src; dest++, src++;
            *dest = *src; dest++, src++;
            *dest = 0; dest++; /* alpha channel ignored */ 
        }
    }

    png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);

    fclose(fp);
}
Beispiel #15
0
/* Read the information before the actual image data.  This has been
 * changed in v0.90 to allow reading a file that already has the magic
 * bytes read from the stream.  You can tell libpng how many bytes have
 * been read from the beginning of the stream (up to the maximum of 8)
 * via png_set_sig_bytes(), and we will only check the remaining bytes
 * here.  The application can then have access to the signature bytes we
 * read if it is determined that this isn't a valid PNG file.
 */
void PNGAPI
png_read_info(png_structp png_ptr, png_infop info_ptr)
{
   png_debug(1, "in png_read_info\n");
   /* save jump buffer and error functions */
   /* If we haven't checked all of the PNG signature bytes, do so now. */
   if (png_ptr->sig_bytes < 8)
   {
      png_size_t num_checked = png_ptr->sig_bytes,
                 num_to_check = 8 - num_checked;

      png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check);
      png_ptr->sig_bytes = 8;

      if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
      {
         if (num_checked < 4 &&
             png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
            png_error(png_ptr, "Not a PNG file");
         else
            png_error(png_ptr, "PNG file corrupted by ASCII conversion");
      }
      if (num_checked < 3)
         png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
   }

   for(;;)
   {
#ifdef PNG_USE_LOCAL_ARRAYS
      PNG_IHDR;
      PNG_IDAT;
      PNG_IEND;
      PNG_PLTE;
#if defined(PNG_READ_bKGD_SUPPORTED)
      PNG_bKGD;
#endif
#if defined(PNG_READ_cHRM_SUPPORTED)
      PNG_cHRM;
#endif
#if defined(PNG_READ_gAMA_SUPPORTED)
      PNG_gAMA;
#endif
#if defined(PNG_READ_hIST_SUPPORTED)
      PNG_hIST;
#endif
#if defined(PNG_READ_iCCP_SUPPORTED)
      PNG_iCCP;
#endif
#if defined(PNG_READ_iTXt_SUPPORTED)
      PNG_iTXt;
#endif
#if defined(PNG_READ_oFFs_SUPPORTED)
      PNG_oFFs;
#endif
#if defined(PNG_READ_pCAL_SUPPORTED)
      PNG_pCAL;
#endif
#if defined(PNG_READ_pHYs_SUPPORTED)
      PNG_pHYs;
#endif
#if defined(PNG_READ_sBIT_SUPPORTED)
      PNG_sBIT;
#endif
#if defined(PNG_READ_sCAL_SUPPORTED)
      PNG_sCAL;
#endif
#if defined(PNG_READ_sPLT_SUPPORTED)
      PNG_sPLT;
#endif
#if defined(PNG_READ_sRGB_SUPPORTED)
      PNG_sRGB;
#endif
#if defined(PNG_READ_tEXt_SUPPORTED)
      PNG_tEXt;
#endif
#if defined(PNG_READ_tIME_SUPPORTED)
      PNG_tIME;
#endif
#if defined(PNG_READ_tRNS_SUPPORTED)
      PNG_tRNS;
#endif
#if defined(PNG_READ_zTXt_SUPPORTED)
      PNG_zTXt;
#endif
#endif /* PNG_GLOBAL_ARRAYS */
      png_byte chunk_length[4];
      png_uint_32 length;

      png_read_data(png_ptr, chunk_length, 4);
      length = png_get_uint_32(chunk_length);

      png_reset_crc(png_ptr);
      png_crc_read(png_ptr, png_ptr->chunk_name, 4);

      png_debug2(0, "Reading %s chunk, length=%lu.\n", png_ptr->chunk_name,
         length);

      /* This should be a binary subdivision search or a hash for
       * matching the chunk name rather than a linear search.
       */
      if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
         png_handle_IHDR(png_ptr, info_ptr, length);
      else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
         png_handle_IEND(png_ptr, info_ptr, length);
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
      else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name))
      {
         if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
            png_ptr->mode |= PNG_HAVE_IDAT;
         png_handle_unknown(png_ptr, info_ptr, length);
         if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
            png_ptr->mode |= PNG_HAVE_PLTE;
         else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
         {
            if (!(png_ptr->mode & PNG_HAVE_IHDR))
               png_error(png_ptr, "Missing IHDR before IDAT");
            else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
                     !(png_ptr->mode & PNG_HAVE_PLTE))
               png_error(png_ptr, "Missing PLTE before IDAT");
            break;
         }
      }
#endif
      else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
         png_handle_PLTE(png_ptr, info_ptr, length);
      else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
      {
         if (!(png_ptr->mode & PNG_HAVE_IHDR))
            png_error(png_ptr, "Missing IHDR before IDAT");
         else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
                  !(png_ptr->mode & PNG_HAVE_PLTE))
            png_error(png_ptr, "Missing PLTE before IDAT");

         png_ptr->idat_size = length;
         png_ptr->mode |= PNG_HAVE_IDAT;
         break;
      }
#if defined(PNG_READ_bKGD_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
         png_handle_bKGD(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_cHRM_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
         png_handle_cHRM(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_gAMA_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
         png_handle_gAMA(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_hIST_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
         png_handle_hIST(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_oFFs_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
         png_handle_oFFs(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_pCAL_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
         png_handle_pCAL(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_sCAL_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4))
         png_handle_sCAL(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_pHYs_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
         png_handle_pHYs(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_sBIT_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
         png_handle_sBIT(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_sRGB_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4))
         png_handle_sRGB(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_iCCP_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4))
         png_handle_iCCP(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_sPLT_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4))
         png_handle_sPLT(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_tEXt_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
         png_handle_tEXt(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_tIME_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
         png_handle_tIME(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_tRNS_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
         png_handle_tRNS(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_zTXt_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
         png_handle_zTXt(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_iTXt_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4))
         png_handle_iTXt(png_ptr, info_ptr, length);
#endif
      else
         png_handle_unknown(png_ptr, info_ptr, length);
   }
}
Beispiel #16
0
static int
lload(lua_State *L) {
    int top = lua_gettop(L);
    FILE *fp; 
    struct png_source source;
    if (top == 1) {
        const char *filename = luaL_checkstring(L,1);
        fp = fopen(filename, "rb");
        if (fp == NULL) {
            return luaL_error(L, strerror(errno));
        }
        unsigned char header[PNGSIGSIZE];
        if (fread(header, 1, PNGSIGSIZE, fp) != PNGSIGSIZE) {
            return luaL_error(L, "png invalid");
        }
        if (png_sig_cmp(header, 0, PNGSIGSIZE)) {
            return luaL_error(L, "png sig invalid");
        }
        fseek(fp, 0, SEEK_SET);
    } else if (top == 2) {
        luaL_checktype(L,1,LUA_TLIGHTUSERDATA);
        void *data = lua_touserdata(L,1);
        size_t size = luaL_checkinteger(L,2);
        if (size < PNGSIGSIZE) {
            return luaL_error(L, "png invalid");
        }
        if (png_sig_cmp(data, 0, PNGSIGSIZE)) {
            return luaL_error(L, "png sig invalid");
        }
        source.data = data;
        source.size = size;
        source.offset = 0;
    } else {
        return luaL_error(L, "invalid argument number");
    }
    
    png_structp png_ptr;
    png_infop info_ptr;
    png_uint_32 width, height;
    int bit_depth, color_type, interlace_type;
    int step;//, type;

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (png_ptr == NULL) {
        return 0;
    }

    info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL) {
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        return 0;
    }

    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        return 0;
    }

    if (top == 1)
        png_init_io(png_ptr, fp);
    else
        png_set_read_fn(png_ptr, (void *)&source, png_read_cb);

    //png_set_sig_bytes(png_ptr, PNGSIGSIZE);

    png_read_info(png_ptr, info_ptr);

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

    if (color_type == PNG_COLOR_TYPE_PALETTE)
        png_set_palette_to_rgb(png_ptr);

    if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
        bit_depth = 8;
        png_set_expand_gray_1_2_4_to_8(png_ptr);
    }

    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) != 0)
        png_set_tRNS_to_alpha(png_ptr);

    if (bit_depth == 16)
        png_set_strip_16(png_ptr);

    if (bit_depth < 8)
        png_set_packing(png_ptr);

    png_read_update_info(png_ptr, info_ptr);
    bit_depth = png_get_bit_depth(png_ptr, info_ptr);
    color_type = png_get_color_type(png_ptr, info_ptr);
    switch (color_type) {
    case PNG_COLOR_TYPE_GRAY:
        // type = TEXTURE_DEPTH;
        step = 1;
        break;
    case PNG_COLOR_TYPE_RGB:
        //type = TEXTURE_RGB;
        step = 3;
        break;
    case PNG_COLOR_TYPE_RGB_ALPHA:
        //type = TEXTURE_RGBA;
        step = 4;
        break;
    default:
        return luaL_error(L, "png color type %d not support", color_type);
    } 

    png_bytep *row_pointers = (png_bytep *)malloc(height * sizeof(png_bytep));

    png_size_t rowbytes = png_get_rowbytes(png_ptr,info_ptr);

    size_t bytes = rowbytes * height;
    uint8_t *buffer = (uint8_t *)malloc(bytes);
    int i;
    for (i=0; i<height; ++i) {
        row_pointers[i] = buffer + i*rowbytes;
    }
    
    png_read_image(png_ptr, row_pointers);

    png_read_end(png_ptr, info_ptr);

    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

    free(row_pointers);

    switch (color_type) {
    case PNG_COLOR_TYPE_GRAY:
        lua_pushliteral(L,"GRAY");
        break;
    case PNG_COLOR_TYPE_RGB:
        lua_pushliteral(L,"RGB8");
        break;
    case PNG_COLOR_TYPE_RGBA:
        lua_pushliteral(L,"RGBA8");
        break;
    }
    lua_pushinteger(L,width);
    lua_pushinteger(L,height);
    int n = width * height * step;
    lua_createtable(L,n,0);
    for (i=0; i<n; ++i) {
        lua_pushinteger(L, buffer[i]);
        lua_rawseti(L, -2, i+1);
    }

    free(buffer);
    return 4;
}
Beispiel #17
0
void png_reader::init()
{
    FILE *fp=fopen(fileName_.c_str(),"rb");
    if (!fp) throw image_reader_exception("cannot open image file "+fileName_);
    png_byte header[8];
    memset(header,0,8);
    if ( fread(header,1,8,fp) != 8)
    {
        fclose(fp);
        throw image_reader_exception("Could not read " + fileName_);
    }
    int is_png=!png_sig_cmp(header,0,8);
    if (!is_png)
    {
        fclose(fp);
        throw image_reader_exception(fileName_ + " is not a png file");
    }
    png_structp png_ptr = png_create_read_struct
        (PNG_LIBPNG_VER_STRING,0,0,0);

    if (!png_ptr)
    {
        fclose(fp);
        throw image_reader_exception("failed to allocate png_ptr");
    }

    // catch errors in a custom way to avoid the need for setjmp
    png_set_error_fn(png_ptr, png_get_error_ptr(png_ptr), user_error_fn, user_warning_fn);

    png_infop info_ptr;
    try
    {
        info_ptr = png_create_info_struct(png_ptr);
        if (!info_ptr)
        {
            png_destroy_read_struct(&png_ptr,0,0);
            fclose(fp);
            throw image_reader_exception("failed to create info_ptr");
        }
    }
    catch (std::exception const& ex)
    {
        png_destroy_read_struct(&png_ptr,0,0);
        fclose(fp);
        throw;
    }

    png_set_read_fn(png_ptr, (png_voidp)fp, png_read_data);

    png_set_sig_bytes(png_ptr,8);
    png_read_info(png_ptr, info_ptr);

    png_uint_32  width, height;
    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth_, &color_type_,0,0,0);

    width_=width;
    height_=height;

    MAPNIK_LOG_DEBUG(png_reader) << "png_reader: bit_depth=" << bit_depth_ << ",color_type=" << color_type_;

    png_destroy_read_struct(&png_ptr,&info_ptr,0);
    fclose(fp);
}
GLuint loadTextureFromPNG(const char* filename, int &width, int &height) {
  file = zip_fopen(APKArchive, filename, 0);
  if (!file) {
    LOGE("Error opening %s from APK", filename);
    return TEXTURE_LOAD_ERROR;
  }

  //header for testing if it is a png
  png_byte header[8];

  //read the header
  zip_fread(file, header, 8);

  //test if png
  int is_png = !png_sig_cmp(header, 0, 8);
  if (!is_png) {
    zip_fclose(file);
    LOGE("Not a png file : %s", filename);
    return TEXTURE_LOAD_ERROR;
  }

  //create png struct
  png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
      NULL, NULL);
  if (!png_ptr) {
    zip_fclose(file);
    LOGE("Unable to create png struct : %s", filename);
    return (TEXTURE_LOAD_ERROR);
  }

  //create png info struct
  png_infop info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr) {
    png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
    LOGE("Unable to create png info : %s", filename);
    zip_fclose(file);
    return (TEXTURE_LOAD_ERROR);
  }

  //create png info struct
  png_infop end_info = png_create_info_struct(png_ptr);
  if (!end_info) {
    png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
    LOGE("Unable to create png end info : %s", filename);
    zip_fclose(file);
    return (TEXTURE_LOAD_ERROR);
  }

  //png error stuff, not sure libpng man suggests this.
  if (setjmp(png_jmpbuf(png_ptr))) {
    zip_fclose(file);
    LOGE("Error during setjmp : %s", filename);
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    return (TEXTURE_LOAD_ERROR);
  }

  //init png reading
  //png_init_io(png_ptr, fp);
  png_set_read_fn(png_ptr, NULL, png_zip_read);

  //let libpng know you already read the first 8 bytes
  png_set_sig_bytes(png_ptr, 8);

  // read all the info up to the image data
  png_read_info(png_ptr, info_ptr);

  //variables to pass to get info
  int bit_depth, color_type;
  png_uint_32 twidth, theight;

  // get info about png
  png_get_IHDR(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type,
      NULL, NULL, NULL);

  //update width and height based on png info
  width = twidth;
  height = theight;

  // Update the png info struct.
  png_read_update_info(png_ptr, info_ptr);

  // Row size in bytes.
  int rowbytes = png_get_rowbytes(png_ptr, info_ptr);

  // Allocate the image_data as a big block, to be given to opengl
  png_byte *image_data = new png_byte[rowbytes * height];
  if (!image_data) {
    //clean up memory and close stuff
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    LOGE("Unable to allocate image_data while loading %s ", filename);
    zip_fclose(file);
    return TEXTURE_LOAD_ERROR;
  }

  //row_pointers is for pointing to image_data for reading the png with libpng
  png_bytep *row_pointers = new png_bytep[height];
  if (!row_pointers) {
    //clean up memory and close stuff
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    delete[] image_data;
    LOGE("Unable to allocate row_pointer while loading %s ", filename);
    zip_fclose(file);
    return TEXTURE_LOAD_ERROR;
  }
  // set the individual row_pointers to point at the correct offsets of image_data
  for (int i = 0; i < height; ++i)
    row_pointers[height - 1 - i] = image_data + i * rowbytes;

  //read the png into image_data through row_pointers
  png_read_image(png_ptr, row_pointers);

  //Now generate the OpenGL texture object
  GLuint texture;
  glGenTextures(1, &texture);
  glBindTexture(GL_TEXTURE_2D, texture);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
      GL_UNSIGNED_BYTE, (GLvoid*) image_data);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

  //clean up memory and close stuff
  png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
  delete[] image_data;
  delete[] row_pointers;
  zip_fclose(file);

  return texture;
}
Beispiel #19
0
static void
read_png(const char* filename, int& width, int& height, png_bytep*& rowPtrs,
	png_structp& pngPtr, png_infop& infoPtr)
{
	char header[8];
	FILE* input = fopen(filename, "rb");
	if (!input)
		error("[read_png] File %s could not be opened for reading", filename);

	AutoFileCloser _(input);

	fread(header, 1, 8, input);
	if (png_sig_cmp((png_byte *)header, 0, 8 ))
		error("[read_png] File %s is not recognized as a PNG file", filename);

	pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
		NULL, NULL, NULL);
	if (!pngPtr)
		error("[read_png] png_create_read_struct failed");

	infoPtr = png_create_info_struct(pngPtr);
	if (!infoPtr)
		error("[read_png] png_create_info_struct failed");

// TODO: I don't know which version of libpng introduced this feature:
#if PNG_LIBPNG_VER > 10005
	if (setjmp(png_jmpbuf(pngPtr)))
		error("[read_png] Error during init_io");
#endif

	png_init_io(pngPtr, input);
	png_set_sig_bytes(pngPtr, 8);

	// make sure we automatically get RGB data with 8 bits per channel
	// also make sure the alpha channel is stripped, in the end, we
	// expect 24 bits BGR data
	png_set_expand(pngPtr);
	png_set_expand_gray_1_2_4_to_8(pngPtr);
	png_set_palette_to_rgb(pngPtr);
	png_set_gray_to_rgb(pngPtr);
	png_set_strip_alpha(pngPtr);
	png_set_bgr(pngPtr);

	png_read_info(pngPtr, infoPtr);
	width = infoPtr->width;
	height = infoPtr->height;
	if (infoPtr->bit_depth != 8)
		error("[read_png] File %s has wrong bit depth\n", filename);
	if ((int)infoPtr->rowbytes < width * 3) {
		error("[read_png] File %s has wrong color type (RGB required)\n",
			filename);
	}


	png_set_interlace_handling(pngPtr);
	png_read_update_info(pngPtr, infoPtr);

#if PNG_LIBPNG_VER > 10005
	if (setjmp(png_jmpbuf(pngPtr)))
		error("[read_png] Error during read_image");
#endif

	rowPtrs = (png_bytep*)malloc(sizeof(png_bytep) * height);
	for (int y = 0; y < height; y++)
		rowPtrs[y] = (png_byte*)malloc(infoPtr->rowbytes);

	png_read_image(pngPtr, rowPtrs);
}
Beispiel #20
0
    PingPNG												(const std::string& aPath) :
        File(0),
        PngPtr(0),
        InfoPtr(0),
        RowPointers(0),
        Width(0),
        Height(0),
        Valid(false)
    {
        File = fopen(aPath.c_str(), "rb");

        if(File)
        {
            fread(Header, 1, 8, File);
            if(!png_sig_cmp(Header, 0, 8))
            {
                PngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
                if(PngPtr)
                {
                    InfoPtr = png_create_info_struct(PngPtr);
                    if(InfoPtr)
                    {
                        if(setjmp(png_jmpbuf(PngPtr)))
                        {
                            es_log->AppendLine("PNG Reader: Error during init_io. [File: %s]", aPath.c_str());
                            return;
                        }

                        png_init_io(PngPtr, File);
                        png_set_sig_bytes(PngPtr, 8);


                        if(setjmp(png_jmpbuf(PngPtr)))
                        {
                            es_log->AppendLine("PNG Reader: Error during read_png. [File: %s]", aPath.c_str());
                            return;
                        }
                        png_read_png(PngPtr, InfoPtr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_SWAP_ALPHA, 0);

                        RowPointers = png_get_rows(PngPtr, InfoPtr);
                        if(!RowPointers)
                        {
                            es_log->AppendLine("PNG Reader: Failed to get pixels. [File: %s]", aPath.c_str());
                            return;
                        }

                        Width = png_get_image_width(PngPtr, InfoPtr);
                        Height = png_get_image_height(PngPtr, InfoPtr);
                        Valid = true;
                        return;
                    }
                    else
                    {
                        es_log->AppendLine("PNG Reader: png_create_info_struct failed. [File: %s]", aPath.c_str());
                        return;
                    }
                }
                else
                {
                    es_log->AppendLine("PNG Reader: png_create_read_struct failed. [File: %s]", aPath.c_str());
                    return;
                }
            }
            else
            {
                es_log->AppendLine("PNG Reader: File not recognized as a PNG file. [File: %s]", aPath.c_str());
                return;
            }
        }
        else
        {
            es_log->AppendLine("PNG Reader: File could not be opened for reading. [File: %s]", aPath.c_str());
            return;
        }
    }
Beispiel #21
0
int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight)
{
    uch sig[8];


    /* first do a quick check that the file really is a PNG image; could
     * have used slightly more general png_sig_cmp() function instead */

    fread(sig, 1, 8, infile);
    if (png_sig_cmp(sig, 0, 8))
        return 1;   /* bad signature */


    /* could pass pointers to user-defined error handlers instead of NULLs: */

    png_ptr = png_create_read_struct(png_get_libpng_ver(NULL), NULL, NULL,
        NULL);
    if (!png_ptr)
        return 4;   /* out of memory */

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        return 4;   /* out of memory */
    }


    /* we could create a second info struct here (end_info), but it's only
     * useful if we want to keep pre- and post-IDAT chunk info separated
     * (mainly for PNG-aware image editors and converters) */


    /* setjmp() must be called in every function that calls a PNG-reading
     * libpng function */

    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        return 2;
    }


    png_init_io(png_ptr, infile);
    png_set_sig_bytes(png_ptr, 8);  /* we already read the 8 signature bytes */

    png_read_info(png_ptr, info_ptr);  /* read all PNG info up to image data */


    /* alternatively, could make separate calls to png_get_image_width(),
     * etc., but want bit_depth and color_type for later [don't care about
     * compression_type and filter_type => NULLs] */

    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
      NULL, NULL, NULL);
    *pWidth = width;
    *pHeight = height;


    /* OK, that's all we need for now; return happy */

    return 0;
}
Beispiel #22
0
    void png_loader::read_image( const char* filename )
    {
        ld_.reset(new LibpngData);
        if ( filename == NULL )
        {
            throw image_load_error("png_loader: invalid filename, it is NULL");
        }
        FILE *fp = fopen( filename, "rb" );
        if ( !fp )
        {
            throw image_load_error(std::string("png_loader: unable to open file ") + filename);
        }
        png_byte sig[8];
        if (fread( sig, 1, 8, fp ) != 8)
        {
            fclose( fp );
            throw image_load_error(std::string("png_loader: error reading file ") + filename);
        }
        if ( png_sig_cmp( sig, 0, 8 ) != 0 )
        {
            fclose( fp );
            throw image_load_error(std::string("png_loader: format error in file ") + filename);
        }
        ld_->png_ptr_ = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, &png_loader_user_error_fn_silent, &png_loader_user_warning_fn_silent );
        if ( ld_->png_ptr_ == NULL )
        {
            fclose( fp );
            throw image_load_error(std::string("png_loader: parse error in file ") + filename);
        }
        ld_->info_ptr_ = png_create_info_struct( ld_->png_ptr_ );
        if ( ld_->info_ptr_ == NULL )
        {
            fclose( fp );
            png_destroy_read_struct( &( ld_->png_ptr_ ), ( png_infopp )NULL, ( png_infopp )NULL );
            throw image_load_error(std::string("png_loader: parse error in file ") + filename);
        }
        ld_->end_info_ = png_create_info_struct( ld_->png_ptr_ );
        if ( ld_->end_info_ == NULL )
        {
            fclose( fp );
            png_destroy_read_struct( &( ld_->png_ptr_ ), &( ld_->info_ptr_ ), ( png_infopp )NULL );
            throw image_load_error(std::string("png_loader: parse error in file ") + filename);
        }

        if (setjmp(png_jmpbuf(ld_->png_ptr_)))
        {
            // If we get here, we had a problem writing the file 
            fclose(fp);
            png_destroy_read_struct( &( ld_->png_ptr_ ), &( ld_->info_ptr_ ), &( ld_->end_info_ ) );
            throw image_load_error(std::string("png_loader: parse error in file ") + filename);
        }

        png_set_palette_to_rgb(ld_->png_ptr_);

        png_init_io( ld_->png_ptr_, fp );
        png_set_sig_bytes( ld_->png_ptr_, 8 );
        // flags force one byte per channel output
        byte_orderer bo;
        int png_transforms = PNG_TRANSFORM_PACKING;
        if (bo.host_is_little_endian())
            png_transforms |= PNG_TRANSFORM_SWAP_ENDIAN;
        png_read_png( ld_->png_ptr_, ld_->info_ptr_, png_transforms, NULL );
        height_ = png_get_image_height( ld_->png_ptr_, ld_->info_ptr_ );
        width_ = png_get_image_width( ld_->png_ptr_, ld_->info_ptr_ );
        bit_depth_ = png_get_bit_depth( ld_->png_ptr_, ld_->info_ptr_ );
        color_type_ = png_get_color_type( ld_->png_ptr_, ld_-> info_ptr_ );


        if (color_type_ != PNG_COLOR_TYPE_GRAY && 
            color_type_ != PNG_COLOR_TYPE_RGB && 
            color_type_ != PNG_COLOR_TYPE_RGB_ALPHA &&
            color_type_ != PNG_COLOR_TYPE_GRAY_ALPHA)
        {
            fclose( fp );
            png_destroy_read_struct( &( ld_->png_ptr_ ), &( ld_->info_ptr_ ), &( ld_->end_info_ ) );
            throw image_load_error(std::string("png_loader: unsupported color type in file ") + filename);
        }

        if (bit_depth_ != 8 && bit_depth_ != 16)
        {
            fclose( fp );
            png_destroy_read_struct( &( ld_->png_ptr_ ), &( ld_->info_ptr_ ), &( ld_->end_info_ ) );
            throw image_load_error("png_loader: unsupported bit depth of " + cast_to_string(bit_depth_) + " in file " + std::string(filename));
        }

        ld_->row_pointers_ = png_get_rows( ld_->png_ptr_, ld_->info_ptr_ );

        fclose( fp );
        if ( ld_->row_pointers_ == NULL )
        {
            png_destroy_read_struct( &( ld_->png_ptr_ ), &( ld_->info_ptr_ ), &( ld_->end_info_ ) );
            throw image_load_error(std::string("png_loader: parse error in file ") + filename);
        }
    }
Beispiel #23
0
/** 从本地磁盘中加载图像
@Param 图像文件的路径
*/
F3DImage* F3DPNGCodec::Load( const char* filename )
{
    F3DImage* image;

    // 打开指定的文件
	FVFile file;
	if( !file.Open(filename,FVFile::VFILE_OPENEXIST) )
    {
		FLOG_WARNINGF( "F3DPNGCodec::Load, Open the image file (%s) failed!",filename );
		return NULL;
    }

    FBYTE** row_pointers;
    png_byte buffer[8];

    // 判断是否为一个正确的PNG文件
    if( file.Read(buffer,8) != 8 || !png_sig_cmp(buffer,0,8) )
    {
		FLOG_WARNINGF( "F3DPNGCodec::Load, Invalid PNG format! (%s)",filename );
        return NULL;
    }

    // 创建一个PNG读取对象
    png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING,NULL,NULL,NULL );

    // 创建一个PNG信息结构体
    png_infop info_ptr = png_create_info_struct( png_ptr );

    if( setjmp(png_jmpbuf(png_ptr)) )
    {
        png_destroy_read_struct( &png_ptr,&info_ptr,NULL );
        if( row_pointers ) delete[] row_pointers;

		FLOG_ERROR("F3DPNGCodec::Load, An error occurs when reading...");
		return NULL;
    }

    // 设置读取数据的回调函数
    png_set_read_fn( png_ptr,&file,PNGReadFunc );

    // 告诉PNG我们已经读取过文件标识
    png_set_sig_bytes( png_ptr,8 );

    // 读取PNG文件的信息
    png_read_info( png_ptr,info_ptr );

    png_uint_32 width,height;
    int bitDepth,colorType;
    png_get_IHDR( png_ptr,info_ptr,&width,&height,&bitDepth,&colorType,NULL,NULL,NULL );

    // 如果是调色板图像则将其转换为真彩色
    if( colorType == PNG_COLOR_TYPE_PALETTE )
        png_set_palette_to_rgb( png_ptr );

    if( bitDepth < 8 )
    {
        if ( colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA )
            png_set_gray_1_2_4_to_8( png_ptr );
        else
            png_set_packing( png_ptr );
    }

    if( png_get_valid(png_ptr,info_ptr,PNG_INFO_tRNS) )
        png_set_tRNS_to_alpha( png_ptr );

    if( bitDepth == 16 )
		png_set_strip_16( png_ptr );

    // 将灰色转换为真彩色
    if( colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA )
        png_set_gray_to_rgb( png_ptr );

    // 更新信息的改变
    png_read_update_info( png_ptr,info_ptr );

    // 将RGBA格式转换为BGRA
    if( colorType == PNG_COLOR_TYPE_RGB_ALPHA )
        png_set_bgr( png_ptr );

    png_get_IHDR( png_ptr,info_ptr,&width,&height,&bitDepth,&colorType,NULL,NULL,NULL );

    // 创建图像对象
    if( colorType == PNG_COLOR_TYPE_RGB_ALPHA )
        image = new F3DImage( width,height,PFT_A8R8G8B8 );
    else
        image = new F3DImage( width,height,PFT_R8G8B8 );

    row_pointers = new png_bytep[height];
    FBYTE* imageData = image->GetImageData();
    for( size_t i=0;i<height;i++ )
    {
        row_pointers[i] = imageData;
        imageData += F3D_PixelSize(image->GetPixelFormat()) * image->GetWidth();
    }

    if( setjmp(png_jmpbuf(png_ptr)) )
    {
        png_destroy_read_struct( &png_ptr,&info_ptr,NULL );
        delete image;
        delete[] row_pointers;

        FLOG_ERROR("F3DPNGCodec::Load, An error occurs when reading...");
		return NULL;
    }

    // 读取像素数据
    png_read_image( png_ptr,row_pointers );
    png_read_end( png_ptr,NULL );

    png_destroy_read_struct( &png_ptr,&info_ptr,NULL );
    delete[] row_pointers;
	file.Close();

    return image;
}
Beispiel #24
0
static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
	png_structp png_ptr = NULL;
	png_infop info_ptr = NULL;
	png_uint_32 width, height;
	int color_type;
	int bit_depth;
	int pixel_depth = 0;	// pixel_depth = bit_depth * channels

	FIBITMAP *dib = NULL;
	png_bytepp row_pointers = NULL;

    fi_ioStructure fio;
    fio.s_handle = handle;
	fio.s_io = io;
    
	if (handle) {
		BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;

		try {		
			// check to see if the file is in fact a PNG file

			BYTE png_check[PNG_BYTES_TO_CHECK];

			io->read_proc(png_check, PNG_BYTES_TO_CHECK, 1, handle);

			if (png_sig_cmp(png_check, (png_size_t)0, PNG_BYTES_TO_CHECK) != 0) {
				return NULL;	// Bad signature
			}
			
			// create the chunk manage structure

			png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, error_handler, warning_handler);

			if (!png_ptr) {
				return NULL;			
			}

			// create the info structure

		    info_ptr = png_create_info_struct(png_ptr);

			if (!info_ptr) {
				png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
				return NULL;
			}

			// init the IO

			png_set_read_fn(png_ptr, &fio, _ReadProc);

            if (setjmp(png_jmpbuf(png_ptr))) {
				png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
				return NULL;
			}

			// because we have already read the signature...

			png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK);

			// read the IHDR chunk

			png_read_info(png_ptr, info_ptr);
			png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);

			// configure the decoder

			FREE_IMAGE_TYPE image_type = FIT_BITMAP;

			if(!ConfigureDecoder(png_ptr, info_ptr, flags, &image_type)) {
				throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
			}

			// update image info

			color_type = png_get_color_type(png_ptr, info_ptr);
			bit_depth = png_get_bit_depth(png_ptr, info_ptr);
			pixel_depth = bit_depth * png_get_channels(png_ptr, info_ptr);

			// create a dib and write the bitmap header
			// set up the dib palette, if needed

			switch (color_type) {
				case PNG_COLOR_TYPE_RGB:
				case PNG_COLOR_TYPE_RGB_ALPHA:
					dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
					break;

				case PNG_COLOR_TYPE_PALETTE:
					dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
					if(dib) {
						png_colorp png_palette = NULL;
						int palette_entries = 0;

						png_get_PLTE(png_ptr,info_ptr, &png_palette, &palette_entries);

						palette_entries = MIN((unsigned)palette_entries, FreeImage_GetColorsUsed(dib));

						// store the palette

						RGBQUAD *palette = FreeImage_GetPalette(dib);
						for(int i = 0; i < palette_entries; i++) {
							palette[i].rgbRed   = png_palette[i].red;
							palette[i].rgbGreen = png_palette[i].green;
							palette[i].rgbBlue  = png_palette[i].blue;
						}
					}
					break;

				case PNG_COLOR_TYPE_GRAY:
					dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);

					if(dib && (pixel_depth <= 8)) {
						RGBQUAD *palette = FreeImage_GetPalette(dib);
						const int palette_entries = 1 << pixel_depth;

						for(int i = 0; i < palette_entries; i++) {
							palette[i].rgbRed   =
							palette[i].rgbGreen =
							palette[i].rgbBlue  = (BYTE)((i * 255) / (palette_entries - 1));
						}
					}
					break;

				default:
					throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
			}

			if(!dib) {
				throw FI_MSG_ERROR_DIB_MEMORY;
			}

			// store the transparency table

			if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
				// array of alpha (transparency) entries for palette
				png_bytep trans_alpha = NULL;
				// number of transparent entries
				int num_trans = 0;						
				// graylevel or color sample values of the single transparent color for non-paletted images
				png_color_16p trans_color = NULL;

				png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color);

				if((color_type == PNG_COLOR_TYPE_GRAY) && trans_color) {
					// single transparent color
					if (trans_color->gray < 256) { 
						BYTE table[256]; 
						memset(table, 0xFF, 256); 
						table[trans_color->gray] = 0; 
						FreeImage_SetTransparencyTable(dib, table, 256); 
					}
					// check for a full transparency table, too
					else if ((trans_alpha) && (pixel_depth <= 8)) {
						FreeImage_SetTransparencyTable(dib, (BYTE *)trans_alpha, num_trans);
					}

				} else if((color_type == PNG_COLOR_TYPE_PALETTE) && trans_alpha) {
					// transparency table
					FreeImage_SetTransparencyTable(dib, (BYTE *)trans_alpha, num_trans);
				}
			}

			// store the background color (only supported for FIT_BITMAP types)

			if ((image_type == FIT_BITMAP) && png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) {
				// Get the background color to draw transparent and alpha images over.
				// Note that even if the PNG file supplies a background, you are not required to
				// use it - you should use the (solid) application background if it has one.

				png_color_16p image_background = NULL;
				RGBQUAD rgbBkColor;

				if (png_get_bKGD(png_ptr, info_ptr, &image_background)) {
					rgbBkColor.rgbRed      = (BYTE)image_background->red;
					rgbBkColor.rgbGreen    = (BYTE)image_background->green;
					rgbBkColor.rgbBlue     = (BYTE)image_background->blue;
					rgbBkColor.rgbReserved = 0;

					FreeImage_SetBackgroundColor(dib, &rgbBkColor);
				}
			}

			// get physical resolution

			if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) {
				png_uint_32 res_x, res_y;
				
				// we'll overload this var and use 0 to mean no phys data,
				// since if it's not in meters we can't use it anyway

				int res_unit_type = PNG_RESOLUTION_UNKNOWN;

				png_get_pHYs(png_ptr,info_ptr, &res_x, &res_y, &res_unit_type);

				if (res_unit_type == PNG_RESOLUTION_METER) {
					FreeImage_SetDotsPerMeterX(dib, res_x);
					FreeImage_SetDotsPerMeterY(dib, res_y);
				}
			}

			// get possible ICC profile

			if (png_get_valid(png_ptr, info_ptr, PNG_INFO_iCCP)) {
				png_charp profile_name = NULL;
				png_bytep profile_data = NULL;
				png_uint_32 profile_length = 0;
				int  compression_type;

				png_get_iCCP(png_ptr, info_ptr, &profile_name, &compression_type, &profile_data, &profile_length);

				// copy ICC profile data (must be done after FreeImage_AllocateHeader)

				FreeImage_CreateICCProfile(dib, profile_data, profile_length);
			}

			// --- header only mode => clean-up and return

			if (header_only) {
				// get possible metadata (it can be located both before and after the image data)
				ReadMetadata(png_ptr, info_ptr, dib);
				if (png_ptr) {
					// clean up after the read, and free any memory allocated - REQUIRED
					png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
				}
				return dib;
			}

			// set the individual row_pointers to point at the correct offsets

			row_pointers = (png_bytepp)malloc(height * sizeof(png_bytep));

			if (!row_pointers) {
				png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
				FreeImage_Unload(dib);
				return NULL;
			}

			// read in the bitmap bits via the pointer table
			// allow loading of PNG with minor errors (such as images with several IDAT chunks)

			for (png_uint_32 k = 0; k < height; k++) {
				row_pointers[height - 1 - k] = FreeImage_GetScanLine(dib, k);
			}

			png_set_benign_errors(png_ptr, 1);
			png_read_image(png_ptr, row_pointers);

			// check if the bitmap contains transparency, if so enable it in the header

			if (FreeImage_GetBPP(dib) == 32) {
				if (FreeImage_GetColorType(dib) == FIC_RGBALPHA) {
					FreeImage_SetTransparent(dib, TRUE);
				} else {
					FreeImage_SetTransparent(dib, FALSE);
				}
			}
				
			// cleanup

			if (row_pointers) {
				free(row_pointers);
				row_pointers = NULL;
			}

			// read the rest of the file, getting any additional chunks in info_ptr

			png_read_end(png_ptr, info_ptr);

			// get possible metadata (it can be located both before and after the image data)

			ReadMetadata(png_ptr, info_ptr, dib);

			if (png_ptr) {
				// clean up after the read, and free any memory allocated - REQUIRED
				png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
			}

			return dib;

		} catch (const char *text) {
			if (png_ptr) {
				png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
			}
			if (row_pointers) {
				free(row_pointers);
			}
			if (dib) {
				FreeImage_Unload(dib);
			}
			FreeImage_OutputMessageProc(s_format_id, text);
			
			return NULL;
		}
	}			

	return NULL;
}
Beispiel #25
0
int loadPNG(ePtr<gPixmap> &result, const char *filename, int accel)
{
	__u8 header[8];
	FILE *fp=fopen(filename, "rb");
	
	if (!fp)
	{
//		eDebug("couldn't open %s", filename );
		return 0;
	}
	if (!fread(header, 8, 1, fp))
	{
		eDebug("couldn't read");
		fclose(fp);
		return 0;
	}
	if (png_sig_cmp(header, 0, 8))
	{
		fclose(fp);
		return 0;
	}
	png_structp png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
	if (!png_ptr)
	{
		eDebug("no pngptr");
		fclose(fp);
		return 0;
	}
	png_infop info_ptr=png_create_info_struct(png_ptr);
	if (!info_ptr)
	{
		eDebug("no info ptr");
		png_destroy_read_struct(&png_ptr, (png_infopp)0, (png_infopp)0);
		fclose(fp);
		return 0;
	}
	png_infop end_info = png_create_info_struct(png_ptr);
	if (!end_info)
	{
		eDebug("no end");
		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
		fclose(fp);
		return 0;
	 }
	if (setjmp(png_jmpbuf(png_ptr)))
	{
		eDebug("das war wohl nix");
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		fclose(fp);
		result = 0;
		return 0;
	}
	png_init_io(png_ptr, fp);
	png_set_sig_bytes(png_ptr, 8);
	png_set_invert_alpha(png_ptr);
	png_read_info(png_ptr, info_ptr);
	
	png_uint_32 width, height;
	int bit_depth;
	int color_type;
	
	png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
	
	if (color_type == PNG_COLOR_TYPE_GRAY || color_type & PNG_COLOR_MASK_PALETTE)
	{
		if (bit_depth < 8)
		{
			png_set_packing(png_ptr);
			bit_depth = 8;
		}

		result=new gPixmap(eSize(width, height), bit_depth, accel);
		gSurface *surface = result->surface;
	
		png_bytep *rowptr=new png_bytep[height];
	
		for (unsigned int i=0; i<height; i++)
			rowptr[i]=((png_byte*)(surface->data))+i*surface->stride;
		png_read_rows(png_ptr, rowptr, 0, height);
	
		delete [] rowptr;
	
		if (png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE))
		{
			png_color *palette;
			int num_palette;
			png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
			if (num_palette)
				surface->clut.data=new gRGB[num_palette];
			else
				surface->clut.data=0;
			surface->clut.colors=num_palette;
			
			for (int i=0; i<num_palette; i++)
			{
				surface->clut.data[i].a=0;
				surface->clut.data[i].r=palette[i].red;
				surface->clut.data[i].g=palette[i].green;
				surface->clut.data[i].b=palette[i].blue;
			}
			if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
			{
				png_byte *trans;
				png_get_tRNS(png_ptr, info_ptr, &trans, &num_palette, 0);
				for (int i=0; i<num_palette; i++)
					surface->clut.data[i].a=255-trans[i];
			}
		} else
		{
			surface->clut.data=0;
			surface->clut.colors=0;
		}
		surface->clut.start=0;
		png_read_end(png_ptr, end_info);
	} else {
		result=0;
		eDebug("%s: %dx%dx%d png, %d", filename, (int)width, (int)height, (int)bit_depth, color_type);
	}

	png_destroy_read_struct(&png_ptr, &info_ptr,&end_info);
	fclose(fp);
	return 0;
}
Beispiel #26
0
img_t* load_png(char* filename) {
  FILE* fp = fopen(filename, "rb");
  if (!fp) {
    fprintf(stderr, "ERROR: Could not open input file %s\n", filename);
    exit(-1);
  }
  
  png_byte pngsig[8];
  fread(pngsig, 1, 8, fp);
  int is_png = !png_sig_cmp(pngsig, 0, 8);
  if (!is_png) {
    fprintf(stderr, "ERROR: File %s is not a PNG!\n", filename);
    fclose(fp);
    exit(-1);
  }
  
  png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
  if (!png_ptr) {
    fprintf(stderr, "ERROR: Could not open input file %s\n", filename);
    fclose(fp);
    exit(-1);
  }

  png_infop info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr) {
    png_destroy_read_struct(&png_ptr, 0, 0);
    fprintf(stderr, "ERROR: Could not open input file %s\n", filename);
    fclose(fp);
    exit(-1);
  }

  png_infop end_info = png_create_info_struct(png_ptr);
  if (!end_info) {
    png_destroy_read_struct(&png_ptr, &info_ptr, 0);
    fprintf(stderr, "ERROR: Could not open input file %s\n", filename);
    fclose(fp);
    exit(-1);
  }
  
  if (setjmp(png_jmpbuf(png_ptr))) {
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    fprintf(stderr, "ERROR: Could not open input file %s\n", filename);
    fclose(fp);
    exit(-1);
  }
  
  png_init_io(png_ptr, fp);
  png_set_sig_bytes(png_ptr, 8);
  
  png_uint_32 width, height;
  int bit_depth, color_type;
  
  png_read_info(png_ptr, info_ptr);
  png_get_IHDR(png_ptr, info_ptr, &width, &height,
               &bit_depth, &color_type, NULL, NULL, NULL);

  if (color_type == PNG_COLOR_TYPE_PALETTE)
    png_set_expand (png_ptr);
  if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
    png_set_expand (png_ptr);
  if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
    png_set_expand (png_ptr);
  if (bit_depth == 16)
    png_set_strip_16 (png_ptr);
  if (color_type == PNG_COLOR_TYPE_GRAY ||
    color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
    png_set_gray_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,
    NULL, NULL, NULL);

  unsigned row_bytes = png_get_rowbytes (png_ptr, info_ptr);

  unsigned char* png_pixels = malloc (row_bytes * height * sizeof (png_byte));
  unsigned char** ret = malloc(height * sizeof (png_bytep));
  unsigned i;
  for (i = 0; i < (height); i++)
    ret[i] = png_pixels + i * row_bytes;

  png_read_image (png_ptr, ret);
  png_read_end (png_ptr, info_ptr);
  fclose(fp);
  
  img_t* image = malloc(sizeof(img_t));
  image->pixels = ret;
  image->top = 0;
  image->left = 0;
  image->w = width;
  image->h = height;
  image->center_x = width / 2;
  image->center_y = height / 2;
  image->filename = filename;

  return image;
}
Beispiel #27
0
bool Cc3dImage::_initWithPngData(void * pData, int nDatalen)
{
// length of bytes to check if it is a valid png file
#define PNGSIGSIZE  8
    bool bRet = false;
    png_byte        header[PNGSIGSIZE]   = {0}; 
    png_structp     png_ptr     =   0;
    png_infop       info_ptr    = 0;

    do 
    {
        // png header len is 8 bytes
        if(nDatalen < PNGSIGSIZE) break;

        // check the data is png or not
        memcpy(header, pData, PNGSIGSIZE);
        if(png_sig_cmp(header, 0, PNGSIGSIZE)) break;

        // init png_struct
        png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
        if(! png_ptr) break;

        // init png_info
        info_ptr = png_create_info_struct(png_ptr);
        if(!info_ptr) break;


        // set the read call back function
        tImageSource imageSource;
        imageSource.data    = (unsigned char*)pData;
        imageSource.size    = nDatalen;
        imageSource.offset  = 0;
        png_set_read_fn(png_ptr, &imageSource, pngReadCallback);

        // read png header info
        
        // read png file info
        png_read_info(png_ptr, info_ptr);
        
        m_nWidth = png_get_image_width(png_ptr, info_ptr);
        m_nHeight = png_get_image_height(png_ptr, info_ptr);
        m_nBitsPerComponent = png_get_bit_depth(png_ptr, info_ptr);
        png_uint_32 color_type = png_get_color_type(png_ptr, info_ptr);

        //CCLOG("color type %u", color_type);
        
        // force palette images to be expanded to 24-bit RGB
        // it may include alpha channel
        if (color_type == PNG_COLOR_TYPE_PALETTE)
        {
            png_set_palette_to_rgb(png_ptr);
        }
        // low-bit-depth grayscale images are to be expanded to 8 bits
        if (color_type == PNG_COLOR_TYPE_GRAY && m_nBitsPerComponent < 8)
        {
            png_set_expand_gray_1_2_4_to_8(png_ptr);
        }
        // expand any tRNS chunk data into a full alpha channel
        if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
        {
            png_set_tRNS_to_alpha(png_ptr);
        }  
        // reduce images with 16-bit samples to 8 bits
        if (m_nBitsPerComponent == 16)
        {
            png_set_strip_16(png_ptr);            
        } 
        // expand grayscale images to RGB
        if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
        {
            png_set_gray_to_rgb(png_ptr);
        }

        // read png data
        // m_nBitsPerComponent will always be 8
        m_nBitsPerComponent = 8;
        png_uint_32 rowbytes;
        png_bytep* row_pointers = (png_bytep*)malloc( sizeof(png_bytep) * m_nHeight );
        
        png_read_update_info(png_ptr, info_ptr);
        
        rowbytes = png_get_rowbytes(png_ptr, info_ptr);
        
        m_pData = new unsigned char[rowbytes * m_nHeight];
        if(!m_pData) break;
        
        for (unsigned short i = 0; i < m_nHeight; ++i)
        {
            row_pointers[i] = m_pData + i*rowbytes;
        }
        png_read_image(png_ptr, row_pointers);
        
        png_read_end(png_ptr, NULL);
        
        png_uint_32 channel = rowbytes/m_nWidth;
        if (channel == 4)
        {
            m_bHasAlpha = true;
            unsigned int *tmp = (unsigned int *)m_pData;
            for(unsigned short i = 0; i < m_nHeight; i++)
            {
                for(unsigned int j = 0; j < rowbytes; j += 4)
                {
                    *tmp++ = CC_RGB_PREMULTIPLY_ALPHA( row_pointers[i][j], row_pointers[i][j + 1], 
                                                      row_pointers[i][j + 2], row_pointers[i][j + 3] );
                }
            }
            
            m_bPreMulti = true;
        }

		do { if(row_pointers) { free(row_pointers); (row_pointers) = 0; } } while(0);

        bRet = true;
    } while (0);

    if (png_ptr)
    {
        png_destroy_read_struct(&png_ptr, (info_ptr) ? &info_ptr : 0, 0);
    }
    return bRet;
}
Beispiel #28
0
int main(int argc, char **argv)
{

	char* outfile = NULL;
	save_mode mode = RAW;

	unsigned split_w = 0;
	unsigned split_h = 0;

	int opt;
	while((opt=getopt(argc, argv, "brpns:o:h?")) != -1) {
		switch(opt) {
			case 'b':
				mode = BINARY;
				break;
			case 'n':
				mode = PALETTE_NO_OUTPUT;
				break;
			case 'p':
				mode = PALETTE;
				break;
			case 'r':
				mode = RGB;
				break;
			case 's':
				{
					unsigned pos;
					if(sscanf(optarg, "%ux%u%n", &split_w, &split_h, &pos)!=2 || pos != strlen(optarg)) {
						usage();
						exit(1);
					}
				}
				break;
			case 'o':
				outfile = optarg;
				break;
			case 'h':
			case '?':
				usage();
				exit(1);
		}
	}

	char** inputfiles = argv + optind;
	unsigned inputcount = argc - optind;

	if (!inputcount) {
		usage();
		exit(1);
	}

	for (unsigned input_nr = 0; input_nr < inputcount; input_nr++) {
		FILE *f = fopen(inputfiles[input_nr], "rb");
		if (!f) {
			fprintf(stderr, "Could not open file %s for reading\n", inputfiles[input_nr]);
			continue;
		}
		char *out = outfile;
		if (!out) {
			out = (char*)malloc(strlen(inputfiles[input_nr])+3);
			sprintf(out, "%s.h", inputfiles[input_nr]);
		}

		FILE *outstream = fopen(out, "w");
		if (!outstream) {
			fprintf(stderr, "Could not open file %s for writing\n", out);
			continue;
		}

		char *file_basename = basename(inputfiles[input_nr]);
		for (unsigned i = 0; i < strlen(file_basename); i++) {
			if (file_basename[i] >= 'a' && file_basename[i] <= 'z') {
				file_basename[i] = file_basename[i] + 'A' - 'a';
			} else if (file_basename[i] >= 'A' && file_basename[i] <= 'Z') {
			} else {
				file_basename[i] = '_';
			}
		}


		char *data_array_name = (char*)malloc(strlen(file_basename)+6);
		sprintf(data_array_name, "%s_DATA", file_basename);
		char *plte_array_name = (char*)malloc(strlen(file_basename)+6);
		sprintf(plte_array_name, "%s_PLTE", file_basename);


		unsigned char header[8];
		fread(header, 1, 8, f);
		if (png_sig_cmp(header, 0, 8)) {
			fprintf(stderr, "%s is not a png file", inputfiles[input_nr]);
			continue;
		}
		png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
		if (!png_ptr) {
			fprintf(stderr, "png_create_read_struct failed");
			continue;
		}
		png_infop info_ptr = png_create_info_struct(png_ptr);
		if (!info_ptr) {
			fprintf(stderr, "png_create_info_struct failed");
			png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
			continue;
		}
		if (setjmp(png_jmpbuf(png_ptr))) {
			fprintf(stderr, "Error during init_io");
			png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
			continue;
		}
		png_init_io(png_ptr, f);
		png_set_sig_bytes(png_ptr, 8);

		png_read_info(png_ptr, info_ptr);

		unsigned width = png_get_image_width(png_ptr, info_ptr);
		unsigned height = png_get_image_height(png_ptr, info_ptr);
		png_byte color_type = png_get_color_type(png_ptr, info_ptr);
		png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);

		
		if (mode == PALETTE || mode == PALETTE_NO_OUTPUT) { // does the user want palette output?
			if ((color_type & PNG_COLOR_MASK_PALETTE) == 0 && (color_type & PNG_COLOR_MASK_COLOR)) { //the image must have a palette or be grayscale
				fprintf(stderr, "%s is not a palette or grayscale image\n", inputfiles[input_nr]);
				continue;
			}
		}


		png_set_interlace_handling(png_ptr);

		// Reduce to 8 bits
		png_set_strip_16(png_ptr);

		png_set_strip_alpha(png_ptr);

		// Unpack 1, 2, 4 bits into 8
		png_set_packing(png_ptr);

		if (mode == RGB) {
			png_set_palette_to_rgb(png_ptr);
		}

		// Done setting read flags
		png_read_update_info(png_ptr, info_ptr);

		png_bytep* row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height);
		
		for (unsigned y = 0; y < height; y++) {
			row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png_ptr, info_ptr));
		}

		png_read_image(png_ptr, row_pointers);

		png_read_end(png_ptr, info_ptr);


		if (mode == PALETTE) {
			if (color_type & PNG_COLOR_MASK_COLOR) { // image is actually paletted
				int plte_length;
				png_colorp plte_colors;
				png_get_PLTE(png_ptr, info_ptr, &plte_colors, &plte_length);
				fprintf(outstream, "uint32_t %s[%d] = {\n", plte_array_name, plte_length);
				for (int i = 0; i < plte_length; i++) {
					uint32_t color = plte_colors[i].red << 16 | plte_colors[i].green << 8 | plte_colors[i].blue;
					fprintf(outstream, "0x%06lX, ", (unsigned long)color);
				}
				fprintf(outstream, "\n};\n\n");

			} else { // create a default grayscale palette
				int plte_length = 1 << bit_depth;
				fprintf(outstream, "uint32_t %s[%d] = {\n", plte_array_name, plte_length);
				for (int i = 0; i < plte_length; i++) {
					printf("%d\n", i);
					int current_bits = i;
					uint32_t color = 0;
					int target_bits = 3 * 8;
					for (int bit = 0; bit < target_bits; bit += bit_depth) {
						color |= current_bits;
						current_bits <<= bit_depth;
					}
					fprintf(outstream, "0x%06lX, ", (unsigned long)color);
				}
				fprintf(outstream, "};\n\n");
			}
		}


		unsigned tile_h = split_h ? split_h : height;
		unsigned tile_w = split_w ? split_w : width;

		unsigned byte_per_pixel = png_get_rowbytes(png_ptr, info_ptr) / width;

		unsigned long pixel_count = width * height;

		fprintf(outstream, "uint%d_t %s[%lu] = {\n", mode == RGB ? 32 : 8, data_array_name, mode == BINARY ? pixel_count / 8 : pixel_count);
		

		for (unsigned tile_y = 0; tile_y + tile_h <= height; tile_y += tile_h) {
			for (unsigned tile_x = 0; tile_x + tile_w <= width; tile_x += tile_w) {
				fprintf(outstream, "// Tile (%d, %d)\n", tile_x / tile_w, tile_y / tile_h);

				switch(mode) {
					case BINARY:
						for (unsigned y = tile_y; y < tile_y + tile_h; y++) {
							png_byte* row = row_pointers[y];
							for (unsigned x0 = tile_x; x0 < tile_x + tile_w; x0 += 8) {
								uint8_t current_bit = 1;
								uint8_t total = 0;
								for (unsigned x = x0; x < x0 + 8 && x < tile_x + tile_w; x++, current_bit <<= 1) {
									if (row[byte_per_pixel * x]) {
										total |= current_bit;
									}
								}
								fprintf(outstream, "0x%02X, ", total);
							}
							fprintf(outstream, "\n");
						}

						break;
					case PALETTE:
					case PALETTE_NO_OUTPUT:
						for (unsigned y = tile_y; y < tile_y + tile_h; y++) {
							png_byte* row = row_pointers[y];
							for (unsigned x = tile_x; x < tile_x + tile_w; x++) {
								fprintf(outstream, "%d, ", row[byte_per_pixel * x]);
							}
							fprintf(outstream, "\n");
						}

						break;
					case RGB:
					case RAW:
					default:
						for (unsigned y = tile_y; y < tile_y + tile_h; y++) {
							png_byte* row = row_pointers[y];
							for (unsigned x = tile_x; x < tile_x + tile_w; x++) {
								fprintf(outstream, "0x");
								for (unsigned i = 0; i < byte_per_pixel; i++) {
									fprintf(outstream, "%02X", row[byte_per_pixel * x + i]);
								}
								fprintf(outstream, ", ");
							}
							fprintf(outstream, "\n");
						}

						break;
				}

			}
		}

		fprintf(outstream, "};\n\n");

		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

		fclose(f);

	}

	
	

}
Beispiel #29
0
/* (Obsolete) function to check signature bytes.  It does not allow one
 * to check a partial signature.  This function might be removed in the
 * future - use png_sig_cmp().  Returns true (nonzero) if the file is PNG.
 */
int PNGAPI
png_check_sig(png_bytep sig, int num)
{
  return ((int)!png_sig_cmp(sig, (png_size_t)0, (png_size_t)num));
}
Beispiel #30
0
bool isPNG(struct VFile* source) {
	png_byte header[PNG_HEADER_BYTES];
	source->read(source, header, PNG_HEADER_BYTES);
	return !png_sig_cmp(header, 0, PNG_HEADER_BYTES);
}