Пример #1
0
Image* Image::create(const char* path)
{
    GP_ASSERT(path);

    // Open the file.
    std::unique_ptr<Stream> stream(FileSystem::open(path));
    if (stream.get() == NULL || !stream->canRead())
    {
        GP_ERROR("Failed to open image file '%s' - %d.", path, errno);
        return NULL;
    }

    // Verify PNG signature.
    unsigned char sig[8];
    if (stream->read(sig, 1, 8) != 8 || png_sig_cmp(sig, 0, 8) != 0)
    {
        GP_ERROR("Failed to load file '%s'; not a valid PNG.", path);
        return NULL;
    }

    // Initialize png read struct (last three parameters use stderr+longjump if NULL).
    png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (png == NULL)
    {
        GP_ERROR("Failed to create PNG structure for reading PNG file '%s'.", path);
        return NULL;
    }

    // Initialize info struct.
    png_infop info = png_create_info_struct(png);
    if (info == NULL)
    {
        GP_ERROR("Failed to create PNG info structure for PNG file '%s'.", path);
        png_destroy_read_struct(&png, NULL, NULL);
        return NULL;
    }

    // Set up error handling (required without using custom error handlers above).
    if (setjmp(png_jmpbuf(png)))
    {
        GP_ERROR("Failed to set up error handling for reading PNG file '%s'.", path);
        png_destroy_read_struct(&png, &info, NULL);
        return NULL;
    }

    // Initialize file io.
    png_set_read_fn(png, stream.get(), readStream);

    // Indicate that we already read the first 8 bytes (signature).
    png_set_sig_bytes(png, 8);

    // Read the entire image into memory.
    png_read_png(png, info, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_GRAY_TO_RGB, NULL);

    Image* image = new Image();
    image->_width = png_get_image_width(png, info);
    image->_height = png_get_image_height(png, info);

    png_byte colorType = png_get_color_type(png, info);
    switch (colorType)
    {
    case PNG_COLOR_TYPE_RGBA:
        image->_format = Image::RGBA;
        break;

    case PNG_COLOR_TYPE_RGB:
        image->_format = Image::RGB;
        break;

    default:
        GP_ERROR("Unsupported PNG color type (%d) for image file '%s'.", (int)colorType, path);
        png_destroy_read_struct(&png, &info, NULL);
        return NULL;
    }

    size_t stride = png_get_rowbytes(png, info);

    // Allocate image data.
    image->_data = new unsigned char[stride * image->_height];

    //GP_INFO("File[%s] ColorType : %d height : %d width : %d size : %d", path, image->_format, image->_height, image->_width, stride * image->_height);

    // Read rows into image data.
    png_bytepp rows = png_get_rows(png, info);
    for (unsigned int i = 0; i < image->_height; ++i)
    {
        memcpy(image->_data+(stride * (image->_height-1-i)), rows[i], stride);
    }

    //if (0 == strcmp(path, "res/hello_jpg.png"))
    //{
    //    std::string strTmp;
    //    for (int i = 0; i < stride * image->_height; i++)
    //    {
    //        char szTmp[10] = { 0 };
    //        sprintf(szTmp, "%02X", image->_data[i]);
    //        strTmp.append(szTmp);
    //        if (i % 20 == 0)
    //        {
    //            GP_INFO("DATA : %s", strTmp.c_str());
    //            strTmp.assign("");
    //        }
    //    }
    //    if (strTmp.length())
    //    {
    //        GP_INFO("DATA : %s", strTmp.c_str());
    //    }
    //}

    // Clean up.
    png_destroy_read_struct(&png, &info, NULL);

    return image;
}
Пример #2
0
bool Image::initWithPngData(const unsigned char * data, ssize_t dataLen)
{
#if CC_USE_WIC
	return decodeWithWIC(data, dataLen);
#else
	// length of bytes to check if it is a valid png file
#define PNGSIGSIZE  8
	bool ret = false;
	png_byte        header[PNGSIGSIZE] = { 0 };
	png_structp     png_ptr = 0;
	png_infop       info_ptr = 0;

	do
	{
		// png header len is 8 bytes
		CC_BREAK_IF(dataLen < PNGSIGSIZE);

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

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

		// init png_info
		info_ptr = png_create_info_struct(png_ptr);
		CC_BREAK_IF(!info_ptr);

#if (PARA_TARGET_PLATFORM != PARA_PLATFORM_BADA && PARA_TARGET_PLATFORM != PARA_PLATFORM_NACL && PARA_TARGET_PLATFORM != PARA_PLATFORM_TIZEN)
		CC_BREAK_IF(setjmp(png_jmpbuf(png_ptr)));
#endif

		// set the read call back function
		tImageSource imageSource;
		imageSource.data = (unsigned char*)data;
		imageSource.size = dataLen;
		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);

		_width = png_get_image_width(png_ptr, info_ptr);
		_height = png_get_image_height(png_ptr, info_ptr);
		png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);
		png_uint_32 color_type = png_get_color_type(png_ptr, info_ptr);

		//OUTPUT_LOG("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 && bit_depth < 8)
		{
			bit_depth = 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 (bit_depth == 16)
		{
			png_set_strip_16(png_ptr);
		}

		// Expanded earlier for grayscale, now take care of palette and rgb
		if (bit_depth < 8)
		{
			png_set_packing(png_ptr);
		}
		// update info
		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:
			_renderFormat = Texture2D::PixelFormat::I8;
			break;
		case PNG_COLOR_TYPE_GRAY_ALPHA:
			_renderFormat = Texture2D::PixelFormat::AI88;
			break;
		case PNG_COLOR_TYPE_RGB:
			_renderFormat = Texture2D::PixelFormat::RGB888;
			break;
		case PNG_COLOR_TYPE_RGB_ALPHA:
			_renderFormat = Texture2D::PixelFormat::RGBA8888;
			break;
		default:
			break;
		}

		// read png data
		png_size_t rowbytes;
		png_bytep* row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * _height);

		rowbytes = png_get_rowbytes(png_ptr, info_ptr);

		_dataLen = rowbytes * _height;
		_data = static_cast<unsigned char*>(malloc(_dataLen * sizeof(unsigned char)));
		if (!_data)
		{
			if (row_pointers != nullptr)
			{
				free(row_pointers);
			}
			break;
		}

		for (unsigned short i = 0; i < _height; ++i)
		{
			row_pointers[i] = _data + i*rowbytes;
		}
		png_read_image(png_ptr, row_pointers);

		png_read_end(png_ptr, nullptr);

		// premultiplied alpha for RGBA8888
		if (PNG_PREMULTIPLIED_ALPHA_ENABLED && color_type == PNG_COLOR_TYPE_RGB_ALPHA)
		{
			premultipliedAlpha();
		}

		if (row_pointers != nullptr)
		{
			free(row_pointers);
		}

		ret = true;
	} while (0);

	if (png_ptr)
	{
		png_destroy_read_struct(&png_ptr, (info_ptr) ? &info_ptr : 0, 0);
	}
	return ret;
#endif
}
/*
 * Magical PNG loader. You probably shouldn't edit this.
 */
int loadTextureFromPNG(char* filename , TextureInfo* t){

	//Required structs and file pointers.
	png_structp png_ptr;
    png_infop info_ptr;
    unsigned int sig_read = 0;
    FILE *fp;

    //Again, this should return an error code instead of exiting,
    //but for this assignment, it should work anyway.
    if ((fp = fopen(filename, "rb")) == NULL){
        printf("Error opening %s\n",filename);
        exit(1);
    }

    //Magic, do not touch.
    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

    if (png_ptr == NULL) {
    	printf("LibPNG did something terrible!\n");
        fclose(fp);
        exit(1);
    }

    //Allocate the struct we're going to read the data into.
    info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL) {
    	printf("LibPNG did something terrible!\n");
        fclose(fp);
        png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
        exit(1);
    }

    //Error handling magic. Do not touch.
    if (setjmp(png_jmpbuf(png_ptr))) {
    	printf("LibPNG did something terrible!\n");
        png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
        fclose(fp);
        exit(1);
    }

    //Point libPNG to the right place
    png_init_io(png_ptr, fp);
    png_set_sig_bytes(png_ptr, sig_read);

    //Yet more magic you shouldn't touch. We -probably- have enough memory to read it all in one go.
    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, png_voidp_NULL);

    //Start setting values in the textureinfo struct
    //Note that PNGs -can- have alpha.
    t->width = png_get_image_width(png_ptr,info_ptr);
    t->height = png_get_image_height(png_ptr,info_ptr);
    switch (png_get_color_type(png_ptr,info_ptr)) {
        case PNG_COLOR_TYPE_RGBA:
            t->hasAlpha = true;
            break;
        case PNG_COLOR_TYPE_RGB:
        	t->hasAlpha = false;
            break;
        default:
            printf("Invalid PNG.\n");
            png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
            fclose(fp);
            exit(1);
    }
    //How long is a row?
    unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
    //Allocate some space!
    t->textureData = (unsigned char*) malloc(row_bytes * t->height);

    //Read the image data into the texture array, in reverse row order. Because GL.
    png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);
    for (int i = 0; i < t->height; i++) {
        memcpy(t->textureData+(row_bytes * (t->height-1-i)), row_pointers[i], row_bytes);
    }

    //Clean up
    png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
    fclose(fp);

    return 0;
}
Пример #4
0
unsigned char* load_png_data(char *filename, int *w, int *h) {
    FILE *fp = fopen(filename, "rb");
    if(!fp) {
        return NULL;
    }
    png_byte header[8];
    fread(header, 1, 8, fp);
    if(png_sig_cmp(header, 0, 8)) {
        return NULL;
    }

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

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

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

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

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

    png_read_info(png_ptr, info_ptr);

    int bit_depth = png_get_bit_depth(png_ptr, info_ptr);

    switch(png_get_color_type(png_ptr, info_ptr)) {
    case PNG_COLOR_TYPE_PALETTE:
        png_set_palette_to_rgb(png_ptr);
        png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
        break;
    case PNG_COLOR_TYPE_GRAY:
        png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
    case PNG_COLOR_TYPE_GRAY_ALPHA:
        if(bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr);
        if(bit_depth==16) png_set_strip_16(png_ptr);
        png_set_gray_to_rgb(png_ptr);
        break;
    case PNG_COLOR_TYPE_RGB:
        if(bit_depth <  8 ) png_set_packing(png_ptr);
        if(bit_depth == 16) png_set_strip_16(png_ptr);
        png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
        break;
    default:
        break;
    }

    png_read_update_info(png_ptr, info_ptr);

    *w = png_get_image_width(png_ptr, info_ptr);
    *h = png_get_image_height(png_ptr, info_ptr);
    int rowbytes = (int)png_get_rowbytes(png_ptr, info_ptr);

    png_bytep data = malloc((*h)*rowbytes*sizeof(*data));

    png_bytep row_pointers[*h];

    int i;
    for(i=0; i<(*h); ++i) {
        row_pointers[i] = &data[i*rowbytes];
    }

    png_read_image(png_ptr, row_pointers);

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

    fclose(fp);

    return data;
}
Пример #5
0
Файл: png.cpp Проект: kyuu/azura
    //-----------------------------------------------------------------
    Image::Ptr ReadPNG(File* file)
    {
        assert(file);

        if (!file) {
            return 0;
        }

        // initialize the necessary libpng data structures
        png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
        if (!png_ptr) {
            return 0;
        }
        png_infop info_ptr = png_create_info_struct(png_ptr);
        if (!info_ptr) {
            png_destroy_read_struct(&png_ptr, 0, 0);
            return 0;
        }

        // check if the file is actually a PNG file
        u8 sig_buf[8];
        if (file->read(sig_buf, 8) != 8 || png_sig_cmp(sig_buf, 0, 8) != 0) {
            png_destroy_read_struct(&png_ptr, &info_ptr, 0);
            return 0;
        }

        // libpng uses SJLJ for error handling, so we need to define
        // any automatic variables before the call to setjmp()
        Image::Ptr image;
        ArrayAutoPtr<png_bytep> rows;

        // establish a return point
        if (setjmp(png_jmpbuf(png_ptr)) != 0) {
            png_destroy_read_struct(&png_ptr, &info_ptr, 0);
            return 0;
        }

        // tell libpng that we are already 8 bytes into the image file
        png_set_sig_bytes(png_ptr, 8);

        // tell libpng that we are going to use our own io functions
        png_set_read_fn(png_ptr, file, read_callback);

        // read the png header
        png_read_info(png_ptr, info_ptr);

        // get the image attributes
        int img_width      = png_get_image_width(png_ptr, info_ptr);
        int img_height     = png_get_image_height(png_ptr, info_ptr);
        int img_bit_depth  = png_get_bit_depth(png_ptr, info_ptr);
        int img_color_type = png_get_color_type(png_ptr, info_ptr);

        // if the color channel bit depth is 16 bit, strip it to 8 bit
        if (img_bit_depth == 16) {
            png_set_strip_16(png_ptr);
        }

        // Note: Not sure if we need this, or if it's correct what we are doing here.
        // if the image has a tRNS chunk, use it for the alpha channel
        //if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
        //    png_set_tRNS_to_alpha(png_ptr);
        //}

        switch (img_color_type)
        {
            case PNG_COLOR_TYPE_PALETTE:
            {
                image = new ImageImpl(img_width, img_height, PixelFormat::RGB_P8);

                // get palette
                png_colorp palette = 0;
                int num_palette = 0;
                png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);

                // copy palette over to image
                std::memcpy(image->getPalette(), palette, num_palette * sizeof(RGB));

                break;
            }
            case PNG_COLOR_TYPE_GRAY:
            {
                png_set_gray_to_rgb(png_ptr);
                image = new ImageImpl(img_width, img_height, PixelFormat::RGB);
                break;
            }
            case PNG_COLOR_TYPE_GRAY_ALPHA:
            {
                png_set_gray_to_rgb(png_ptr);
                image = new ImageImpl(img_width, img_height, PixelFormat::RGBA);
                break;
            }
            case PNG_COLOR_TYPE_RGB:
            {
                image = new ImageImpl(img_width, img_height, PixelFormat::RGB);
                break;
            }
            case PNG_COLOR_TYPE_RGB_ALPHA:
            {
                image = new ImageImpl(img_width, img_height, PixelFormat::RGBA);
                break;
            }
            default: // shouldn't happen
                png_destroy_read_struct(&png_ptr, &info_ptr, 0);
                return 0;
        }

        // prepare an array of row pointers for libpng
        PixelFormatDescriptor pfd = Image::GetPixelFormatDescriptor(image->getPixelFormat());
        rows = new png_bytep[img_height];
        for (int i = 0; i < img_height; ++i) {
            rows[i] = (png_bytep)(image->getPixels() + i * img_width * pfd.bytesPerPixel);
        }

        // read the image data
        png_read_image(png_ptr, rows.get());

        // finish the read process
        png_read_end(png_ptr, 0);

        // clean up
        png_destroy_read_struct(&png_ptr, &info_ptr, 0);

        return image;
    }
Пример #6
0
static bool loadPng(const uint8_t *inputData, size_t size,
		Bytes &outputData, Color &color, Alpha &alpha, uint32_t &width, uint32_t &height,
		uint32_t &stride, const Bitmap::StrideFn &strideFn) {
	auto png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (png_ptr == NULL) {
    	log::text("libpng", "fail to create read struct");
        return false;
    }

    auto info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL) {
    	log::text("libpng", "fail to create info struct");
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        return false;
    }

	if (setjmp(png_jmpbuf(png_ptr))) {
		log::text("libpng", "error in processing (setjmp return)");
	    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
	    return false;
	}

	Bitmap_readState state;
	state.data = inputData;
	state.offset = 0;

	png_set_read_fn(png_ptr,(png_voidp)&state, Bitmap_readDynamicData);
    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);
    png_byte bitdepth = png_get_bit_depth(png_ptr, info_ptr);
    png_uint_32 color_type = png_get_color_type(png_ptr, info_ptr);

    if (color_type == PNG_COLOR_TYPE_PALETTE) {
        png_set_palette_to_rgb(png_ptr);
    }
    if (color_type == PNG_COLOR_TYPE_GRAY && bitdepth < 8) {
    	bitdepth = 8;
        png_set_expand_gray_1_2_4_to_8(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 (bitdepth < 8) {
        png_set_packing(png_ptr);
    }

    png_read_update_info(png_ptr, info_ptr);
    bitdepth = png_get_bit_depth(png_ptr, info_ptr);
    color_type = png_get_color_type(png_ptr, info_ptr);
	auto rowbytes = png_get_rowbytes(png_ptr, info_ptr);

	if (color_type == PNG_COLOR_TYPE_GRAY) {
		color = (color == Color::A8?Color::A8:Color::I8);
	} else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
		color = Color::IA88;
	} else if (color_type == PNG_COLOR_TYPE_RGB) {
		color = Color::RGB888;
	} else if (color_type == PNG_COLOR_TYPE_RGBA) {
		color = Color::RGBA8888;
	} else {
		width = 0;
		height = 0;
		stride = 0;
		outputData.clear();
        log::format("Bitmap", "unsupported color type: %u", (unsigned int)color_type);
	    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
	    return false;
	}

	if (strideFn) {
		stride = max((uint32_t)strideFn(color, width), (uint32_t)rowbytes);
	} else {
		stride = (uint32_t)rowbytes;
	}

	if (color == Color::I8 || color == Color::RGB888) {
		alpha = Alpha::Opaque;
	} else {
		alpha = Alpha::Unpremultiplied;
	}

    // read png data
    png_bytep* row_pointers = new png_bytep[height];

    auto dataLen = stride * height;
    outputData.resize(dataLen);

    for (unsigned short i = 0; i < height; ++i) {
        row_pointers[i] = outputData.data() + i*stride;
    }

    png_read_image(png_ptr, row_pointers);
    png_read_end(png_ptr, nullptr);

    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

    delete [] row_pointers;

	if (!outputData.empty()) {
		return true;
	}

	return false;
}
Пример #7
0
int ShapeWipeMain::read_pattern_image(int new_frame_width, int new_frame_height)
{
	png_byte header[8];
	int is_png;
	int row;
	int col;
	int scaled_row;
	int scaled_col;
	int pixel_width;
	unsigned char value;
	png_uint_32 width;
	png_uint_32 height;
	png_byte color_type;
	png_byte bit_depth;
	png_structp png_ptr;
	png_infop info_ptr;
	png_infop end_info;
	png_bytep *image;
	frame_width = new_frame_width;
	frame_height = new_frame_height;

// Convert name to filename
	for(int i = 0; i < shape_paths.size(); i++)
	{
		if(!strcmp(shape_titles.get(i), shape_name))
		{
			strcpy(filename, shape_paths.get(i));
			break;
		}
	}

	FILE *fp = fopen(filename, "rb");
	if (!fp)
	{
		return 1;
	}

	fread(header, 1, 8, fp);
	is_png = !png_sig_cmp(header, 0, 8);

	if (!is_png)
	{
		return 1;
	}

	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
		NULL, NULL, NULL);

	if (!png_ptr)
	{
	return 1;
	}

	/* Tell libpng we already checked the first 8 bytes */
	png_set_sig_bytes(png_ptr, 8);

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

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

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

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

	/* Skip the alpha channel if present 
	* stripping alpha currently doesn't work in conjunction with 
	* converting to grayscale in libpng */
	if (color_type & PNG_COLOR_MASK_ALPHA)
		pixel_width = 2;
	else
		pixel_width = 1;

	/* Convert 16 bit data to 8 bit */
	if (bit_depth == 16) png_set_strip_16(png_ptr);

	/* Expand to 1 pixel per byte if necessary */
	if (bit_depth < 8) png_set_packing(png_ptr);

	/* Convert to grayscale */
	if (color_type == PNG_COLOR_TYPE_RGB || 
		color_type == PNG_COLOR_TYPE_RGB_ALPHA)
	png_set_rgb_to_gray_fixed(png_ptr, 1, -1, -1);

	/* Allocate memory to hold the original png image */
	image = (png_bytep*)malloc(sizeof(png_bytep)*height);
	for (row = 0; row < height; row++)
	{
		image[row] = (png_byte*)malloc(sizeof(png_byte)*width*pixel_width);
	}

	/* Allocate memory for the pattern image that will actually be
	* used for the wipe */
	pattern_image = (unsigned char**)malloc(sizeof(unsigned char*)*frame_height);


	png_read_image(png_ptr, image);
	png_read_end(png_ptr, end_info);

	double row_factor, col_factor;
	double row_offset = 0.5, col_offset = 0.5;	// for rounding

	if (preserve_aspect && aspect_w != 0 && aspect_h != 0)
	{
		row_factor = (height-1)/aspect_h;
		col_factor = (width-1)/aspect_w;
		if (row_factor < col_factor)
			col_factor = row_factor;
		else
			row_factor = col_factor;
		row_factor *= aspect_h/(double)(frame_height-1);
		col_factor *= aspect_w/(double)(frame_width-1);

		// center the pattern over the frame
		row_offset += (height-1-(frame_height-1)*row_factor)/2;
		col_offset += (width-1-(frame_width-1)*col_factor)/2;
	}
	else
	{
		// Stretch (or shrink) the pattern image to fill the frame
		row_factor = (double)(height-1)/(double)(frame_height-1);
		col_factor = (double)(width-1)/(double)(frame_width-1);
	}

	for (scaled_row = 0; scaled_row < frame_height; scaled_row++)
	{
		row = (int)(row_factor*scaled_row + row_offset);
		pattern_image[scaled_row] = (unsigned char*)malloc(sizeof(unsigned char)*frame_width);
		for (scaled_col = 0; scaled_col < frame_width; scaled_col++)
		{
			col = (int)(col_factor*scaled_col + col_offset)*pixel_width;
			value = image[row][col];
			pattern_image[scaled_row][scaled_col] = value;
			if (value < min_value) min_value = value;
			if (value > max_value) max_value = value;

		}
	}

	png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
	fclose(fp);
	/* Deallocate the original image as it is no longer needed */
	for (row = 0; row < height; row++)
	{
		free(image[row]);
	}
	free (image);
	return 0;
}
Пример #8
0
static GstFlowReturn
gst_pngdec_caps_create_and_set (GstPngDec * pngdec)
{
  GstFlowReturn ret = GST_FLOW_OK;
  gint bpc = 0, color_type;
  png_uint_32 width, height;
  GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;

  g_return_val_if_fail (GST_IS_PNGDEC (pngdec), GST_FLOW_ERROR);

  /* Get bits per channel */
  bpc = png_get_bit_depth (pngdec->png, pngdec->info);

  /* Get Color type */
  color_type = png_get_color_type (pngdec->png, pngdec->info);

  /* Add alpha channel if 16-bit depth, but not for GRAY images */
  if ((bpc > 8) && (color_type != PNG_COLOR_TYPE_GRAY)) {
    png_set_add_alpha (pngdec->png, 0xffff, PNG_FILLER_BEFORE);
    png_set_swap (pngdec->png);
  }
#if 0
  /* We used to have this HACK to reverse the outgoing bytes, but the problem
   * that originally required the hack seems to have been in videoconvert's
   * RGBA descriptions. It doesn't seem needed now that's fixed, but might
   * still be needed on big-endian systems, I'm not sure. J.S. 6/7/2007 */
  if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
    png_set_bgr (pngdec->png);
#endif

  /* Gray scale with alpha channel converted to RGB */
  if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
    GST_LOG_OBJECT (pngdec,
        "converting grayscale png with alpha channel to RGB");
    png_set_gray_to_rgb (pngdec->png);
  }

  /* Gray scale converted to upscaled to 8 bits */
  if ((color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ||
      (color_type == PNG_COLOR_TYPE_GRAY)) {
    if (bpc < 8) {              /* Convert to 8 bits */
      GST_LOG_OBJECT (pngdec, "converting grayscale image to 8 bits");
#if PNG_LIBPNG_VER < 10400
      png_set_gray_1_2_4_to_8 (pngdec->png);
#else
      png_set_expand_gray_1_2_4_to_8 (pngdec->png);
#endif
    }
  }

  /* Palette converted to RGB */
  if (color_type == PNG_COLOR_TYPE_PALETTE) {
    GST_LOG_OBJECT (pngdec, "converting palette png to RGB");
    png_set_palette_to_rgb (pngdec->png);
  }

  png_set_interlace_handling (pngdec->png);

  /* Update the info structure */
  png_read_update_info (pngdec->png, pngdec->info);

  /* Get IHDR header again after transformation settings */
  png_get_IHDR (pngdec->png, pngdec->info, &width, &height,
      &bpc, &pngdec->color_type, NULL, NULL, NULL);

  GST_LOG_OBJECT (pngdec, "this is a %dx%d PNG image", (gint) width,
      (gint) height);

  switch (pngdec->color_type) {
    case PNG_COLOR_TYPE_RGB:
      GST_LOG_OBJECT (pngdec, "we have no alpha channel, depth is 24 bits");
      if (bpc == 8)
        format = GST_VIDEO_FORMAT_RGB;
      break;
    case PNG_COLOR_TYPE_RGB_ALPHA:
      GST_LOG_OBJECT (pngdec,
          "we have an alpha channel, depth is 32 or 64 bits");
      if (bpc == 8)
        format = GST_VIDEO_FORMAT_RGBA;
      else if (bpc == 16)
        format = GST_VIDEO_FORMAT_ARGB64;
      break;
    case PNG_COLOR_TYPE_GRAY:
      GST_LOG_OBJECT (pngdec,
          "We have an gray image, depth is 8 or 16 (be) bits");
      if (bpc == 8)
        format = GST_VIDEO_FORMAT_GRAY8;
      else if (bpc == 16)
        format = GST_VIDEO_FORMAT_GRAY16_BE;
      break;
    default:
      break;
  }

  if (format == GST_VIDEO_FORMAT_UNKNOWN) {
    GST_ELEMENT_ERROR (pngdec, STREAM, NOT_IMPLEMENTED, (NULL),
        ("pngdec does not support this color type"));
    ret = GST_FLOW_NOT_SUPPORTED;
    goto beach;
  }

  /* Check if output state changed */
  if (pngdec->output_state) {
    GstVideoInfo *info = &pngdec->output_state->info;

    if (width == GST_VIDEO_INFO_WIDTH (info) &&
        height == GST_VIDEO_INFO_HEIGHT (info) &&
        GST_VIDEO_INFO_FORMAT (info) == format) {
      goto beach;
    }
    gst_video_codec_state_unref (pngdec->output_state);
  }

  pngdec->output_state =
      gst_video_decoder_set_output_state (GST_VIDEO_DECODER (pngdec), format,
      width, height, pngdec->input_state);
  gst_video_decoder_negotiate (GST_VIDEO_DECODER (pngdec));
  GST_DEBUG ("Final %d %d", GST_VIDEO_INFO_WIDTH (&pngdec->output_state->info),
      GST_VIDEO_INFO_HEIGHT (&pngdec->output_state->info));

beach:
  return ret;
}
unsigned char* PPGame_LoadPNG(const char* fileName,unsigned long* imageWidth,unsigned long* imageHeight,unsigned long* bytesPerRow)
{

	FILE *PNG_file = fopen(fileName, "rb");

//    fprintf(stderr, "open PNG file %s\n", fileName);

    if (PNG_file == NULL)
    {
        fprintf(stderr, "Can't open PNG file %s\n", fileName);
		return NULL;
    }
    
    unsigned char PNG_header[PNG_HEADER_SIZE];
    
    fread(PNG_header, 1, PNG_HEADER_SIZE, PNG_file);
    if (png_sig_cmp(PNG_header, 0, PNG_HEADER_SIZE) != 0)
    {
        fprintf(stderr, "%s is not a PNG file\n", fileName);
        fclose(PNG_file);
		return NULL;
    }
/*	
	{
		for (int i=0;i<8;i++) {
			printf("%02X,",PNG_header[i]);
		}
		printf("\n");
	}
*/
    png_structp PNG_reader = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (PNG_reader == NULL)
    {
        fprintf(stderr, "Can't start reading PNG file %s\n", fileName);
        fclose(PNG_file);
		return NULL;
    }

    png_infop PNG_info = png_create_info_struct(PNG_reader);
    if (PNG_info == NULL)
    {
        fprintf(stderr, "Can't get info for PNG file %s\n", fileName);
        png_destroy_read_struct(&PNG_reader, NULL, NULL);
        fclose(PNG_file);
		return NULL;
    }

    png_infop PNG_end_info = png_create_info_struct(PNG_reader);
    if (PNG_end_info == NULL)
    {
        fprintf(stderr, "Can't get end info for PNG file %s\n", fileName);
        png_destroy_read_struct(&PNG_reader, &PNG_info, NULL);
        fclose(PNG_file);
		return NULL;
    }
    
    if (setjmp(png_jmpbuf(PNG_reader)))
    {
        fprintf(stderr, "Can't load PNG file %s\n", fileName);
        png_destroy_read_struct(&PNG_reader, &PNG_info, &PNG_end_info);
        fclose(PNG_file);
		return NULL;
    }
    
    png_init_io(PNG_reader, PNG_file);
    png_set_sig_bytes(PNG_reader, PNG_HEADER_SIZE);
    
    png_read_info(PNG_reader, PNG_info);

	if (PNG_reader == NULL) {
        fclose(PNG_file);
		return NULL;
    }
    
    png_uint_32 width, height;
    width = png_get_image_width(PNG_reader, PNG_info);
    height = png_get_image_height(PNG_reader, PNG_info);

//printf("width %d\n",width);
//printf("height %d\n",height);
    
    png_uint_32 bit_depth, color_type;
    bit_depth = png_get_bit_depth(PNG_reader, PNG_info);
    color_type = png_get_color_type(PNG_reader, PNG_info);

//printf("bit_depth %d\n",bit_depth);
//printf("rowbytes %d\n",png_get_rowbytes(PNG_reader, PNG_info));
    
    if (color_type == PNG_COLOR_TYPE_PALETTE)
    {
    //png_set_palette_to_rgb(PNG_reader);
    png_set_palette_to_rgb(PNG_reader);
    }
/*
    if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) 
    {
    png_set_gray_1_2_4_to_8(PNG_reader);
    }
*/
    if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
    {
    png_set_gray_to_rgb(PNG_reader);
    }
    if (png_get_valid(PNG_reader, PNG_info, PNG_INFO_tRNS))
    {
    png_set_tRNS_to_alpha(PNG_reader);
    }
    else
    {
    png_set_filler(PNG_reader, 0xff, PNG_FILLER_AFTER);
    }
    if (bit_depth == 16)
    {
        png_set_strip_16(PNG_reader);
    }
    
    png_read_update_info(PNG_reader, PNG_info);
    
    png_byte* PNG_image_buffer = (png_byte*)malloc(4 * width * height);
    png_byte** PNG_rows = (png_byte**)malloc(height * sizeof(png_byte*));
    
    unsigned int row;
    for (row = 0; row < height; ++row)
    {
        //PNG_rows[height - 1 - row] = PNG_image_buffer + (row * 4 * width);
        PNG_rows[row] = PNG_image_buffer + (row * 4 * width);
    }
    
    png_read_image(PNG_reader, PNG_rows);
    
    free(PNG_rows);
    
    png_destroy_read_struct(&PNG_reader, &PNG_info, &PNG_end_info);
    fclose(PNG_file);

    *imageWidth = width;
    *imageHeight = height;
	*bytesPerRow = width*4;

	return convert(PNG_image_buffer,width,height);
}
Пример #10
0
gavl_video_frame_t * read_png(const char * filename,
                              gavl_video_format_t * format,
                              gavl_pixelformat_t pixelformat)
  {
  int i;
  unsigned char ** rows;
  
  gavl_video_converter_t * cnv;
  gavl_video_options_t * opt;
  gavl_video_format_t format_1;
  gavl_video_frame_t * frame, * frame_1;
    
  int bit_depth;
  int color_type;
  int has_alpha = 0;

  png_structp png_ptr;
  png_infop info_ptr;
  png_infop end_info;

  FILE * file;
  
  file = fopen(filename, "rb");

  if(!file)
    {
    fprintf(stderr, "Cannot open file %s\n", filename);
    return NULL;
    }
  
  png_ptr = png_create_read_struct
    (PNG_LIBPNG_VER_STRING, NULL,
     NULL, NULL);
  
  setjmp(png_jmpbuf(png_ptr));
  info_ptr = png_create_info_struct(png_ptr);


  end_info = png_create_info_struct(png_ptr);

  png_init_io(png_ptr, file);

  png_read_info(png_ptr, info_ptr);

  format->frame_width  = png_get_image_width(png_ptr, info_ptr);
  format->frame_height = png_get_image_height(png_ptr, info_ptr);

  format->image_width  = format->frame_width;
  format->image_height = format->frame_height;
  format->pixel_width = 1;
  format->pixel_height = 1;

  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:       /*  (bit depths 1, 2, 4, 8, 16) */
      if(bit_depth < 8)
#if GAVL_MAKE_BUILD(PNG_LIBPNG_VER_MAJOR, PNG_LIBPNG_VER_MINOR, PNG_LIBPNG_VER_RELEASE) < GAVL_MAKE_BUILD(1,2,9)
        png_set_gray_1_2_4_to_8(png_ptr);
#else
      png_set_expand_gray_1_2_4_to_8(png_ptr);
#endif
      if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
        {
        png_set_tRNS_to_alpha(png_ptr);
        has_alpha = 1;
        }
      png_set_gray_to_rgb(png_ptr);
      break;
    case PNG_COLOR_TYPE_GRAY_ALPHA: /*  (bit depths 8, 16) */
      if(bit_depth == 16)
        png_set_strip_16(png_ptr);
      png_set_gray_to_rgb(png_ptr);
      break;
    case PNG_COLOR_TYPE_PALETTE:    /*  (bit depths 1, 2, 4, 8) */
      png_set_palette_to_rgb(png_ptr);
      if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
        {
        png_set_tRNS_to_alpha(png_ptr);
        has_alpha = 1;
        }
      break;
    case PNG_COLOR_TYPE_RGB:        /*  (bit_depths 8, 16) */
      if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
        {
        png_set_tRNS_to_alpha(png_ptr);
        has_alpha = 1;
        }
      if(bit_depth == 16)
        png_set_strip_16(png_ptr);
      break;
    case PNG_COLOR_TYPE_RGB_ALPHA:  /*  (bit_depths 8, 16) */
      if(bit_depth == 16)
        png_set_strip_16(png_ptr);
      has_alpha = 1;
      break;
    }
  if(has_alpha)
    format->pixelformat = GAVL_RGBA_32;
  else
    format->pixelformat = GAVL_RGB_24;

  frame = gavl_video_frame_create(format);
  rows = malloc(format->frame_height * sizeof(*rows));
  for(i = 0; i < format->frame_height; i++)
    rows[i] = frame->planes[0] + i * frame->strides[0];

  png_read_image(png_ptr, rows);
  png_read_end(png_ptr, end_info);

  png_destroy_read_struct(&png_ptr, &info_ptr,
                          &end_info);
  fclose(file);
  free(rows);
  
  /* Check wether to set up the converter */

  if(format->pixelformat != pixelformat)
    {
    cnv = gavl_video_converter_create();
    opt = gavl_video_converter_get_options(cnv);
    gavl_video_options_set_alpha_mode(opt, GAVL_ALPHA_BLEND_COLOR);    

    gavl_video_format_copy(&format_1, format);
    format_1.pixelformat = pixelformat;
    frame_1 = gavl_video_frame_create(&format_1);
    
    gavl_video_converter_init(cnv, format, &format_1);
    
    gavl_video_convert(cnv, frame, frame_1);
    gavl_video_converter_destroy(cnv);
    format->pixelformat = pixelformat;
    }
  else
    frame_1 = NULL;

  if(frame_1)
    {
    gavl_video_frame_destroy(frame);
    return frame_1;
    }
  else
    return frame;
  }
void readPngFile(char* file_name)
{
    //printf("%s\n", file_name);
    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){
        printf("Unable to open file '%s'\n", file_name);
        exit(-1);
        //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 */
    pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    
    if (!pngPtr)
        abort_("[read_png_file] png_create_read_struct failed");
    
    infoPtr = png_create_info_struct(pngPtr);
    if (!infoPtr)
        abort_("[read_png_file] png_create_info_struct failed");
    
    if (setjmp(png_jmpbuf(pngPtr)))
        abort_("[read_png_file] Error during init_io");
    
    png_init_io(pngPtr, fp);
    png_set_sig_bytes(pngPtr, 8);
    
    png_read_info(pngPtr, infoPtr);
    
    imageWidth = png_get_image_width(pngPtr, infoPtr);
    imageLength = png_get_image_height(pngPtr, infoPtr);
    config = png_get_color_type(pngPtr, infoPtr);
    bitsPerSample = png_get_bit_depth(pngPtr, infoPtr); // = 8 bits
        
    numberOfPasses = png_set_interlace_handling(pngPtr);
    png_read_update_info(pngPtr, infoPtr);
    
    imageWidth = png_get_image_width(pngPtr, infoPtr);
    imageLength = png_get_image_height(pngPtr, infoPtr);

    samplesPerPixel = png_get_channels(pngPtr, infoPtr); // = 4 bytes

    bitsPerPixel = samplesPerPixel*bitsPerSample;
    linebytes = samplesPerPixel * imageWidth; // = 640
    //linebytes = png_get_rowbytes(pngPtr, infoPtr); = 640
    imageBitSize = (sizeof(uint8) * imageWidth * imageLength * samplesPerPixel);
    imageSize = imageWidth * imageLength * samplesPerPixel;
    //printf("linebytes = %i, expected %i\n",linebytes,png_get_rowbytes(pngPtr, infoPtr));
    //printf("Image Height is %d", sizeof(png_bytep) * imageLength);

    
    /* read file */
    if (setjmp(png_jmpbuf(pngPtr)))
        abort_("[read_png_file] Error during read_image");
    
    rowPointers = (png_bytep*) malloc(sizeof(png_bytep) * imageLength);
    for (y=0; y<imageLength; y++)
        rowPointers[y] = (png_byte*) malloc(png_get_rowbytes(pngPtr,infoPtr));
    
    png_read_image(pngPtr, rowPointers);
    
    fclose(fp);
}
Пример #12
0
// ref: http://zarb.org/~gc/html/libpng.html
bool read_image_from_png_file(const char *filepath, image_t &image) {
  FILE *fp = fopen(filepath, "rb");
  if (!fp) {
    log("[read_png_file] File %s could not be opened for reading", filepath);
		return false;
	}

  unsigned char header[8]; 
  fread(header, 1, 8, fp);
  if (png_sig_cmp(header, 0, 8)) {
    log("[read_png_file] File %s is not recognized as a PNG file", filepath);
		return false;
	}

  png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (!png_ptr) {
    log("[read_png_file] png_create_read_struct failed");
		return false;
	}

  png_infop info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr) {
    log("[read_png_file] png_create_info_struct failed");
		return false;
	}

  if (setjmp(png_jmpbuf(png_ptr))) {
    log("[read_png_file] Error during init_io");
		return false;
	}

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

  png_read_info(png_ptr, info_ptr);

  int width = png_get_image_width(png_ptr, info_ptr);
  int 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);

  png_set_interlace_handling(png_ptr);
  png_read_update_info(png_ptr, info_ptr);

  if (setjmp(png_jmpbuf(png_ptr))) {
    log("[read_png_file] Error during read_image");
		return false;
	}

	png_byte byte_depth = png_get_channels(png_ptr, info_ptr);
	if (bit_depth == 16)
		byte_depth *= 2;

	png_byte *buf = new png_byte[width * height * byte_depth];

	int offset = 0;
  for (int y = 0; y < height; y++) {
		png_read_row(png_ptr, buf + offset, NULL);
		offset += width * byte_depth;
	}

	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
	
  fclose(fp);

	image.width = width;
	image.height = height;
	image.byte_depth = byte_depth;
	image.data = (unsigned char *)buf;

  switch (color_type) {
  case PNG_COLOR_TYPE_GRAY:
		image.format = GL_LUMINANCE;
    break;
  case PNG_COLOR_TYPE_RGB:
		image.format = GL_RGB;
    break;
  case PNG_COLOR_TYPE_RGBA:
		image.format = GL_RGBA;
    break;
  case PNG_COLOR_TYPE_GA:
		image.format = GL_LUMINANCE_ALPHA;
    break;
  default:
    log("Non-support color type");
		return false;
  }

	return true;
}
Пример #13
0
/*
 * Function    : libaroma_png_ex
 * Return Value: LIBAROMA_CANVASP
 * Descriptions: read png - extended
 */
LIBAROMA_CANVASP libaroma_png_ex(
    LIBAROMA_STREAMP stream, 
    byte freeStream, 
    byte hicolor) {
  if (!stream) {
    return NULL;
  }
  /* init adapter */
  _LIBAROMA_PNG_ADAPTERP adapter = (_LIBAROMA_PNG_ADAPTERP)
    malloc(sizeof(_LIBAROMA_PNG_ADAPTER));
  if (!adapter) {
    if (freeStream){
      libaroma_stream_close(stream);
    }
    ALOGW("libaroma_png_ex cannot allocating adapter");
    return NULL;
  }
  adapter->data = stream->data;
  adapter->n    = stream->size;
  adapter->p    = 0;
  
  /* png structures */
  png_structp png_ptr = NULL;
  png_infop info_ptr  = NULL;
  volatile LIBAROMA_CANVASP cv = NULL;
  byte header[8];
  
  /* headers */
  memcpy(header, adapter->data, sizeof(header));
  adapter->p += sizeof(header);
  
  /* compare signature */
  if (png_sig_cmp(header, 0, sizeof(header))) {
    ALOGW("libaroma_png_ex signature error");
    goto exit;
  }
  
  /* read structure */
  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  
  if (!png_ptr) {
    ALOGW("libaroma_png_ex png_ptr is invalid");
    goto exit;
  }
  
  /* info structure */
  info_ptr = png_create_info_struct(png_ptr);
  
  if (!info_ptr) {
    ALOGW("libaroma_png_ex info_ptr is invalid");
    goto exit;
  }
  
  /* jmp */
  if (setjmp(png_jmpbuf(png_ptr))) {
    ALOGW("libaroma_png_ex jmp error");
    goto exit;
  }
  
  /* callback */
  png_set_read_fn(png_ptr, adapter, _libaroma_png_reader);
  png_set_sig_bytes(png_ptr, sizeof(header));
  png_read_info(png_ptr, info_ptr);
  
  /* check color */
  int bit_depth  = png_get_bit_depth(png_ptr, info_ptr);
  int color_type = png_get_color_type(png_ptr, info_ptr);
  int channels   = png_get_channels(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);
    png_read_update_info(png_ptr, info_ptr);
  }
  else if (color_type == PNG_COLOR_TYPE_PALETTE) {
    png_set_palette_to_rgb(png_ptr);
    png_read_update_info(png_ptr, info_ptr);
  }
  else 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)
       )) {
    ALOGW("libaroma_png_ex mode not supported (c:%i, t:%i, d:%i)",
          channels, color_type, bit_depth);
    goto exit;
  }
  
  /* init main info */
  int pcv_w    = png_get_image_width(png_ptr, info_ptr);
  int pcv_h    = png_get_image_height(png_ptr, info_ptr);
  int pcv_c    = png_get_channels(png_ptr, info_ptr);
  
  /* verbose */
  ALOGV("load png \"%s\" (%ix%ix%i)",
    stream->uri, pcv_w, pcv_h, pcv_c);

  /* new canvas */
  cv = libaroma_canvas_new(
      pcv_w, pcv_h, (pcv_c==4)?1:0, hicolor);
  
  if (!cv) {
    ALOGW("libaroma_png_ex cannot create canvas");
    goto exit;
  }
  
  /* switch to abgr */
  if (pcv_c == 4) {
    png_set_bgr(png_ptr);
  }
  
  /* read row size*/
  int row_sz = (int) png_get_rowbytes(png_ptr, info_ptr);
  
  /* loop */
  int y, x;
  if (pcv_c == 4) {
    int z;
    png_bytep row_data  = (png_bytep) malloc(row_sz);
    if (hicolor) {
      for (y = 0; y < pcv_h; ++y) {
        int   ypos = (y * cv->l);
        wordp line = cv->data + ypos;
        bytep alph = cv->alpha + ypos;
        bytep hicl = cv->hicolor + ypos;
        png_read_row(png_ptr, row_data, NULL);
        for (x = 0, z = pcv_w * pcv_c; x < z; x += 4) {
          *line++ = libaroma_rgb(
            row_data[x + 2],
            row_data[x + 1],
            row_data[x]);
          *hicl++ = libaroma_color_left(
            row_data[x + 2],
            row_data[x + 1],
            row_data[x]);
          *alph++ = row_data[x + 3];
        }
      }
    }
    else {
      for (y = 0; y < pcv_h; ++y) {
        int   ypos = (y * cv->l);
        wordp line = cv->data + ypos;
        bytep alph = cv->alpha + ypos;
        png_read_row(png_ptr, row_data, NULL);
        libaroma_dither_line(y, pcv_w, line, (dwordp) row_data);
        for (x = 0, z = pcv_w * pcv_c; x < z; x += 4) {
          *alph++ = row_data[x + 3];
        }
      }
    }
    free(row_data);
  }
  else if (pcv_c == 3) {
    int z;
    png_bytep row_data  = (png_bytep) malloc(row_sz);
    if (hicolor) {
      for (y = 0; y < pcv_h; ++y) {
        wordp line = cv->data + (y * cv->l);
        bytep hicl = cv->hicolor + (y * cv->l);
        png_read_row(png_ptr, row_data, NULL);
        for (x = 0, z = pcv_w * pcv_c; x < z; x += 3) {
          *line++ = libaroma_rgb(row_data[x], row_data[x + 1], row_data[x + 2]);
          *hicl++ = libaroma_color_left(
              row_data[x + 2],
              row_data[x + 1],
              row_data[x]);
        }
      }
    }
    else {
      for (y = 0; y < pcv_h; ++y) {
        wordp line = cv->data + (y * cv->l);
        png_read_row(png_ptr, row_data, NULL);
        libaroma_dither_24to16(y, pcv_w, line, row_data);
        /*
        for (x = 0, z = pcv_w * pcv_c; x < z; x += 3) {
          *line++ = libaroma_dither_rgb(
            x, y, row_data[x + 2], row_data[x + 1], row_data[x]);
        }*/
      }
    }
    free(row_data);
  }
exit:
  png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
  if (freeStream) {
    libaroma_stream_close(stream);
  }
  free(adapter);
  return cv;
} /* End of libaroma_png_ex */
Пример #14
0
image_t* imagelib_load_png_from_mem( char* buffer, size_t size, const imageloadersettings_t settings )
{
    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
    if ( !png_ptr ) {
        return NULL;
    }

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

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

    png_memory_buffer membuffer = {
        .data = buffer,
        .size = size,
        .offset = 0
    };

    //png_init_io(png_ptr,fp);
    png_set_read_fn(png_ptr,&membuffer,png_read_data);
    png_set_sig_bytes(png_ptr,0);


    int png_transforms = PNG_TRANSFORM_STRIP_16|PNG_TRANSFORM_SWAP_ENDIAN|PNG_TRANSFORM_PACKING|PNG_TRANSFORM_EXPAND|(settings.swaprb?PNG_TRANSFORM_BGR:0);
    png_read_png(png_ptr, info, png_transforms, NULL);


    int rowbytes = png_get_rowbytes(png_ptr, info);
    int width = png_get_image_width(png_ptr, info);
    int height = png_get_image_height(png_ptr, info);
    int bit_depth = png_get_bit_depth(png_ptr, info);
    int color_type = png_get_color_type(png_ptr, info);

    // convert bit_depth + color_type to image format

    int bytepp = 0;
    if ( bit_depth==8 )
    {
        switch( color_type )
        {
            case PNG_COLOR_TYPE_GRAY: bytepp = 1; break;
            case PNG_COLOR_TYPE_GRAY_ALPHA: bytepp = 2; break;
            case PNG_COLOR_TYPE_RGB: bytepp = 3; break;
            case PNG_COLOR_TYPE_RGBA: bytepp = 4; break;
        }
    }

    if ( bytepp==0 ) {
        png_destroy_read_struct(&png_ptr, &info, NULL);
        return NULL;
    }

    int forcergba = settings.forcergba && color_type!=PNG_COLOR_TYPE_RGBA;


    image_t* image = malloc(sizeof(image_t));
    image->data = malloc(sizeof(unsigned char)*width*height*(forcergba?4:bytepp));
    image->width = width;
    image->height = height;
    image->bpp = bytepp;

    int stride = width*(forcergba?4:bytepp);


    png_bytepp row_pointers = png_get_rows(png_ptr, info);

    int x,y;

    if (!forcergba) {
        if (settings.swapy) {
            for ( y=0; y<image->height; y++ )
                memcpy(image->data+stride*(image->height-1-y), row_pointers[y], rowbytes);
        }
        else {
            for ( y=0; y<image->height; y++ )
                memcpy(image->data+stride*y, row_pointers[y], rowbytes);
        }
    } else {

        if (color_type==PNG_COLOR_TYPE_RGB) {
            for ( y=0;y<image->height;y++ ) {
                unsigned char* src = row_pointers[y];
                unsigned char* trg = image->data+stride*y;
                for ( x=0; x<image->width; x++ ) {
                    int tx = x*4;
                    int sx = x*bytepp;
                    trg[tx+0] = src[sx+0];
                    trg[tx+1] = src[sx+1];
                    trg[tx+2] = src[sx+2];
                    trg[tx+3] = settings.alpha;
                }
            }
        }
        else
        if (color_type==PNG_COLOR_TYPE_GRAY) {
            for ( y=0;y<image->height;y++ ) {
                unsigned char* src = row_pointers[y];
                unsigned char* trg = image->data+stride*y;
                for ( x=0; x<image->width; x++ ) {
                    int tx = x*4;
                    int sx = x*bytepp;
                    trg[tx+0] = src[sx];
                    trg[tx+1] = src[sx];
                    trg[tx+2] = src[sx];
                    trg[tx+3] = settings.alpha;
                }
            }
        }
        else
        if (color_type==PNG_COLOR_TYPE_GRAY_ALPHA) {
            for ( y=0;y<image->height;y++ ) {
                unsigned char* src = row_pointers[y];
                unsigned char* trg = image->data+stride*y;
                for ( x=0; x<image->width; x++ ) {
                    int tx = x*4;
                    int sx = x*bytepp;
                    trg[tx+0] = src[sx];
                    trg[tx+1] = src[sx];
                    trg[tx+2] = src[sx];
                    trg[tx+3] = src[sx+1];
                }
            }
        }
    }

    png_destroy_read_struct(&png_ptr, &info, NULL);

    return image;
}
Пример #15
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;
	png_uint_32 width, height;
	png_colorp png_palette = NULL;
	int color_type, palette_entries = 0;
	int bit_depth, pixel_depth;		// pixel_depth = bit_depth * channels

	FIBITMAP *dib = NULL;
	RGBQUAD *palette = NULL;		// pointer to dib palette
	png_bytepp  row_pointers = NULL;
	int i;

    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);

			pixel_depth = png_get_bit_depth(png_ptr, info_ptr) * png_get_channels(png_ptr, info_ptr);

			// get image data type (assume standard image type)

			FREE_IMAGE_TYPE image_type = FIT_BITMAP;
			if (bit_depth == 16) {
				if ((pixel_depth == 16) && (color_type == PNG_COLOR_TYPE_GRAY)) {
					image_type = FIT_UINT16;
				} 
				else if ((pixel_depth == 48) && (color_type == PNG_COLOR_TYPE_RGB)) {
					image_type = FIT_RGB16;
				} 
				else if ((pixel_depth == 64) && (color_type == PNG_COLOR_TYPE_RGB_ALPHA)) {
					image_type = FIT_RGBA16;
				} else {
					// tell libpng to strip 16 bit/color files down to 8 bits/color
					png_set_strip_16(png_ptr);
					bit_depth = 8;
				}
			}

#ifndef FREEIMAGE_BIGENDIAN
			if((image_type == FIT_UINT16) || (image_type == FIT_RGB16) || (image_type == FIT_RGBA16)) {
				// turn on 16 bit byte swapping
				png_set_swap(png_ptr);
			}
#endif						

			// set some additional flags

			switch(color_type) {
				case PNG_COLOR_TYPE_RGB:
				case PNG_COLOR_TYPE_RGB_ALPHA:
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
					// flip the RGB pixels to BGR (or RGBA to BGRA)

					if(image_type == FIT_BITMAP) {
						png_set_bgr(png_ptr);
					}
#endif
					break;

				case PNG_COLOR_TYPE_PALETTE:
					// expand palette images to the full 8 bits from 2 bits/pixel

					if (pixel_depth == 2) {
						png_set_packing(png_ptr);
						pixel_depth = 8;
					}					

					break;

				case PNG_COLOR_TYPE_GRAY:
					// expand grayscale images to the full 8 bits from 2 bits/pixel
					// but *do not* expand fully transparent palette entries to a full alpha channel

					if (pixel_depth == 2) {
						png_set_expand_gray_1_2_4_to_8(png_ptr);
						pixel_depth = 8;
					}

					break;

				case PNG_COLOR_TYPE_GRAY_ALPHA:
					// expand 8-bit greyscale + 8-bit alpha to 32-bit

					png_set_gray_to_rgb(png_ptr);
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
					// flip the RGBA pixels to BGRA

					png_set_bgr(png_ptr);
#endif
					pixel_depth = 32;

					break;

				default:
					throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
			}

			// unlike the example in the libpng documentation, we have *no* idea where
			// this file may have come from--so if it doesn't have a file gamma, don't
			// do any correction ("do no harm")

			if (png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA)) {
				double gamma = 0;
				double screen_gamma = 2.2;

				if (png_get_gAMA(png_ptr, info_ptr, &gamma) && ( flags & PNG_IGNOREGAMMA ) != PNG_IGNOREGAMMA) {
					png_set_gamma(png_ptr, screen_gamma, gamma);
				}
			}

			// all transformations have been registered; now update info_ptr data

			png_read_update_info(png_ptr, info_ptr);

			// color type may have changed, due to our transformations

			color_type = png_get_color_type(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:
					png_set_invert_alpha(png_ptr);

					if(image_type == FIT_BITMAP) {
						dib = FreeImage_AllocateHeader(header_only, width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
					} else {
						dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth);
					}
					break;

				case PNG_COLOR_TYPE_RGB_ALPHA:
					if(image_type == FIT_BITMAP) {
						dib = FreeImage_AllocateHeader(header_only, width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
					} else {
						dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth);
					}
					break;

				case PNG_COLOR_TYPE_PALETTE:
					dib = FreeImage_AllocateHeader(header_only, width, height, pixel_depth);

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

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

					// store the palette

					for (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);

					if(pixel_depth <= 8) {
						palette = FreeImage_GetPalette(dib);
						palette_entries = 1 << pixel_depth;

						for (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;
			}

			// 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 < palette_entries) { 
						BYTE table[256]; 
						memset(table, 0xFF, palette_entries); 
						table[trans_color->gray] = 0; 
						FreeImage_SetTransparencyTable(dib, table, palette_entries); 
					}
				} else if((color_type == PNG_COLOR_TYPE_PALETTE) && trans_alpha) {
					// transparency table
					FreeImage_SetTransparencyTable(dib, (BYTE *)trans_alpha, num_trans);
				}
			}

			// store the background color 

			if (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;
}
unsigned char* PPGame_DecodePNG(unsigned char* bytes,unsigned long size,unsigned long* imageWidth,unsigned long* imageHeight,unsigned long* bytesPerRow)
{
	if (bytes == NULL || size == 0) return NULL;
	my_png_buffer png_buff;
	memset(&png_buff,0,sizeof(png_buff));
	png_buff.data_len = size;
	png_buff.data = bytes;
	int is_png = png_check_sig((png_bytep)png_buff.data, 8);
	if (!is_png) {
		fprintf(stderr, "is not PNG!\n");
		free(png_buff.data);
		return NULL;
	}
	png_structp PNG_reader = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,NULL,NULL);
	if (!PNG_reader) {
		fprintf(stderr, "can't create read_struct\n");
		free(png_buff.data);
		return NULL;
	}
	png_infop PNG_info = png_create_info_struct(PNG_reader);
	if (!PNG_info) {
		fprintf(stderr, "can't create info_struct\n");
		png_destroy_read_struct (&PNG_reader, NULL, NULL);
		free(png_buff.data);
		return NULL;
	}

    png_infop PNG_end_info = png_create_info_struct(PNG_reader);
    if (PNG_end_info == NULL)
    {
        fprintf(stderr, "Can't get end info for PNG data\n");
        png_destroy_read_struct(&PNG_reader, &PNG_info, NULL);
		free(png_buff.data);
		return NULL;
    }
    
    if (setjmp(png_jmpbuf(PNG_reader)))
    {
        fprintf(stderr, "Can't decode PNG data\n");
        png_destroy_read_struct(&PNG_reader, &PNG_info, &PNG_end_info);
		free(png_buff.data);
		return NULL;
    }

	png_data_read(PNG_reader,&png_buff);
	png_read_info(PNG_reader,PNG_info);
	
    png_uint_32 width, height;
    width = png_get_image_width(PNG_reader, PNG_info);
    height = png_get_image_height(PNG_reader, PNG_info);

//printf("width %ld\n",width);
//printf("height %ld\n",height);
    
    png_uint_32 bit_depth, color_type;
    bit_depth = png_get_bit_depth(PNG_reader, PNG_info);
    color_type = png_get_color_type(PNG_reader, PNG_info);

//printf("bit_depth %ld\n",bit_depth);
//printf("rowbytes %ld\n",png_get_rowbytes(PNG_reader, PNG_info));

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

    if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
    {
    png_set_gray_to_rgb(PNG_reader);
    }
    if (png_get_valid(PNG_reader, PNG_info, PNG_INFO_tRNS))
    {
    png_set_tRNS_to_alpha(PNG_reader);
    }
    else
    {
    png_set_filler(PNG_reader, 0xff, PNG_FILLER_AFTER);
    }
    if (bit_depth == 16)
    {
        png_set_strip_16(PNG_reader);
    }
    
    png_read_update_info(PNG_reader, PNG_info);
    
    png_byte* PNG_image_buffer = (png_byte*)malloc(4 * width * height);
    png_byte** PNG_rows = (png_byte**)malloc(height * sizeof(png_byte*));
    
    unsigned int row;
    for (row = 0; row < height; ++row)
    {
        //PNG_rows[height - 1 - row] = PNG_image_buffer + (row * 4 * width);
        PNG_rows[row] = PNG_image_buffer + (row * 4 * width);
    }
    
    png_read_image(PNG_reader, PNG_rows);
    
    free(PNG_rows);
    
    png_destroy_read_struct(&PNG_reader, &PNG_info, &PNG_end_info);

	if (png_buff.data) free(png_buff.data);

    *imageWidth = width;
    *imageHeight = height;
	*bytesPerRow = width*4;

	return convert(PNG_image_buffer,width,height);
}
Пример #17
0
int
main(int argc, char **argv)
{
    static char *usage="Usage:\n\t%s png__file\n";

    int i;
    FILE *fp_in = NULL;
    png_structp png_p;
    png_infop info_p;
    char header[8];
    int bit_depth;
    int color_type;
    png_color_16p input_backgrd;
    double gammaval;
    int file_width, file_height;
    png_int_32 xoff, yoff;
    png_uint_32 xres, yres;
    int unit_type;
    int rgb_intent;
    double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
    png_timep mod_time;
    png_textp text;
    int num_text;
    unsigned char *image;
    unsigned char **rows;

    if (argc != 2) {
	bu_log(usage, argv[0]);
	bu_exit(EXIT_FAILURE, "Incorrect number of arguments!!\n");
    } else {
	if ((fp_in = fopen(argv[1], "rb")) == NULL) {
	    perror(argv[1]);
	    bu_log("png_onfo: cannot open \"%s\" for reading\n",
		   argv[1]);
	    bu_exit(EXIT_FAILURE, "Cannot open input file\n");
	}
    }

    if (fread(header, 8, 1, fp_in) != 1)
	bu_exit(EXIT_FAILURE, "ERROR: Failed while reading file header!!!\n");

    if (png_sig_cmp((png_bytep)header, 0, 8))
	bu_exit(EXIT_FAILURE, "This is not a PNG file!!!\n");

    png_p = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_p)
	bu_exit(EXIT_FAILURE, "png_create_read_struct() failed!!\n");

    info_p = png_create_info_struct(png_p);
    if (!info_p)
	bu_exit(EXIT_FAILURE, "png_create_info_struct() failed!!\n");

    png_init_io(png_p, fp_in);

    png_set_sig_bytes(png_p, 8);

    png_read_info(png_p, info_p);

    color_type = png_get_color_type(png_p, info_p);

    bit_depth = png_get_bit_depth(png_p, info_p);

    switch (color_type) {
	case PNG_COLOR_TYPE_GRAY:
	    bu_log("color type: b/w (bit depth=%d)\n", bit_depth);
	    break;
	case PNG_COLOR_TYPE_GRAY_ALPHA:
	    bu_log("color type: b/w with alpha channel (bit depth=%d)\n", bit_depth);
	    break;
	case PNG_COLOR_TYPE_PALETTE:
	    bu_log("color type: color palette (bit depth=%d)\n", bit_depth);
	    break;
	case PNG_COLOR_TYPE_RGB:
	    bu_log("color type: RGB (bit depth=%d)\n", bit_depth);
	    break;
	case PNG_COLOR_TYPE_RGB_ALPHA:
	    bu_log("color type: RGB with alpha channel (bit depth=%d)\n", bit_depth);
	    break;
	default:
	    bu_log("Unrecognized color type (bit depth=%d)\n", bit_depth);
	    break;
    }

    file_width = png_get_image_width(png_p, info_p);
    file_height = png_get_image_height(png_p, info_p);

    bu_log("Image size: %d X %d\n", file_width, file_height);

    /* allocate memory for image */
    image = (unsigned char *)bu_calloc(1, file_width*file_height*3, "image");

    /* create rows array */
    rows = (unsigned char **)bu_calloc(file_height, sizeof(unsigned char *), "rows");
    for (i=0; i<file_height; i++)
	rows[file_height-1-i] = image+(i*file_width*3);

    png_read_image(png_p, rows);

    if (png_get_oFFs(png_p, info_p, &xoff, &yoff, &unit_type)) {
	if (unit_type == PNG_OFFSET_PIXEL)
	    bu_log("X Offset: %d pixels\nY Offset: %d pixels\n", (int)xoff, (int)yoff);
	else if (unit_type == PNG_OFFSET_MICROMETER)
	    bu_log("X Offset: %d um\nY Offset: %d um\n", (int)xoff, (int)yoff);
    }

    if (png_get_pHYs(png_p, info_p, &xres, &yres, &unit_type)) {
	if (unit_type == PNG_RESOLUTION_UNKNOWN)
	    bu_log("Aspect ratio: %g (width/height)\n", (double)xres/(double)yres);
	else if (unit_type == PNG_RESOLUTION_METER)
	    bu_log("pixel density:\n\t%d pixels/m horizontal\n\t%d pixels/m vertical\n",
		   (int)xres, (int)yres);
    }

    if (png_get_interlace_type(png_p, info_p) == PNG_INTERLACE_NONE)
	bu_log("not interlaced\n");
    else
	bu_log("interlaced\n");

    if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
	color_type == PNG_COLOR_TYPE_RGB_ALPHA)
	if (png_get_bKGD(png_p, info_p, &input_backgrd))
	    bu_log("background color: %d %d %d\n", input_backgrd->red, input_backgrd->green, input_backgrd->blue);

    if (png_get_sRGB(png_p, info_p, &rgb_intent)) {
	bu_log("rendering intent: ");
	switch (rgb_intent) {
	    case PNG_sRGB_INTENT_SATURATION:
		bu_log("saturation\n");
		break;
	    case PNG_sRGB_INTENT_PERCEPTUAL:
		bu_log("perceptual\n");
		break;
	    case PNG_sRGB_INTENT_ABSOLUTE:
		bu_log("absolute\n");
		break;
	    case PNG_sRGB_INTENT_RELATIVE:
		bu_log("relative\n");
		break;
	}
    }

    if (png_get_gAMA(png_p, info_p, &gammaval))
	bu_log("gamma: %g\n", gammaval);

#if defined(PNG_READ_cHRM_SUPPORTED)
    if (png_get_cHRM(png_p, info_p, &white_x, &white_y, &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y)) {
	bu_log("Chromaticity:\n");
	bu_log("\twhite point\t(%g %g)\n\tred\t(%g %g)\n\tgreen\t(%g %g)\n\tblue\t(%g %g)\n",
	       white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
    }
#endif

    if (png_get_text(png_p, info_p, &text, &num_text))
	for (i=0; i<num_text; i++)
	    bu_log("%s: %s\n", text[i].key, text[i].text);

    if (png_get_tIME(png_p, info_p, &mod_time))
	bu_log("Last modified: %d/%d/%d %d:%d:%d\n", mod_time->month, mod_time->day,
	       mod_time->year, mod_time->hour, mod_time->minute, mod_time->second);
    return 0;
}
Пример #18
0
void
input_png_file(struct Options opts, struct PNGImage *img)
{
	FILE *f;
	int i, y, num_trans;
	bool has_palette = false;
	png_byte *trans_alpha;
	png_color_16 *trans_values;
	bool *full_alpha;
	png_color *palette;

	f = fopen(opts.infile, "rb");
	if (!f) {
		err(1, "Opening input png file '%s' failed", opts.infile);
	}

	img->png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!img->png) {
		errx(1, "Creating png structure failed");
	}

	img->info = png_create_info_struct(img->png);
	if (!img->info) {
		errx(1, "Creating png info structure failed");
	}

	/* Better error handling here? */
	if (setjmp(png_jmpbuf(img->png))) {
		exit(1);
	}

	png_init_io(img->png, f);

	png_read_info(img->png, img->info);

	img->width  = png_get_image_width(img->png, img->info);
	img->height = png_get_image_height(img->png, img->info);
	img->depth  = png_get_bit_depth(img->png, img->info);
	img->type   = png_get_color_type(img->png, img->info);

	if (img->type & PNG_COLOR_MASK_ALPHA) {
		png_set_strip_alpha(img->png);
	}

	if (img->depth != depth) {
		if (opts.verbose) {
			warnx("Image bit depth is not %i (is %i).", depth,
			    img->depth);
		}
	}

	if (img->type == PNG_COLOR_TYPE_GRAY) {
		if (img->depth < 8) {
			png_set_expand_gray_1_2_4_to_8(img->png);
		}
		png_set_gray_to_rgb(img->png);
	} else {
		if (img->depth < 8) {
			png_set_expand_gray_1_2_4_to_8(img->png);
		}
		has_palette = png_get_PLTE(img->png, img->info, &palette,
		    &colors);
	}

	if (png_get_tRNS(img->png, img->info, &trans_alpha, &num_trans,
	    &trans_values)) {
		if (img->type == PNG_COLOR_TYPE_PALETTE) {
			full_alpha = malloc(sizeof(bool) * num_trans);

			for (i = 0; i < num_trans; i++) {
				if (trans_alpha[i] > 0) {
					full_alpha[i] = false;
				} else {
					full_alpha[i] = true;
				}
			}

			for (i = 0; i < num_trans; i++) {
				if (full_alpha[i]) {
					palette[i].red   = 0xFF;
					palette[i].green = 0x00;
					palette[i].blue  = 0xFF;
					/*
					 * Set to the lightest color in the
					 * palette.
					 */
				}
			}

			free(full_alpha);
		} else {
			/* Set to the lightest color in the image. */
		}

		png_free_data(img->png, img->info, PNG_FREE_TRNS, -1);
	}

	if (has_palette) {
		/* Make sure palette only has the amount of colors you want. */
	} else {
		/*
		 * Eventually when this copies colors from the image itself,
		 * make sure order is lightest to darkest.
		 */
		palette = malloc(sizeof(png_color) * colors);

		if (strcmp(opts.infile, "rgb.png") == 0) {
			palette[0].red   = 0xFF;
			palette[0].green = 0xEF;
			palette[0].blue  = 0xFF;

			palette[1].red   = 0xF7;
			palette[1].green = 0xF7;
			palette[1].blue  = 0x8C;

			palette[2].red   = 0x94;
			palette[2].green = 0x94;
			palette[2].blue  = 0xC6;

			palette[3].red   = 0x39;
			palette[3].green = 0x39;
			palette[3].blue  = 0x84;
		} else {
			palette[0].red   = 0xFF;
			palette[0].green = 0xFF;
			palette[0].blue  = 0xFF;

			palette[1].red   = 0xA9;
			palette[1].green = 0xA9;
			palette[1].blue  = 0xA9;

			palette[2].red   = 0x55;
			palette[2].green = 0x55;
			palette[2].blue  = 0x55;

			palette[3].red   = 0x00;
			palette[3].green = 0x00;
			palette[3].blue  = 0x00;
		}
	}

	/*
	 * Also unfortunately, this sets it at 8 bit, and I can't find any
	 * option to reduce to 2 or 1 bit.
	 */
#if PNG_LIBPNG_VER < 10402
	png_set_dither(img->png, palette, colors, colors, NULL, 1);
#else
	png_set_quantize(img->png, palette, colors, colors, NULL, 1);
#endif

	if (!has_palette) {
		png_set_PLTE(img->png, img->info, palette, colors);
		free(palette);
	}

	/*
	 * If other useless chunks exist (sRGB, bKGD, pHYs, gAMA, cHRM, iCCP,
	 * etc.) offer to remove?
	 */

	png_read_update_info(img->png, img->info);

	img->data = malloc(sizeof(png_byte *) * img->height);
	for (y = 0; y < img->height; y++) {
		img->data[y] = malloc(png_get_rowbytes(img->png, img->info));
	}

	png_read_image(img->png, img->data);
	png_read_end(img->png, img->info);

	fclose(f);
}
Пример #19
0
//
// validate our input
//
static void s_PngReadValidate(png_structp png_ptr,
                              png_infop info_ptr,
                              size_t& width,
                              size_t& height,
                              size_t& depth,
                              size_t& x, size_t& y, size_t& w, size_t& h)
{
    // store and validate our image's parameters
    width        = png_get_image_width(png_ptr, info_ptr);
    height       = png_get_image_height(png_ptr, info_ptr);
    depth        = png_get_channels(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);

    // we support only RGB and RGBA images
    if ( color_type != PNG_COLOR_TYPE_RGB  &&
         color_type != PNG_COLOR_TYPE_RGB_ALPHA ) {
        string msg("CImageIOPng::ReadImage(): unhandled color type: ");
        msg += NStr::NumericToString((int)color_type);
        NCBI_THROW(CImageException, eReadError, msg);
    }

    // ...and only with a bit depth of 8
    if (bit_depth != 8) {
        string msg("CImageIOPng::ReadImage(): unhandled bit depth: ");
        msg += NStr::NumericToString((int)bit_depth);
        NCBI_THROW(CImageException, eReadError, msg);
    }

    // this goes along with RGB or RGBA
    if (depth != 3  &&  depth != 4) {
        string msg("CImageIOPng::ReadImage(): unhandled image channels: ");
        msg += NStr::NumericToString((int)depth);
        NCBI_THROW(CImageException, eReadError, msg);
    }

    if (x != (size_t)-1  &&  y != (size_t)-1  &&
        w != (size_t)-1  &&  h != (size_t)-1) {
        // further validation: make sure we're actually on the image
        if (x >= width  ||  y >= height) {
            string msg("CImageIOPng::ReadImage(): invalid starting position: ");
            msg += NStr::NumericToString(x);
            msg += ", ";
            msg += NStr::NumericToString(y);
            NCBI_THROW(CImageException, eReadError, msg);
        }

        // clamp our width and height to the image size
        if (x + w >= width) {
            w = width - x;
            LOG_POST_X(27, Warning
                     << "CImageIOPng::ReadImage(): clamped width to " << w);
        }

        if (y + h >= height) {
            h = height - y;
            LOG_POST_X(28, Warning
                     << "CImageIOPng::ReadImage(): clamped height to " << h);
        }
    }

    png_read_update_info(png_ptr, info_ptr);
}
Пример #20
0
    bool DecodePNG ( Image& aImage, size_t aBufferSize, const void* aBuffer )
    {
        if ( png_sig_cmp ( static_cast<uint8_t*> ( const_cast<void*> ( aBuffer ) ), 0, 8 ) != 0 )
        {
            return false;
        }
        try
        {
            png_structp png_ptr =
                png_create_read_struct ( PNG_LIBPNG_VER_STRING,
                                         nullptr, nullptr, nullptr );
            if ( png_ptr == nullptr )
            {
                throw std::runtime_error ( "png_create_read_struct failed." );
            }
            png_infop info_ptr = png_create_info_struct ( png_ptr );
            if ( info_ptr == nullptr )
            {
                throw std::runtime_error ( "png_create_info_struct failed." );
            }
            if ( setjmp ( png_jmpbuf ( png_ptr ) ) )
            {
                throw std::runtime_error ( "Error during init_io." );
            }
            png_read_memory_struct read_memory_struct = {static_cast<const uint8_t*> ( aBuffer ), static_cast<const uint8_t*> ( aBuffer ) + 8,
                                                         static_cast<png_size_t> ( aBufferSize * sizeof ( uint8_t ) )
                                                        };
            png_set_read_fn ( png_ptr, &read_memory_struct, png_read_memory_data );
            png_set_sig_bytes ( png_ptr, 8 );

            png_read_info ( png_ptr, info_ptr );

            uint32_t width = png_get_image_width ( png_ptr, info_ptr );
            uint32_t 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 );

            Image::ImageFormat format;
            Image::ImageType type;
            if ( ( color_type == PNG_COLOR_TYPE_RGB ) || ( color_type == PNG_COLOR_TYPE_RGBA ) )
            {
                format = ( color_type == PNG_COLOR_TYPE_RGB ) ? Image::ImageFormat::RGB : Image::ImageFormat::RGBA;
                type   = ( bit_depth == 8 ) ? Image::ImageType::UNSIGNED_BYTE : Image::ImageType::UNSIGNED_SHORT;
            }
            else
            {
                throw std::runtime_error ( "PNG image color type not supported...yet" );
            }

            /*int number_of_passes =*/ png_set_interlace_handling ( png_ptr );
            png_read_update_info ( png_ptr, info_ptr );

            /* read file */
            if ( setjmp ( png_jmpbuf ( png_ptr ) ) )
            {
                throw std::runtime_error ( "Error during read_image." );
            }
            // --------------------------------------
            png_size_t rowbytes = png_get_rowbytes ( png_ptr, info_ptr );
            std::vector<uint8_t*> row_pointers ( sizeof ( png_bytep ) * height );
            std::vector<uint8_t> pixels ( width * height * GetPixelSize ( format, type ) );
            for ( png_uint_32 y = 0; y < height; ++y )
            {
                row_pointers[y] = pixels.data() + ( rowbytes * y );
            }
            // --------------------------------------
            png_read_image ( png_ptr, row_pointers.data() );
            png_destroy_read_struct ( &png_ptr, &info_ptr, ( png_infopp ) nullptr );
            aImage.Initialize ( width, height, format, type, pixels.data() );
        }
        catch ( std::runtime_error& e )
        {
            std::cout << e.what() << std::endl;
            return false;
        }
        return true;
    }
Пример #21
0
PyObject*
_png_module::_read_png(const Py::Object& py_fileobj, const bool float_result,
                       int result_bit_depth)
{
    png_byte header[8];   // 8 is the maximum size that can be checked
    FILE* fp = NULL;
    bool close_file = false;
    bool close_dup_file = false;
    PyObject *py_file = NULL;

    if (py_fileobj.isString())
    {
        if ((py_file = npy_PyFile_OpenFile(py_fileobj.ptr(), (char *)"rb")) == NULL) {
            throw Py::Exception();
        }
        close_file = true;
    } else {
        py_file = py_fileobj.ptr();
    }

    if ((fp = npy_PyFile_Dup(py_file, "rb")))
    {
        close_dup_file = true;
    }
    else
    {
        PyErr_Clear();
        PyObject* read_method = PyObject_GetAttrString(py_file, "read");
        if (!(read_method && PyCallable_Check(read_method)))
        {
            Py_XDECREF(read_method);
            throw Py::TypeError(
                "Object does not appear to be a 8-bit string path or a Python "
                "file-like object");
        }
        Py_XDECREF(read_method);
    }

    if (fp)
    {
        if (fread(header, 1, 8, fp) != 8)
        {
            throw Py::RuntimeError(
                "_image_module::readpng: error reading PNG header");
        }
    }
    else
    {
        _read_png_data(py_file, header, 8);
    }
    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");
    }

    if (fp)
    {
        png_init_io(png_ptr, fp);
    }
    else
    {
        png_set_read_fn(png_ptr, (void*)py_file, &read_png_data);
    }
    png_set_sig_bytes(png_ptr, 8);
    png_read_info(png_ptr, info_ptr);

    png_uint_32 width = png_get_image_width(png_ptr, info_ptr);
    png_uint_32 height = png_get_image_height(png_ptr, info_ptr);

    int bit_depth = png_get_bit_depth(png_ptr, info_ptr);

    // Unpack 1, 2, and 4-bit images
    if (bit_depth < 8)
        png_set_packing(png_ptr);

    // If sig bits are set, shift data
    png_color_8p sig_bit;
    if ((png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_PALETTE) &&
        png_get_sBIT(png_ptr, info_ptr, &sig_bit))
    {
        png_set_shift(png_ptr, sig_bit);
    }

    // Convert big endian to little
    if (bit_depth == 16)
    {
        png_set_swap(png_ptr);
    }

    // Convert palletes to full RGB
    if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE)
    {
        png_set_palette_to_rgb(png_ptr);
        bit_depth = 8;
    }

    // If there's an alpha channel convert gray to RGB
    if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_GRAY_ALPHA)
    {
        png_set_gray_to_rgb(png_ptr);
    }

    png_set_interlace_handling(png_ptr);
    png_read_update_info(png_ptr, info_ptr);

    /* read file */
    if (setjmp(png_jmpbuf(png_ptr)))
    {
        throw Py::RuntimeError(
            "_image_module::readpng: error during read_image");
    }

    png_bytep *row_pointers = new png_bytep[height];
    png_uint_32 row;

    for (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);

    npy_intp dimensions[3];
    dimensions[0] = height;  //numrows
    dimensions[1] = width;   //numcols
    if (png_get_color_type(png_ptr, info_ptr) & PNG_COLOR_MASK_ALPHA)
    {
        dimensions[2] = 4;     //RGBA images
    }
    else if (png_get_color_type(png_ptr, info_ptr) & PNG_COLOR_MASK_COLOR)
    {
        dimensions[2] = 3;     //RGB images
    }
    else
    {
        dimensions[2] = 1;     //Greyscale images
    }
    //For gray, return an x by y array, not an x by y by 1
    int num_dims  = (png_get_color_type(png_ptr, info_ptr)
                                & PNG_COLOR_MASK_COLOR) ? 3 : 2;

    PyArrayObject *A = NULL;
    if (float_result) {
        double max_value = (1 << bit_depth) - 1;

        A = (PyArrayObject *) PyArray_SimpleNew(num_dims, dimensions, NPY_FLOAT);

        if (A == NULL)
        {
            throw Py::MemoryError("Could not allocate image array");
        }

        for (png_uint_32 y = 0; y < height; y++)
        {
            png_byte* row = row_pointers[y];
            for (png_uint_32 x = 0; x < width; x++)
            {
                size_t offset = y * A->strides[0] + x * A->strides[1];
                if (bit_depth == 16)
                {
                    png_uint_16* ptr = &reinterpret_cast<png_uint_16*>(row)[x * dimensions[2]];
                    for (png_uint_32 p = 0; p < (png_uint_32)dimensions[2]; p++)
                    {
                        *(float*)(A->data + offset + p*A->strides[2]) = (float)(ptr[p]) / max_value;
                    }
                }
                else
                {
                    png_byte* ptr = &(row[x * dimensions[2]]);
                    for (png_uint_32 p = 0; p < (png_uint_32)dimensions[2]; p++)
                    {
                        *(float*)(A->data + offset + p*A->strides[2]) = (float)(ptr[p]) / max_value;
                    }
                }
            }
        }
    } else {
        if (result_bit_depth < 0) {
            result_bit_depth = bit_depth;
        }

        if (result_bit_depth == 8) {
            A = (PyArrayObject *) PyArray_SimpleNew(num_dims, dimensions, NPY_UBYTE);
        } else if (result_bit_depth == 16) {
            A = (PyArrayObject *) PyArray_SimpleNew(num_dims, dimensions, NPY_UINT16);
        } else {
            throw Py::RuntimeError(
                "_image_module::readpng: image has unknown bit depth");
        }

        if (A == NULL)
        {
            throw Py::MemoryError("Could not allocate image array");
        }

        for (png_uint_32 y = 0; y < height; y++)
        {
            png_byte* row = row_pointers[y];
            for (png_uint_32 x = 0; x < width; x++)
            {
                size_t offset = y * A->strides[0] + x * A->strides[1];
                if (bit_depth == 16)
                {
                    png_uint_16* ptr = &reinterpret_cast<png_uint_16*>(row)[x * dimensions[2]];

                    if (result_bit_depth == 16) {
                        for (png_uint_32 p = 0; p < (png_uint_32)dimensions[2]; p++)
                        {
                            *(png_uint_16*)(A->data + offset + p*A->strides[2]) = ptr[p];
                        }
                    } else {
                        for (png_uint_32 p = 0; p < (png_uint_32)dimensions[2]; p++)
                        {
                            *(png_byte*)(A->data + offset + p*A->strides[2]) = ptr[p] >> 8;
                        }
                    }
                }
                else
                {
                    png_byte* ptr = &(row[x * dimensions[2]]);
                    if (result_bit_depth == 16) {
                        for (png_uint_32 p = 0; p < (png_uint_32)dimensions[2]; p++)
                        {
                            *(png_uint_16*)(A->data + offset + p*A->strides[2]) = ptr[p];
                        }
                    } else {
                        for (png_uint_32 p = 0; p < (png_uint_32)dimensions[2]; p++)
                        {
                            *(png_byte*)(A->data + offset + p*A->strides[2]) = ptr[p];
                        }
                    }
                }
            }
        }
Пример #22
0
ImageData ReadPNG(char* fileName)
{
    ImageData meta;
    meta.valid = false;

    // Step 0: Make sure we can open the input file
    FILE* inFile = fopen(fileName, "rb");
    if (!inFile) {
        abort_("ReadPNG: Can't open %s for reading\n", fileName);
    }

    // Step 1: initialize the reader
    png_structp png = png_create_read_struct(
            PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png) {
        abort_("ReadPNG: png_create_read_struct() failed\n");
    }

    png_infop info = png_create_info_struct(png);
    if (!info) {
        abort_("ReadPNG: png_create_info_struct() failed\n");
    }

    if (setjmp(png_jmpbuf(png))) {
        abort_("ReadPNG: Error during initialization.\n");
    }
    
    png_init_io(png, inFile);
    png_read_info(png, info);

    // Step 2: Collect image statistics
    int width           = png_get_image_width(png, info);
    int height          = png_get_image_height(png, info);
    png_byte color_type = png_get_color_type(png, info);
    png_byte bit_depth  = png_get_bit_depth(png, info);

    // Make some adjustments
    if (bit_depth == 16) {
        png_set_strip_16(png);
    }
    if (color_type == PNG_COLOR_TYPE_PALETTE) {
        png_set_palette_to_rgb(png);
    }
    if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
        png_set_expand_gray_1_2_4_to_8(png);
    }

    if(png_get_valid(png, info, PNG_INFO_tRNS))
            png_set_tRNS_to_alpha(png);

    // These color_type don't have an alpha channel then fill it with 0xff.
    if(color_type == PNG_COLOR_TYPE_RGB ||
       color_type == PNG_COLOR_TYPE_GRAY ||
       color_type == PNG_COLOR_TYPE_PALETTE) {
        png_set_filler(png, 0xFF, PNG_FILLER_AFTER);
    }
    
    if(color_type == PNG_COLOR_TYPE_GRAY ||
       color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
        png_set_gray_to_rgb(png);
    }

    png_read_update_info(png, info);

    // Step 3: Read the data
    if (setjmp(png_jmpbuf(png))) {
        abort_("ReadPNG: Error during image data reading.\n");
    }

    png_bytep row_pointers[height];

    // This method gives a discontiguous array of rows
    // Each row is later copied to the destination image, RGB only.
    // There should be a more streamlined method, but this method works for lena.png
    for (int y = 0; y < height; y++) {
       row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png, info));
       if (!row_pointers[y]) {
           abort_("ReadPNG: Couldn't allocate row %d\n", y);
        }
    }
    
    // Now we can read the image
    int row_bytes = png_get_rowbytes(png, info);
    png_read_image(png, row_pointers);

    // Convert the image from discontiguous rows to contiguous rows, discarding alpha
    Pixel* image = (Pixel*)malloc(height * width * 3);
    if (!image) {
        abort_("ReadPNG: Couldn't allocate image (%d, %d)\n", height, row_bytes);
    }

    // Brute force copy, skip over ALPHA channel
    for (int row = 0; row < height; row++) {
        for (int pixel = 0; pixel < width; pixel++)
        {
            image[(row * width + pixel)] = 
                *(Pixel*)(row_pointers[row] + pixel * 4);
        }
        // As we use them, delete the pointers to the image rows.
        free(row_pointers[row]);
    }

   
    meta.xDim = width;
    meta.yDim = height;
    meta.valid = true;
    meta.pixels = (Pixel*)image;

    // Step 4: Tidy up.
    fclose(inFile);

    // Done.
    return meta;

}
Пример #23
0
/*!
 *  pixReadStreamPng()
 *
 *      Input:  stream
 *      Return: pix, or null on error
 *
 *  Notes:
 *      (1) If called from pixReadStream(), the stream is positioned
 *          at the beginning of the file.
 *      (2) To do sequential reads of png format images from a stream,
 *          use pixReadStreamPng()
 */
PIX *
pixReadStreamPng(FILE  *fp)
{
l_uint8      rval, gval, bval;
l_int32      i, j, k;
l_int32      wpl, d, spp, cindex;
l_uint32     png_transforms;
l_uint32    *data, *line, *ppixel;
int          num_palette, num_text;
png_byte     bit_depth, color_type, channels;
png_uint_32  w, h, rowbytes;
png_uint_32  xres, yres;
png_bytep    rowptr;
png_bytep   *row_pointers;
png_structp  png_ptr;
png_infop    info_ptr, end_info;
png_colorp   palette;
png_textp    text_ptr;  /* ptr to text_chunk */
PIX         *pix;
PIXCMAP     *cmap;

    PROCNAME("pixReadStreamPng");

    if (!fp)
        return (PIX *)ERROR_PTR("fp not defined", procName, NULL);
    pix = NULL;

        /* Allocate the 3 data structures */
    if ((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
                   (png_voidp)NULL, NULL, NULL)) == NULL)
        return (PIX *)ERROR_PTR("png_ptr not made", procName, NULL);

    if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) {
        png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
        return (PIX *)ERROR_PTR("info_ptr not made", procName, NULL);
    }

    if ((end_info = png_create_info_struct(png_ptr)) == NULL) {
        png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
        return (PIX *)ERROR_PTR("end_info not made", procName, NULL);
    }

        /* Set up png setjmp error handling */
    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        return (PIX *)ERROR_PTR("internal png error", procName, NULL);
    }

    png_init_io(png_ptr, fp);

        /* ---------------------------------------------------------- *
         *  Set the transforms flags.  Whatever happens here,
         *  NEVER invert 1 bpp using PNG_TRANSFORM_INVERT_MONO.
         * ---------------------------------------------------------- */
        /* To strip 16 --> 8 bit depth, use PNG_TRANSFORM_STRIP_16 */
    if (var_PNG_STRIP_16_TO_8 == 1)   /* our default */
        png_transforms = PNG_TRANSFORM_STRIP_16;
    else
        png_transforms = PNG_TRANSFORM_IDENTITY;
        /* To remove alpha channel, use PNG_TRANSFORM_STRIP_ALPHA */
    if (var_PNG_STRIP_ALPHA == 1)   /* our default */
        png_transforms |= PNG_TRANSFORM_STRIP_ALPHA;

        /* Read it */
    png_read_png(png_ptr, info_ptr, png_transforms, NULL);

    row_pointers = png_get_rows(png_ptr, info_ptr);
    w = png_get_image_width(png_ptr, info_ptr);
    h = png_get_image_height(png_ptr, info_ptr);
    bit_depth = png_get_bit_depth(png_ptr, info_ptr);
    rowbytes = png_get_rowbytes(png_ptr, info_ptr);
    color_type = png_get_color_type(png_ptr, info_ptr);
    channels = png_get_channels(png_ptr, info_ptr);
    spp = channels;

    if (spp == 1)
        d = bit_depth;
    else if (spp == 2) {
        d = 2 * bit_depth;
        L_WARNING("there shouldn't be 2 spp!", procName);
    }
    else  /* spp == 3 (rgb), spp == 4 (rgba) */
        d = 4 * bit_depth;

        /* Remove if/when this is implemented for all bit_depths */
    if (spp == 3 && bit_depth != 8) {
        fprintf(stderr, "Help: spp = 3 and depth = %d != 8\n!!", bit_depth);
        return (PIX *)ERROR_PTR("not implemented for this depth",
            procName, NULL);
    }

    if (color_type == PNG_COLOR_TYPE_PALETTE ||
        color_type == PNG_COLOR_MASK_PALETTE) {   /* generate a colormap */
        png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
        cmap = pixcmapCreate(d);  /* spp == 1 */
        for (cindex = 0; cindex < num_palette; cindex++) {
            rval = palette[cindex].red;
            gval = palette[cindex].green;
            bval = palette[cindex].blue;
            pixcmapAddColor(cmap, rval, gval, bval);
        }
    }
    else
        cmap = NULL;

    if ((pix = pixCreate(w, h, d)) == NULL) {
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        return (PIX *)ERROR_PTR("pix not made", procName, NULL);
    }
    wpl = pixGetWpl(pix);
    data = pixGetData(pix);
    pixSetColormap(pix, cmap);

    if (spp == 1) {   /* copy straight from buffer to pix */
        for (i = 0; i < h; i++) {
            line = data + i * wpl;
            rowptr = row_pointers[i];
            for (j = 0; j < rowbytes; j++) {
                SET_DATA_BYTE(line, j, rowptr[j]);
            }
        }
    }
    else  {   /* spp == 3 or spp == 4 */
        for (i = 0; i < h; i++) {
            ppixel = data + i * wpl;
            rowptr = row_pointers[i];
            for (j = k = 0; j < w; j++) {
                SET_DATA_BYTE(ppixel, COLOR_RED, rowptr[k++]);
                SET_DATA_BYTE(ppixel, COLOR_GREEN, rowptr[k++]);
                SET_DATA_BYTE(ppixel, COLOR_BLUE, rowptr[k++]);
                if (spp == 4)
                    SET_DATA_BYTE(ppixel, L_ALPHA_CHANNEL, rowptr[k++]);
                ppixel++;
            }
        }
    }

#if  DEBUG
    if (cmap) {
        for (i = 0; i < 16; i++) {
            fprintf(stderr, "[%d] = %d\n", i,
                   ((l_uint8 *)(cmap->array))[i]);
        }
    }
#endif  /* DEBUG */

        /* If there is no colormap, PNG defines black = 0 and
         * white = 1 by default for binary monochrome.  Therefore,
         * since we use the opposite definition, we must invert
         * the image in either of these cases:
         *    (i) there is no colormap (default)
         *    (ii) there is a colormap which defines black to
         *         be 0 and white to be 1.
         * We cannot use the PNG_TRANSFORM_INVERT_MONO flag
         * because that flag (since version 1.0.9) inverts 8 bpp
         * grayscale as well, which we don't want to do.
         * (It also doesn't work if there is a colormap.)
         * If there is a colormap that defines black = 1 and
         * white = 0, we don't need to do anything.
         * 
         * How do we check the polarity of the colormap?
         * The colormap determines the values of black and
         * white pixels in the following way:
         *     if black = 1 (255), white = 0
         *          255, 255, 255, 0, 0, 0, 0, 0, 0
         *     if black = 0, white = 1 (255)
         *          0, 0, 0, 0, 255, 255, 255, 0
         * So we test the first byte to see if it is 0;
         * if so, invert the data.  */
    if (d == 1 && (!cmap || (cmap && ((l_uint8 *)(cmap->array))[0] == 0x0))) {
/*        fprintf(stderr, "Inverting binary data on png read\n"); */
        pixInvert(pix, pix);
    }

    xres = png_get_x_pixels_per_meter(png_ptr, info_ptr);
    yres = png_get_y_pixels_per_meter(png_ptr, info_ptr);
    pixSetXRes(pix, (l_int32)((l_float32)xres / 39.37 + 0.5));  /* to ppi */
    pixSetYRes(pix, (l_int32)((l_float32)yres / 39.37 + 0.5));  /* to ppi */

        /* Get the text if there is any */
    png_get_text(png_ptr, info_ptr, &text_ptr, &num_text);
    if (num_text && text_ptr)
        pixSetText(pix, text_ptr->text);

    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    return pix;
}
Пример #24
0
void read_png(const char* filename, int* w, int* h, GLenum* format, 
              char*& pixels)
{
    if(!w || !h || !format || !filename) return;
    FILE* fptr = fopen(filename,"rb");
    if(!fptr)
    {
        printf("READ PNG: Can't open file %s\n", filename);
        return;
    }

    // png structures

    png_structp png_ptr;
    png_infop   info_ptr;
    
    png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if( !png_ptr ) return;

    info_ptr = png_create_info_struct( png_ptr );
    if( !info_ptr ) return;

    png_init_io(png_ptr, fptr);
    png_read_png( png_ptr, info_ptr,
                  PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING, NULL);

    int components = 0;

    switch( png_get_color_type(png_ptr,info_ptr))
    {
    case PNG_COLOR_TYPE_GRAY:
        *format = GL_LUMINANCE;
        components = 1;
        break;
    case PNG_COLOR_TYPE_RGB:
        *format = GL_RGB;
        components = 3;
        break;
    case PNG_COLOR_TYPE_RGB_ALPHA:
        *format = GL_RGBA;
        components = 4;
        break;
    default:
        break;
    }

    if( !components )
    {
        printf("Unsupported PNG color mode\n");
        png_destroy_read_struct( &png_ptr, &info_ptr, NULL);
        fclose(fptr);
        return;
    }

    if( info_ptr->bit_depth != 8 )
    {
        printf("Unsupported PNG bit depth\n");
        png_destroy_read_struct( &png_ptr, &info_ptr, NULL);
        fclose(fptr);
        return;
    }

    // try to get rows

    png_bytep *b = png_get_rows( png_ptr, info_ptr );

    if( !b)
    {
        printf("Can't get pixels from PNG\n");
        png_destroy_read_struct( &png_ptr, &info_ptr, NULL);
        fclose(fptr);
        return;
    }

    *w = (int) png_get_image_width( png_ptr, info_ptr);
    *h = (int) png_get_image_height( png_ptr, info_ptr);

    pixels = new char[ (*w) * (*h) * components ];
    memset( pixels, 0, (*w) * (*h) * components );

    for( int y = 0; y < *h; ++y)
        for( int x = 0; x < *w; ++x)
            for( int c = 0; c < components; ++c)
            {
                pixels[ y * (*w) * components +  x * components + c] = 
                    (char) b[y][x * components + c];

            }

    png_destroy_read_struct( &png_ptr, &info_ptr, NULL);
    fclose(fptr);

    // done
}
Пример #25
0
static void png(FILE *input, FILE *output, int width, int height)
{
	int i, in_width, in_height, ret;
	png_structp rpng, wpng;
	png_infop rinfo, winfo;
	png_byte ctype;
	struct oil_libpng ol;
	unsigned char *outbuf;

	rpng = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

	if (setjmp(png_jmpbuf(rpng))) {
		fprintf(stderr, "PNG Decoding Error.\n");
		exit(1);
	}

	rinfo = png_create_info_struct(rpng);
	png_init_io(rpng, input);
	png_read_info(rpng, rinfo);

	png_set_packing(rpng);
	png_set_strip_16(rpng);
	png_set_expand(rpng);
	png_set_interlace_handling(rpng);
	png_read_update_info(rpng, rinfo);

	in_width = png_get_image_width(rpng, rinfo);
	in_height = png_get_image_height(rpng, rinfo);
	oil_fix_ratio(in_width, in_height, &width, &height);

	wpng = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	winfo = png_create_info_struct(wpng);
	png_init_io(wpng, output);

	ret = oil_libpng_init(&ol, rpng, rinfo, width, height);
	if (ret!=0) {
		fprintf(stderr, "Unable to allocate buffers.\n");
		exit(1);
	}

	ctype = png_get_color_type(rpng, rinfo);
	png_set_IHDR(wpng, winfo, width, height, 8, ctype, PNG_INTERLACE_NONE,
		PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

	png_write_info(wpng, winfo);

	outbuf = malloc(width * OIL_CMP(ol.os.cs));
	if (!outbuf) {
		fprintf(stderr, "Unable to allocate buffers.\n");
		exit(1);
	}

	for(i=0; i<height; i++) {
		oil_libpng_read_scanline(&ol, outbuf);
		png_write_row(wpng, outbuf);
	}

	png_write_end(wpng, winfo);
	png_destroy_write_struct(&wpng, &winfo);
	png_destroy_read_struct(&rpng, &rinfo, NULL);

	free(outbuf);
	oil_libpng_free(&ol);
}
Пример #26
0
plMipmap* plPNG::IRead(hsStream* inStream)
{
    plMipmap* newMipmap = NULL;
    png_structp png_ptr;
    png_infop info_ptr;
    png_infop end_info;

    try {
        //  Check PNG Signature
        png_byte sig[PNGSIGSIZE];
        inStream->Read8Bytes((char*) sig);

        if (!png_sig_cmp(sig, 0, PNGSIGSIZE)) {
            //  Allocate required structs
            png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

            if (!png_ptr) {
                throw false;
            }

            info_ptr = png_create_info_struct(png_ptr);

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

            end_info = png_create_info_struct(png_ptr);

            if (!end_info) {
                png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
                throw false;
            }

            //  Assign delegate function for reading from hsStream
            png_set_read_fn(png_ptr, (png_voidp)inStream, pngReadDelegate);
            //  Get PNG Header information
            png_set_sig_bytes(png_ptr, PNGSIGSIZE);
            png_read_info(png_ptr, info_ptr);
            png_uint_32 imgWidth =  png_get_image_width(png_ptr, info_ptr);
            png_uint_32 imgHeight = png_get_image_height(png_ptr, info_ptr);
            png_uint_32 bitdepth   = png_get_bit_depth(png_ptr, info_ptr);
            png_uint_32 channels   = png_get_channels(png_ptr, info_ptr);
            png_uint_32 color_type = png_get_color_type(png_ptr, info_ptr);

            //  Convert images to RGB color space
            switch (color_type) {
                case PNG_COLOR_TYPE_PALETTE:
                    png_set_palette_to_rgb(png_ptr);
                    channels = 3;
                    break;
                case PNG_COLOR_TYPE_GRAY:

                    if (bitdepth < 8) {
                        png_set_expand_gray_1_2_4_to_8(png_ptr);
                    }

                    bitdepth = 8;
                    break;
            }

            //  Convert transparency (if needed) to a full alpha channel
            if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
                png_set_tRNS_to_alpha(png_ptr);
                channels += 1;
            } else if (channels == 3) {
                // Add an opaque alpha channel if still none exists
                png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
                channels = 4;
            }

            // Invert color byte-order as used by plMipmap for DirectX
            png_set_bgr(png_ptr);
            /// Construct a new mipmap to hold everything
            newMipmap = new plMipmap(imgWidth, imgHeight, plMipmap::kARGB32Config, 1, plMipmap::kUncompressed);
            char* destp = (char*)newMipmap->GetImage();
            png_bytep* row_ptrs = new png_bytep[imgHeight];
            const unsigned int stride = imgWidth * bitdepth * channels / 8;

            //  Assign row pointers to the appropriate locations in the newly-created Mipmap
            for (size_t i = 0; i < imgHeight; i++) {
                row_ptrs[i] = (png_bytep)destp + (i * stride);
            }

            png_read_image(png_ptr, row_ptrs);
            png_read_end(png_ptr, end_info);
            //  Clean up allocated structs
            png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
            delete [] row_ptrs;
        }
    } catch (...) {
        delete newMipmap;
        newMipmap = nullptr;
    }

    return newMipmap;
}
Пример #27
0
int main(int argc, char *argv[])
{
  unsigned char header[8];
  if ( argc != 3 )
   {
        printf( "usage: %s filename gamma_value", argv[0] );
    }
  FILE *fp = fopen(argv[1],"rb");
  float gamma ;
  sscanf(argv[2], "%f", &gamma);
  if(!fp)
    printf("not a file");
  fread(header, 1, 8, fp);
  int is_png = !png_sig_cmp(header, 0, 8); //Quite weird. cmp return 0 if bytes match PNG signature
  if(!is_png)
    printf("not a png");
  else
    printf("input file confirmed as png\n");

  //Creating png_structp
  png_structp png_ptr = png_create_read_struct
	(PNG_LIBPNG_VER_STRING, 
	 NULL, //(png_voidp)user_error_ptr, 
	 NULL, //user_error_fn, 
	 NULL); //user_warning_fn);
  
  if(!png_ptr)
    printf("png_ptr construct error\n");

  //Creating png_infop
  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);
    printf("something wrong with pngInfo\n");
  }
  
  //setjmp for error condition from libpng

  if(setjmp(png_jmpbuf(png_ptr)))
    printf("something wrong with jmp setting\n");

  //eventually, we are reading the file :-)
  png_init_io(png_ptr, fp);
  //since we've sampled 8 byes for testing if it is png, we need to let libpng know 
  png_set_sig_bytes(png_ptr, 8);

  //There're bunch of error handling from the manual... we skip as usual
/*
  //High-level of reading interface, we'll read into memory directly
  png_read_png(png_ptr, info_ptr, 0, NULL); //third para as png_transforms bitwise OR mask
  png_bytep *row_pointers = png_get_rows(png_ptr, info_ptr);
*/

  /* low level of reading, we need it to manipulate more detailed stuff*/
  png_read_info(png_ptr, info_ptr);
  
  int width = png_get_image_width(png_ptr, info_ptr);
  int 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);
  png_bytep *row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
  int x, y,k;
  k = (int)((log(bit_depth)/log(2)));
  printf("%d\n", k);
  for (y = 0; y < height; y++)
    row_pointers[y] = (png_bytep) malloc(width*k);

  png_read_image(png_ptr, row_pointers);

  printf("color_type:%d\nbit_depth: %d\n",color_type, bit_depth);
  

  //processing image
  for (y = 0; y< height; y++)
  {
    png_byte* row = row_pointers[y];
    for(x = 0; x < width; x ++)
    {
      png_byte* ptr = &(row[x*k]);    
      //ptr[0] = 255 - ptr[0]; //shouldn't invert alpha :)
      //ptr[0] = (int)(pow(ptr[0], 0.9)) ;
      ptr[1] = (int)(255 * pow((ptr[1]/255.0), gamma)) ;
      ptr[2] = (int)(255 * pow((ptr[2]/255.0), gamma)) ;
      ptr[3] = (int)(255 * pow((ptr[3]/255.0), gamma)) ;
    } 

  }
  //output
  FILE *outfp = fopen("gammaout.png", "wb");
  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
  info_ptr = png_create_info_struct(png_ptr);
  png_init_io(png_ptr, outfp);
  png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

  png_write_info(png_ptr, info_ptr);  
  png_write_image(png_ptr, row_pointers);
  png_write_end(png_ptr, NULL);

  free(row_pointers);

  fclose(fp);
  


}
Пример #28
0
bool CGLCG::loadPngImage(const TCHAR *name, int &outWidth, int &outHeight, bool &outHasAlpha, GLubyte **outData) {
    png_structp png_ptr;
    png_infop info_ptr;
    unsigned int sig_read = 0;
    int color_type, interlace_type;
    FILE *fp;

	if ((fp = _tfopen(name, TEXT("rb"))) == NULL)
        return false;

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

    if (png_ptr == NULL) {
        fclose(fp);
        return false;
    }

    /* Allocate/initialize the memory
     * for image information.  REQUIRED. */
    info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL) {
        fclose(fp);
        png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
        return false;
    }

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

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

    /* If we have already
     * read some of the signature */
    png_set_sig_bytes(png_ptr, sig_read);

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

    outWidth = png_get_image_width(png_ptr, info_ptr);
    outHeight = png_get_image_height(png_ptr, info_ptr);
    switch (png_get_color_type(png_ptr, info_ptr)) {
        case PNG_COLOR_TYPE_RGBA:
            outHasAlpha = true;
            break;
        case PNG_COLOR_TYPE_RGB:
            outHasAlpha = false;
            break;
        default:
            png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
            fclose(fp);
            return false;
    }
    unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
    *outData = (unsigned char*) malloc(row_bytes * outHeight);

    png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);

    for (int i = 0; i < outHeight; i++) {
        memcpy(*outData+(row_bytes * i), row_pointers[i], row_bytes);
    }

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

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

    /* That's it */
    return true;
}
Пример #29
0
s32 pngDecOpen(ppu_thread& ppu, PHandle handle, PPStream png_stream, PSrc source, POpenInfo open_info, PCbControlStream control_stream = vm::null, POpenParam open_param = vm::null)
{
	// Check if partial image decoding is used
	if (control_stream || open_param)
	{
		fmt::throw_exception("Partial image decoding is not supported." HERE);
	}

	// Allocate memory for the stream structure
	auto stream = vm::ptr<PngStream>::make(handle->malloc(ppu, sizeof(PngStream), handle->malloc_arg).addr());

	// Check if the allocation of memory for the stream structure failed
	if (!stream)
	{
		cellPngDec.error("PNG stream creation failed.");
		return CELL_PNGDEC_ERROR_FATAL;
	}

	// Set memory info
	open_info->initSpaceAllocated = sizeof(PngStream);

	// Set the stream source to the source give by the game
	stream->source = *source;

	// Indicate that a fixed alpha value isn't used, if not specified otherwise
	stream->fixed_alpha = false;

	// Use virtual memory address as a handle
	*png_stream = stream;

	// Allocate memory for the PNG buffer for decoding
	auto buffer = vm::ptr<PngBuffer>::make(handle->malloc(ppu, sizeof(PngBuffer), handle->malloc_arg).addr());

	// Check for if the buffer structure allocation failed
	if (!buffer)
	{
		fmt::throw_exception("Memory allocation for the PNG buffer structure failed." HERE);
	}

	// We might not be reading from a file stream
	buffer->file = false;

	// Set the buffer pointer in the stream structure, so we can later deallocate it
	stream->buffer = buffer;

	// Open the buffer/file and check the header
	u8 header[8];

	// Need to test it somewhere
	if (stream->source.fileOffset != 0)
	{
		fmt::throw_exception("Non-0 file offset not supported." HERE);
	}

	// Depending on the source type, get the first 8 bytes
	if (source->srcSelect == CELL_PNGDEC_FILE)
	{
		// Open a file stream
		fs::file file_stream(vfs::get(stream->source.fileName.get_ptr()));
		
		// Check if opening of the PNG file failed
		if (!file_stream)
		{
			cellPngDec.error("Opening of PNG failed. (%s)", stream->source.fileName.get_ptr());
			return CELL_PNGDEC_ERROR_OPEN_FILE;
		}

		// Read the header
		if (file_stream.read(header, 8) != 8)
		{
			cellPngDec.error("PNG header is too small.");
			return CELL_PNGDEC_ERROR_HEADER;
		}

		// Get the file descriptor
		buffer->fd = idm::make<lv2_file>(stream->source.fileName.get_ptr(), std::move(file_stream), 0, 0);

		// Indicate that we need to read from a file stream
		buffer->file = true;
	}
	else
	{
		// We can simply copy the first 8 bytes
		memcpy(header, stream->source.streamPtr.get_ptr(), 8);
	}

	// Check if the header indicates a valid PNG file
	if (png_sig_cmp(header, 0, 8))
	{
		cellPngDec.error("PNG signature is invalid.");
		return CELL_PNGDEC_ERROR_HEADER;
	}

	// Create a libpng structure, also pass our custom error/warning functions
	stream->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, pngDecError, pngDecWarning);

	// Check if the creation of the structure failed
	if (!stream->png_ptr)
	{
		cellPngDec.error("Creation of png_structp failed.");
		return CELL_PNGDEC_ERROR_FATAL;
	}

	// Create a libpng info structure
	stream->info_ptr = png_create_info_struct(stream->png_ptr);

	// Check if the creation of the structure failed
	if (!stream->info_ptr)
	{
		fmt::throw_exception("Creation of png_infop failed." HERE);
	}

	// Set a point to return to when an error occurs in libpng
	if (setjmp(png_jmpbuf(stream->png_ptr)))
	{
		fmt::throw_exception("Fatal error in libpng." HERE);
	}

	// We must indicate, that we allocated more memory
	open_info->initSpaceAllocated += sizeof(PngBuffer);

	// Init the IO for either reading from a file or a buffer
	if (source->srcSelect == CELL_PNGDEC_BUFFER)
	{
		// Set the data pointer and the file size
		buffer->length = stream->source.fileSize;
		buffer->data = stream->source.streamPtr;

		// Since we already read the header, we start reading from position 8
		buffer->cursor = 8;
	}

	// Set the custom read function for decoding
	png_set_read_fn(stream->png_ptr, buffer.get_ptr(), pngDecReadBuffer);

	// We need to tell libpng, that we already read 8 bytes
	png_set_sig_bytes(stream->png_ptr, 8);

	// Read the basic info of the PNG file
	png_read_info(stream->png_ptr, stream->info_ptr);

	// Read the header info for future use
	stream->info.imageWidth = png_get_image_width(stream->png_ptr, stream->info_ptr);
	stream->info.imageHeight = png_get_image_height(stream->png_ptr, stream->info_ptr);
	stream->info.numComponents = png_get_channels(stream->png_ptr, stream->info_ptr);
	stream->info.colorSpace = getPngDecColourType(png_get_color_type(stream->png_ptr, stream->info_ptr));
	stream->info.bitDepth = png_get_bit_depth(stream->png_ptr, stream->info_ptr);
	stream->info.interlaceMethod = png_get_interlace_type(stream->png_ptr, stream->info_ptr);
	stream->info.chunkInformation = pngDecGetChunkInformation(stream);

	return CELL_OK;
}
Пример #30
0
int VFrame::read_png(const unsigned char *data, long img_sz)
{
// Test for RAW format
	if(data[0] == 'R' && data[1] == 'A' && data[2] == 'W' && data[3] == ' ') {
		int new_color_model = BC_RGBA8888;
		w = data[4] | (data[5] << 8) | (data[6]  << 16) | (data[7]  << 24);
		h = data[8] | (data[9] << 8) | (data[10] << 16) | (data[11] << 24);
		int components = data[12];
		new_color_model = components == 3 ? BC_RGB888 : BC_RGBA8888;
// This shares the data directly
// 		reallocate(data + 20, 0, 0, 0, w, h, new_color_model, -1);

// Can't use shared data for theme since button constructions overlay the
// images directly.
		reallocate(NULL, -1, 0, 0, 0, w, h, new_color_model, -1);
		memcpy(get_data(), data + 16, w * h * components);

	}
	else if(data[0] == 0x89 && data[1] == 'P' && data[2] == 'N' && data[3] == 'G') {
		int have_alpha = 0;
		png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
		png_infop info_ptr = png_create_info_struct(png_ptr);
		int new_color_model;

		image_offset = 0;
		image = data;  image_size = img_sz;
		png_set_read_fn(png_ptr, this, PngReadFunction::png_read_function);
		png_read_info(png_ptr, info_ptr);

		w = png_get_image_width(png_ptr, info_ptr);
		h = png_get_image_height(png_ptr, info_ptr);

		int src_color_model = png_get_color_type(png_ptr, info_ptr);

		/* tell libpng to strip 16 bit/color files down to 8 bits/color */
		png_set_strip_16(png_ptr);

		/* extract multiple pixels with bit depths of 1, 2, and 4 from a single
		 * byte into separate bytes (useful for paletted and grayscale images).
		 */
		png_set_packing(png_ptr);

		/* expand paletted colors into true RGB triplets */
		if (src_color_model == PNG_COLOR_TYPE_PALETTE)
			png_set_expand(png_ptr);

		/* expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
		if (src_color_model == PNG_COLOR_TYPE_GRAY && png_get_bit_depth(png_ptr, info_ptr) < 8)
			png_set_expand(png_ptr);

		if (src_color_model == PNG_COLOR_TYPE_GRAY ||
		    src_color_model == PNG_COLOR_TYPE_GRAY_ALPHA)
			png_set_gray_to_rgb(png_ptr);

		/* expand paletted or RGB images with transparency to full alpha channels
		 * so the data will be available as RGBA quartets */
		if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)){
			have_alpha = 1;
			png_set_expand(png_ptr);
		}

		switch(src_color_model)
		{
			case PNG_COLOR_TYPE_GRAY:
			case PNG_COLOR_TYPE_RGB:
				new_color_model = BC_RGB888;
				break;

			case PNG_COLOR_TYPE_GRAY_ALPHA:
			case PNG_COLOR_TYPE_RGB_ALPHA:
			default:
				new_color_model = BC_RGBA8888;
				break;

			case PNG_COLOR_TYPE_PALETTE:
				if(have_alpha)
					new_color_model = BC_RGBA8888;
				else
					new_color_model = BC_RGB888;
		}

		reallocate(NULL, -1, 0, 0, 0, w, h, new_color_model, -1);

//printf("VFrame::read_png %d %d %d %p\n", __LINE__, w, h, get_rows());
		png_read_image(png_ptr, get_rows());
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
	}
	else {
		printf("VFrame::read_png %d: unknown file format"
			" 0x%02x 0x%02x 0x%02x 0x%02x\n",
			__LINE__, data[4], data[5], data[6], data[7]);
	}
	return 0;
}