Exemplo n.º 1
0
Arquivo: lpng.c Projeto: lvshaco/lpng
static int
lload(lua_State *L) {
    int top = lua_gettop(L);
    FILE *fp; 
    struct png_source source;
    if (top == 1) {
        const char *filename = luaL_checkstring(L,1);
        fp = fopen(filename, "rb");
        if (fp == NULL) {
            return luaL_error(L, strerror(errno));
        }
        unsigned char header[PNGSIGSIZE];
        if (fread(header, 1, PNGSIGSIZE, fp) != PNGSIGSIZE) {
            return luaL_error(L, "png invalid");
        }
        if (png_sig_cmp(header, 0, PNGSIGSIZE)) {
            return luaL_error(L, "png sig invalid");
        }
        fseek(fp, 0, SEEK_SET);
    } else if (top == 2) {
        luaL_checktype(L,1,LUA_TLIGHTUSERDATA);
        void *data = lua_touserdata(L,1);
        size_t size = luaL_checkinteger(L,2);
        if (size < PNGSIGSIZE) {
            return luaL_error(L, "png invalid");
        }
        if (png_sig_cmp(data, 0, PNGSIGSIZE)) {
            return luaL_error(L, "png sig invalid");
        }
        source.data = data;
        source.size = size;
        source.offset = 0;
    } else {
        return luaL_error(L, "invalid argument number");
    }
    
    png_structp png_ptr;
    png_infop info_ptr;
    png_uint_32 width, height;
    int bit_depth, color_type, interlace_type;
    int step;//, type;

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

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

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

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

    //png_set_sig_bytes(png_ptr, PNGSIGSIZE);

    png_read_info(png_ptr, info_ptr);

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

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

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

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

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

    if (bit_depth < 8)
        png_set_packing(png_ptr);

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

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

    png_size_t rowbytes = png_get_rowbytes(png_ptr,info_ptr);

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

    png_read_end(png_ptr, info_ptr);

    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

    free(row_pointers);

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

    free(buffer);
    return 4;
}
Exemplo n.º 2
0
CDibSection* InformApp::GetImage(const char* path)
{
  // Check if it's a PNG file
  CStdioFile imageFile;
  if (!imageFile.Open(path,CFile::modeRead|CFile::typeBinary))
    return 0;
  png_byte fileHeader[8];
  imageFile.Read(fileHeader,8);
  bool isPNG = (png_sig_cmp(fileHeader,0,8) == 0);

  if (isPNG)
  {
    // Prepare to read the PNG file
    png_structp png_ptr = png_create_read_struct
      (PNG_LIBPNG_VER_STRING,(png_voidp)NULL,NULL,NULL);
    if (png_ptr == NULL)
      return 0;
    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL)
    {
      png_destroy_read_struct(&png_ptr,(png_infopp)NULL,(png_infopp)NULL);
      return 0;
    }
    png_infop end_info = png_create_info_struct(png_ptr);
    if (end_info == NULL)
    {
      png_destroy_read_struct(&png_ptr,&info_ptr,(png_infopp)NULL);
      return 0;
    }

    // Set up the point to return to in case of error
    png_bytep* rowPointers = NULL;
    if (setjmp(png_jmpbuf(png_ptr)))
    {
      if (rowPointers)
        delete[] rowPointers;
      png_destroy_read_struct(&png_ptr,&info_ptr,&end_info);
      return 0;
    }

    png_init_io(png_ptr,imageFile.m_pStream);
    png_set_sig_bytes(png_ptr,8);
    png_read_info(png_ptr,info_ptr);

    // Get details of the image
    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);
    int color_type = png_get_color_type(png_ptr,info_ptr);

    // Set up transforms to the required format
    if (color_type == PNG_COLOR_TYPE_PALETTE && bit_depth <= 8)
      png_set_palette_to_rgb(png_ptr);
    if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
      png_set_expand_gray_1_2_4_to_8(png_ptr);
    if (png_get_valid(png_ptr,info_ptr,PNG_INFO_tRNS))
      png_set_tRNS_to_alpha(png_ptr);
    double gamma;
    if (png_get_gAMA(png_ptr,info_ptr,&gamma))
      png_set_gamma(png_ptr,2.2,gamma);
    if (bit_depth == 16)
      png_set_strip_16(png_ptr);
    if (bit_depth < 8)
      png_set_packing(png_ptr);
    if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      png_set_gray_to_rgb(png_ptr);
    png_set_bgr(png_ptr);
    png_set_filler(png_ptr,0xFF,PNG_FILLER_AFTER);

    // Create a bitmap
    HDC dc = ::GetDC(NULL);
    CDibSection* dib = new CDibSection();
    BOOL created = dib->CreateBitmap(dc,width,height);
    ::ReleaseDC(NULL,dc);
    if (!created)
    {
      png_destroy_read_struct(&png_ptr,&info_ptr,&end_info);
      return NULL;
    }

    // Read in the image
    rowPointers = new png_bytep[height];
    for (int i = 0; i < (int)height; i++)
      rowPointers[i] = ((png_bytep)dib->GetBits())+(width*i*4);
    png_read_image(png_ptr,rowPointers);
    png_read_end(png_ptr,end_info);
    delete[] rowPointers;

    png_destroy_read_struct(&png_ptr,&info_ptr,&end_info);
    return dib;
  }
  else
  {
    imageFile.SeekToBegin();

    struct jpeg_decompress_struct info;
    struct JPEGErrorInfo error;

    // Initialize the error handling
    info.err = jpeg_std_error(&(error.base));
    error.base.error_exit = errorJPEGExit;
    error.base.output_message = outputJPEGMessage;
    if (setjmp(error.errorJump))
    {
      jpeg_destroy_decompress(&info);
      return NULL;
    }

    // Set up the decompression
    jpeg_create_decompress(&info);
    jpeg_stdio_src(&info,imageFile.m_pStream);

    // Read the image attributes
    jpeg_read_header(&info,TRUE);
    jpeg_calc_output_dimensions(&info);
    int width = info.output_width;
    int height = info.output_height;

    // Force RGB output
    info.out_color_space = JCS_RGB;

    // Create a bitmap
    HDC dc = ::GetDC(NULL);
    CDibSection* dib = new CDibSection();
    BOOL created = dib->CreateBitmap(dc,width,height);
    ::ReleaseDC(NULL,dc);
    if (!created)
    {
      jpeg_destroy_decompress(&info);
      return NULL;
    }

    // Get an output buffer
    JSAMPARRAY buffer = (*info.mem->alloc_sarray)
      ((j_common_ptr)&info,JPOOL_IMAGE,width*3,1);

    // Read in the image
    jpeg_start_decompress(&info);
    while ((int)info.output_scanline < height)
    {
      jpeg_read_scanlines(&info,buffer,1);

      BYTE* pixelRow = ((BYTE*)dib->GetBits())+(width*(info.output_scanline-1)*4);
      for (int i = 0; i < width; i++)
      {
        pixelRow[(i*4)+0] = (*buffer)[(i*3)+2];
        pixelRow[(i*4)+1] = (*buffer)[(i*3)+1];
        pixelRow[(i*4)+2] = (*buffer)[(i*3)+0];
        pixelRow[(i*4)+3] = 0xFF;
      }
    }
    jpeg_finish_decompress(&info);
    jpeg_destroy_decompress(&info);
    return dib;
  }
}
Exemplo n.º 3
0
// PNG 형식의 로드
void CDIB::LoadPNGFile(wstring file_name)
{
	unsigned int sig_read=0;
	int bit_depth, color_type, interlace_type;
	
	// 파일 열기
	FILE* fp=_wfopen(file_name.c_str(), L"rb");
	if (!fp) return;

	// png_struct 초기화
	png_structp png_ptr=png_create_read_struct(
		PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!png_ptr) {
		fclose(fp);
		return;
	}
	png_init_io(png_ptr, fp);

	// png_info 초기화
	png_infop info_ptr=png_create_info_struct(png_ptr);
	if (!info_ptr) {
		fclose(fp);
		png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
		return;
	}

	// 화상정보 취득
	png_read_info(png_ptr, info_ptr);
	png_get_IHDR(png_ptr, info_ptr, 
		(unsigned long*)&W, (unsigned long*)&H, 
		&bit_depth, &color_type, &interlace_type, NULL, NULL);

	// DIB 초기화
	InitDIB();
	
	// 변환방법 설정
	// Palette를 RGB로
	if (color_type==PNG_COLOR_TYPE_PALETTE)
		png_set_palette_to_rgb(png_ptr);

	// 투명색을 Alpha로
	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
		png_set_tRNS_to_alpha(png_ptr);

	// Bit depth를 8bit로
	if (bit_depth<8) png_set_packing(png_ptr); else
	if (bit_depth==16) png_set_strip_16(png_ptr);
	
	// 24bit(RGB)를 32bit(RGB0)로
	if (color_type==PNG_COLOR_TYPE_RGB)
		png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);

	// RGB를 BGR로
	if (color_type==PNG_COLOR_TYPE_PALETTE ||
		color_type==PNG_COLOR_TYPE_RGB ||
		color_type==PNG_COLOR_TYPE_RGB_ALPHA)
		png_set_bgr(png_ptr);

	// 화상 읽기
	png_bytep *row_pointers=new png_bytep[H];
	for (int row=0; row<H; row++) row_pointers[row]=(png_bytep)(Pixel+row*W);
	png_read_image(png_ptr, row_pointers);
	png_read_end(png_ptr, info_ptr);
	delete [] row_pointers;

	// 뒷처리
	png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);

	// Alpha 값을 얻는다
	DWORD* p=Pixel;
	BYTE* a=Alpha;
	for (int y=0; y<H; y++) {
		for (int x=0; x<W; x++, p++, a++) {
			*a=(BYTE)(*p>>24);
			*p&=0x00ffffff;
		}
	}

	// Region 초기화
	InitRgn();
}
Exemplo n.º 4
0
int res_create_surface(const char* name, gr_surface* pSurface) {
    char resPath[256];
    GGLSurface* surface = NULL;
    int result = 0;
    unsigned char header[8];
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;

    *pSurface = NULL;

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

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

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

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

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

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

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

    int color_type, bit_depth;
    size_t width, height;

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

    png_byte channels = png_get_channels(png_ptr, info_ptr);

    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 ||
                                color_type == PNG_COLOR_TYPE_GRAY))))) {
        return -7;
        goto exit;
    }

    size_t stride = (color_type == PNG_COLOR_TYPE_GRAY ? 1 : 4) * width;
    size_t pixelSize = stride * height;

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

    int alpha = 0;
    if (color_type == PNG_COLOR_TYPE_PALETTE) {
        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);
        alpha = 1;
    }
    if (color_type == PNG_COLOR_TYPE_GRAY) {
        alpha = 1;
    }

    unsigned int y;
    if (channels == 3 || (channels == 1 && !alpha)) {
        for (y = 0; y < height; ++y) {
            unsigned char* pRow = pData + y * stride;
            png_read_row(png_ptr, pRow, NULL);

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

    *pSurface = (gr_surface) surface;

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

    if (fp != NULL) {
        fclose(fp);
    }
    if (result < 0) {
        if (surface) {
            free(surface);
        }
    }
    return result;
}
Exemplo n.º 5
0
int simpl_gray_load_png(SimplGrayImage **image,
                        SimplInStream istream,
                        const SimplColorToGrayMethods method,
                        const SimplPixel bk_value)
{
    png_structp png_ptr;
    png_infop info_ptr;
    png_byte color_type, bitdepth, *row_data=NULL;
    png_bytep* row_ptrs=NULL;
    
    png_uint_32 i, j, x, width, height, row_size;
    
    SimplColorPixel *pixels=NULL;
    SimplPixel *iptr, *alpha=NULL;
    
    int value, out = SIMPL_INTERNAL;
    
    /* Create a read struct. */
    if (!(png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0))) {
        return SIMPL_INTERNAL;
    }
    
    /* Create an info struct. */
    if (!(info_ptr = png_create_info_struct(png_ptr))) {
        goto error;
    }
    
    /* Handle libpng errors with a magic setjmp. */
    if (setjmp(png_jmpbuf(png_ptr))) {
        goto error;
    }
    
    /* Set the stream-based data source. */
    png_set_read_fn(png_ptr, istream, StreamReadData);
    
    /* Read the info chunk. */
    png_read_info(png_ptr, info_ptr);
    
    /* Get the dimensions and color information. */
    width = png_get_image_width(png_ptr, info_ptr);
    height = png_get_image_height(png_ptr, info_ptr);
    bitdepth = png_get_bit_depth(png_ptr, info_ptr);
    color_type = png_get_color_type(png_ptr, info_ptr);
    
    /* If palette, low bit depth gray, transparent w/o alpha, or 16 bit, fix it. */
    if (color_type == PNG_COLOR_TYPE_PALETTE) {
        png_set_palette_to_rgb(png_ptr);
        color_type = png_get_color_type(png_ptr, info_ptr);
    } else if (color_type == PNG_COLOR_TYPE_GRAY) {
        if (bitdepth<8) png_set_expand_gray_1_2_4_to_8(png_ptr);
        bitdepth = 8;
    }
    
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
        png_set_tRNS_to_alpha(png_ptr);
        color_type = png_get_color_type(png_ptr, info_ptr);
    }
    
    png_set_strip_16(png_ptr);
    
    /* Either allocate a row, or load the entire image into a buffer. This is
     * because single row access uses less memory but doesn't work for
     * interlaced PNGs.
     */
    row_size = png_get_rowbytes(png_ptr, info_ptr);
    if (png_get_interlace_type(png_ptr, info_ptr)==PNG_INTERLACE_NONE) {
        row_data = (png_byte *)malloc(sizeof(png_byte) * row_size);
        if (!row_data) {
            out = SIMPL_NOMEM;
            goto error;
        }
    } else {
        row_ptrs = (png_bytep*)calloc(height, sizeof(png_bytep));
        if (!row_ptrs) {
            out = SIMPL_NOMEM;
            goto error;
        }
        
        for (j=0; j<height; ++j) {
            row_ptrs[j] = (png_byte *)malloc(sizeof(png_byte) * row_size);
            if (!row_ptrs[j]) {
                out = SIMPL_NOMEM;
                goto error;
            }
        }
        
        png_read_image(png_ptr, row_ptrs);
    }
    
    /* Allocate an image of the specified size. */
    out = simpl_gray(image, width, height);
    if (out != SIMPL_OK) goto error;
    
    /* Decode the image line by line. */
    if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
        pixels = (SimplColorPixel *)malloc(sizeof(SimplColorPixel) * width);
        if (!pixels) {
            out = SIMPL_NOMEM;
            goto error;
        }
        
        alpha = (SimplPixel *)malloc(sizeof(SimplPixel) * width);
        if (!alpha) {
            out = SIMPL_NOMEM;
            goto error;
        }
        memset(alpha, 255, width);
        
        for (j=0; j<height; j++) {
            if (row_ptrs) row_data = row_ptrs[j];
            else png_read_row(png_ptr, row_data, NULL);
            iptr = (*image)->image + j * width;
            
            if (color_type==PNG_COLOR_TYPE_RGB) {
                for (x=i=0; x<width; ++x, i+=3) {
                    pixels[x].red   = row_data[i];
                    pixels[x].green = row_data[i+1];
                    pixels[x].blue  = row_data[i+2];
                }
            } else {
                for (x=i=0; x<width; ++x, i+=4) {
                    pixels[x].red   = row_data[i];
                    pixels[x].green = row_data[i+1];
                    pixels[x].blue  = row_data[i+2];
                    alpha[x]        = row_data[i+3];
                }
            }
            
            switch(method) {
            case COLOR_TO_GRAY_RED:
                for (i=0; i<width; ++i) iptr[i] = pixels[i].red;
                break;
                
            case COLOR_TO_GRAY_GREEN:
                for (i=0; i<width; ++i) iptr[i] = pixels[i].green;
                break;
                
            case COLOR_TO_GRAY_BLUE:
                for (i=0; i<width; ++i) iptr[i] = pixels[i].blue;
                break;
                
            case COLOR_TO_GRAY_ALPHA:
                for (i=0; i<width; ++i) iptr[i] = alpha[i];
                break;
                
            case COLOR_TO_GRAY_CIE:
                if (color_type==PNG_COLOR_TYPE_RGB_ALPHA) {
                    for (i=0; i<width; ++i) {
                        value = (6969*pixels[i].red + 23434*pixels[i].green + 2365*pixels[i].blue)>>15;
                        value = (alpha[i]*value + (255-alpha[i])*bk_value) / 255;
                        iptr[i] = (value>255)?255:value;
                    }
                } else {
                    for (i=0; i<width; ++i) {
                        value = (6969*pixels[i].red + 23434*pixels[i].green + 2365*pixels[i].blue)>>15;
                        iptr[i] = (value>255)?255:value;
                    }
                }
                break;
                
            case COLOR_TO_GRAY_MEAN:
            default:
                if (color_type==PNG_COLOR_TYPE_RGB_ALPHA) {
                    for (i=0; i<width; ++i) {
                        value = (pixels[i].red + pixels[i].green + pixels[i].blue)/3;
                        value = (alpha[i]*value + (255-alpha[i])*bk_value) / 255;
                        iptr[i] = (value>255)?255:value;
                    }
                } else {
                    for (i=0; i<width; ++i) {
                        value = (pixels[i].red + pixels[i].green + pixels[i].blue)/3;
                        iptr[i] = (value>255)?255:value;
                    }
                }
                break;
            }
        }
Exemplo n.º 6
0
void PNGImage::loadImage() {
  FILE* file_descriptor = nullptr;
  png_byte header[8];
  png_structp png_ptr = nullptr;
  png_infop info_ptr = nullptr;
  png_byte* image_buffer = nullptr;
  png_bytep* row_ptrs = nullptr;
  png_int_32 row_size = 0;
  bool transparency = false;
  int error_code = 0;

  size_t header_size = sizeof(header);
  file_descriptor = std::fopen(m_filename, "rb");
  if (file_descriptor == nullptr) { error_code = 10; goto ERROR_PNG; }
  if (header_size != std::fread(header, 1, header_size, file_descriptor)) { error_code = 11; goto ERROR_PNG; }
  if (png_sig_cmp(header, 0, 8) != 0) { error_code = 3; goto ERROR_PNG; }

  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
  if (png_ptr == nullptr) { error_code = 4; goto ERROR_PNG; }
  info_ptr = png_create_info_struct(png_ptr);
  if (info_ptr == nullptr) { error_code = 5; goto ERROR_PNG; }

  png_set_read_fn(png_ptr, file_descriptor, callback_read_file);
  {
    int jump_code = 0;
    if ( (jump_code = setjmp(png_jmpbuf(png_ptr))) != 0) {
      ERR("PNGImage: setjump() returned code %i", jump_code);
      error_code = 6; goto ERROR_PNG;
    }
  }

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

  png_int_32 depth, color_type;
  png_uint_32 width, height;
  png_get_IHDR(png_ptr, info_ptr, &width, &height, &depth, &color_type, nullptr, nullptr, nullptr);
  m_width = width;  m_height = height;

  if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
    png_set_tRNS_to_alpha(png_ptr);
    transparency = true;
  }

  if (depth < 8) {
    png_set_packing(png_ptr);
  } else {
    png_set_strip_16(png_ptr);
  }

  switch (color_type) {
    case PNG_COLOR_TYPE_PALETTE:
      png_set_palette_to_rgb(png_ptr);
      break;
    case PNG_COLOR_TYPE_GRAY:
      png_set_expand_gray_1_2_4_to_8(png_ptr);
      break;
    case PNG_COLOR_TYPE_GA:
      png_set_expand_gray_1_2_4_to_8(png_ptr);
      break;
    case PNG_COLOR_TYPE_RGB:
    case PNG_COLOR_TYPE_RGBA:
    default:
      break;
  }
  png_read_update_info(png_ptr, info_ptr);

  row_size = png_get_rowbytes(png_ptr, info_ptr);
  m_size = row_size * height;
  if (row_size <= 0) { error_code = 7; goto ERROR_PNG; }
  image_buffer = new (std::nothrow) png_byte[m_size];
  if (image_buffer == nullptr) { error_code = 8; goto ERROR_PNG; }

  row_ptrs = new (std::nothrow) png_bytep[height];
  if (row_ptrs == nullptr) { error_code = 9; goto ERROR_PNG; }
  for (int32_t i = 0; i < height; ++i) {
    row_ptrs[height - (i + 1)] = image_buffer + i * row_size;
  }
  png_read_image(png_ptr, row_ptrs);

  std::fclose(file_descriptor);
  png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
  delete [] row_ptrs;

  m_buffer = image_buffer;
  return;

  ERROR_PNG:
    m_error_code = error_code;
    ERR("Error while reading PNG file: %s, code %i", m_filename, m_error_code);
    std::fclose(file_descriptor);
    delete [] image_buffer;  image_buffer = nullptr;
    delete [] row_ptrs;  row_ptrs = nullptr;
    if (png_ptr != nullptr) {
      png_infop* info_ptr_p = info_ptr != nullptr ? &info_ptr : nullptr;
      png_destroy_read_struct(&png_ptr, info_ptr_p, nullptr);
    }
}
Exemplo n.º 7
0
/* For little endian systems, ARGB is equivalent to the int32 BGRA.
 * So, to read the image as RGB
 */
static SLang_Array_Type *read_image_internal (char *file, int flip, int *color_typep)
{
   Png_Type *p;
   png_uint_32 width, height, rowbytes;
   png_struct *png;
   png_info *info;
   int bit_depth;
   int interlace_type;
   int color_type;
   unsigned int sizeof_type;
   SLindex_Type dims[2];
   SLtype data_type;
   png_byte **image_pointers = NULL;
   png_byte *data = NULL;
   SLang_Array_Type *at;
   void (*fixup_array_fun) (SLang_Array_Type *);

   if (NULL == (p = open_png_file (file)))
     return NULL;

   png = p->png;
   if (setjmp (png_jmpbuf (png)))
     {
	free_png_type (p);
	if (data != NULL) SLfree ((char *) data);
	free_image_pointers (image_pointers);
	SLang_verror (SL_Read_Error, "Error encountered during I/O to %s", file);
	return NULL;
     }

   png_init_io (png, p->fp);
   png_set_sig_bytes (png, 8);
   info = p->info;
   png_read_info(png, info);

   width = png_get_image_width (png, info);
   height = png_get_image_height (png, info);
   interlace_type = png_get_interlace_type (png, info);
   bit_depth = png_get_bit_depth (png, info);

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

   switch (png_get_color_type (png, info))
     {
      case PNG_COLOR_TYPE_GRAY:
#if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10209)
	if (bit_depth < 8) png_set_expand_gray_1_2_4_to_8 (png);
#else				       /* deprecated */
	if (bit_depth < 8) png_set_gray_1_2_4_to_8 (png);
#endif
	break;
      case PNG_COLOR_TYPE_GRAY_ALPHA:
	/* png_set_gray_to_rgb (png); */
	break;

      case PNG_COLOR_TYPE_PALETTE:
	png_set_palette_to_rgb (png);
	break;
     }

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

   png_read_update_info (png, info);

   color_type = png_get_color_type (png, info);
   switch (color_type)
     {
      case PNG_COLOR_TYPE_RGBA:
	sizeof_type = 4;
	fixup_array_fun = fixup_array_rgba;
	data_type = SLang_get_int_type (32);
	break;

      case PNG_COLOR_TYPE_RGB:
	sizeof_type = 4;
	fixup_array_fun = fixup_array_rgb;
	data_type = SLang_get_int_type (32);
	break;

      case PNG_COLOR_TYPE_GRAY_ALPHA:
	sizeof_type = 2;
	fixup_array_fun = fixup_array_ga;
	data_type = SLang_get_int_type (16);
	break;

      case PNG_COLOR_TYPE_GRAY:
	sizeof_type = 1;
	fixup_array_fun = NULL;
	data_type = SLANG_UCHAR_TYPE;
	break;

      default:
	SLang_verror (SL_Read_Error, "Unsupported PNG color-type");
	free_png_type (p);
	return NULL;
     }
   *color_typep = color_type;

   /* Use the high-level interface */
   rowbytes = png_get_rowbytes (png, info);
   if (rowbytes > width * sizeof_type)
     {
	SLang_verror (SL_INTERNAL_ERROR, "Unexpected value returned from png_get_rowbytes");
	free_png_type (p);
	return NULL;
     }

   if (NULL == (data = (png_byte *) SLmalloc (height * width * sizeof_type)))
     {
	free_png_type (p);
	return NULL;
     }

   if (NULL == (image_pointers = allocate_image_pointers (height, data, width * sizeof_type, flip)))
     {
	SLfree ((char *) data);
	free_png_type (p);
	return NULL;
     }
   png_read_image(png, image_pointers);

   dims[0] = height;
   dims[1] = width;

   if (NULL == (at = SLang_create_array (data_type, 0, (VOID_STAR) data, dims, 2)))
     {
	SLfree ((char *) data);
	free_image_pointers (image_pointers);
	free_png_type (p);
	return NULL;
     }
   free_png_type (p);
   free_image_pointers (image_pointers);
   if (fixup_array_fun != NULL)
     (*fixup_array_fun) (at);
   return at;
}
Exemplo n.º 8
0
static void *
do_png_read(struct png_reader * reader,
	void *(*alloc)(int w, int h, int bpp, void** datap))
{

	png_structp read_ptr;
	png_infop info_ptr;

	TRACE(SYSTEM, "ready to read png stream\n");

	if (reader->read_ptr == NULL) {
		reader->info_ptr = NULL;
		read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
				NULL, png_error, png_warning);
		reader->read_ptr = read_ptr;
	} else {
		read_ptr = reader->read_ptr;
		reader->read_ptr_save = read_ptr;
	}

	if (read_ptr == NULL) {
		ERROR(SYSTEM, "libpng: create read_ptr error\n");
		THROW(EXCEPTION_CONTINUE, "libpng read error");
	}

	if (setjmp(png_jmpbuf(read_ptr))) {
		ERROR(SYSTEM, "libpng: read error\n");
		THROW(EXCEPTION_RESOURCE_LOST, "libpng read error");
	}

	if (reader->info_ptr == NULL) {
		info_ptr = png_create_info_struct(read_ptr);
		reader->info_ptr = info_ptr;
	} else {
		info_ptr = reader->info_ptr;
	}

	png_set_read_fn(read_ptr, reader->io_ptr,
			reader->read_fn);

	/* here: begin read */
	/* code borrowed from SDL_img's IMG_png.c */
	png_uint_32 width, height;
	int bit_depth, color_type, interlace_type;

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

	TRACE(SYSTEM, "png bitmap: %dx%d:%d\n", width, height, bit_depth);

	if (bit_depth > 8)
		png_set_strip_16(read_ptr);
	if (bit_depth < 8)
		png_set_packing(read_ptr);

	if (color_type == PNG_COLOR_TYPE_GRAY) {
		TRACE(SYSTEM, "\tcolor type: PNG_COLOR_TYPE_GRAY\n");
		png_set_expand(read_ptr);
	}

	if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
		TRACE(SYSTEM, "\tcolor type: PNG_COLOR_TYPE_GRAY_ALPHA\n");
		png_set_gray_to_rgb(read_ptr);
	}
    if (color_type == PNG_COLOR_TYPE_PALETTE) {
		TRACE(SYSTEM, "\tcolor type: PNG_COLOR_TYPE_PALETTE\n");
        png_set_palette_to_rgb(read_ptr);
	}

    if (png_get_valid(read_ptr, info_ptr, PNG_INFO_tRNS)) {
		TRACE(SYSTEM, "\tstream has PNG_INFO_tRNS\n");
		png_set_tRNS_to_alpha(read_ptr);
	}

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

	TRACE(SYSTEM, "update png bitmap: %dx%d:%d\n", width, height, bit_depth);

	/* start read */
	if (bit_depth != 8) {
		WARNING(RESOURCE, "We don't support this png stream\n");
		THROW(EXCEPTION_RESOURCE_LOST, "format error");
	}

	int bytes_pp;

	switch (color_type) {
		case PNG_COLOR_TYPE_GRAY:
			TRACE(SYSTEM, "\tcolor type: PNG_COLOR_TYPE_GRAY\n");
			bytes_pp = 1;
			break;
		case PNG_COLOR_TYPE_GRAY_ALPHA:
			TRACE(SYSTEM, "\tcolor type: PNG_COLOR_TYPE_GRAY_ALPHA\n");
			bytes_pp = 2;
			break;
		case PNG_COLOR_TYPE_RGB:
			TRACE(SYSTEM, "\tcolor type: PNG_COLOR_TYPE_RGB\n");
			bytes_pp = 3;
			break;
		case PNG_COLOR_TYPE_RGB_ALPHA:
			TRACE(SYSTEM, "\tcolor type: PNG_COLOR_TYPE_RGB_ALPHA\n");
			bytes_pp = 4;
			break;
		case PNG_COLOR_TYPE_PALETTE:
			WARNING(SYSTEM,
					"PNG_COLOR_TYPE_PALETTE:"
					" I don't know how to read PALETTE png stream...\n");
			if (png_get_valid(read_ptr, info_ptr, PNG_INFO_tRNS))
				bytes_pp = 3;
			else
				bytes_pp = 4;
			break;
		default:
			WARNING(RESOURCE, "We don't support this png stream\n");
			THROW(EXCEPTION_RESOURCE_LOST, "format error");
	};

	/* alloc data */
	void * retval = NULL;
	void * data = NULL;
	retval = alloc(width, height, bytes_pp, &data);
	assert(retval != NULL);
	assert(data != NULL);

	/* start read!! */
	VERBOSE(SYSTEM, "png stream read start\n");
	png_bytep *volatile row_pointers;

	int row;
#ifdef HAVE_ALLOCA
	row_pointers = (png_bytep*)alloca(sizeof(png_bytep)*height);
#else
	row_pointers = (png_bytep*)xmalloc(sizeof(png_bytep)*height);
	reader->row_pointers = row_pointers;
#endif
	assert(row_pointers != NULL);

	for (row = 0; row < (int)height; row++) {
		row_pointers[row] = (png_bytep)(
				(uint8_t*)(data + ((int)height-row) * bytes_pp * width));
	}
	png_read_image(read_ptr, row_pointers);

#ifndef HAVE_ALLOCA
	GC_FREE_BLOCK_SET(row_pointers);
	reader->row_pointers = NULL;
#endif

	return retval;
}
Exemplo n.º 9
0
ImageData PNGImageCodec::Load(InputStreamPtr& file, const ImageParams& params,
		ImageCodecMetaInfo& metaInfo) {
	InputStream* readr = file.GetPtr();
	// check if png_ptr
	if (!CheckIfPng(readr)) {
		Warn(String("Image file format is not png: ") + params.name);
	}

	png_structp png_ptr;
	png_infop info_ptr;
	png_uint_32 width, height;
	int bit_depth, color_type;
	bool alpha;
	Color32 keycolor;
	int keycolor_index = -1;
	bool hascolorkey = false;

	ImageType imagetype;

	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
	if (png_ptr == NULL) {
		Error("Could not create read struct");
		NEX_THROW_GracefulError(EXCEPT_INVALID_CALL);
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL) {
		png_destroy_read_struct(&png_ptr, NULL, NULL);
		Error("Could not create info struct");
		NEX_THROW_GracefulError(EXCEPT_INVALID_CALL);
	}

	png_set_error_fn(png_ptr, (void *) (readr), PngWarn, PngWarn);
	png_set_read_fn(png_ptr, (void *) (readr), PngReadFile);

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

	// todo Unstrip
	png_set_strip_16(png_ptr);

	if (bit_depth != 8 && bit_depth != 16) {
		Error("Unsupported bit depth");
		NEX_THROW_GracefulError(EXCEPT_INVALID_CALL);
	}

	switch (color_type) {
	case PNG_COLOR_TYPE_GRAY:
	case PNG_COLOR_TYPE_GRAY_ALPHA:
		if (color_type & PNG_COLOR_MASK_ALPHA)
			imagetype = GrayAlpha;
		else {
			imagetype = Palleted;
			png_set_strip_alpha(png_ptr);
			if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
				png_color_16p trans_values;
				png_get_tRNS(png_ptr, info_ptr, 0, 0, &trans_values);
				hascolorkey = true;
				keycolor.red = uint8(trans_values->gray) & 0xff;
				keycolor.green = uint8(trans_values->gray) & 0xff;
				keycolor.blue = uint8(trans_values->gray) & 0xff;
				keycolor.alpha = uint8(trans_values->gray) & 0xff;
			}

		}
		break;
	case PNG_COLOR_TYPE_PALETTE:
		imagetype = Palleted;
		alpha = true;
		if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
			// tRNS chunk. Every palette entry gets its own alpha value.
			png_bytep trans;
			int num_trans;
			png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, 0);

			// see if there is a single entry w/ alpha==0 and all other 255.
			// if yes use keycolor transparency.
			bool only_binary_trans = true;
			for (int32 i = 0; (i < num_trans) && only_binary_trans; i++) {
				if (trans[i] != 0xff) {
					only_binary_trans = only_binary_trans && (trans[i] == 0)
							&& (keycolor_index == -1);
					keycolor_index = i;
				}
			}
			if (!only_binary_trans) {
				keycolor_index = -1;
				png_set_palette_to_rgb(png_ptr);
				png_set_tRNS_to_alpha(png_ptr);
				imagetype = RGBImage;
			} else
				alpha = false;
		} else
			alpha = false;

		break;
	case PNG_COLOR_TYPE_RGBA:
		alpha = true;
	case PNG_COLOR_TYPE_RGB:
		imagetype = RGBImage;
		if (!(color_type & PNG_COLOR_MASK_ALPHA)) {
			alpha = false;
			if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
				png_color_16p trans_values;
				png_get_tRNS(png_ptr, info_ptr, 0, 0, &trans_values);
				hascolorkey = true;
				keycolor.red = uint8((trans_values->red) & 0xff);
				keycolor.green = uint8((trans_values->green) & 0xff);
				keycolor.blue = uint8((trans_values->blue) & 0xff);
			}
		}
		break;
	}

	// setup gamma
	//@ TODO: add code to retrieve the gamma here
	double screen_gamma = 0; //X_SharedPtr(iSystem)->getUserGamma();
	// and comment this
	screen_gamma = 2.2;

	int intent;

	if (png_get_sRGB(png_ptr, info_ptr, &intent))
		png_set_gamma(png_ptr, screen_gamma, 0.45455);
	else {
		double image_gamma;
		if (png_get_gAMA(png_ptr, info_ptr, &image_gamma))
			png_set_gamma(png_ptr, screen_gamma, image_gamma);
		else
			png_set_gamma(png_ptr, screen_gamma, 0.45455);
	}

	/* todo Unstrip this */
	if (bit_depth > 8) {
		// tell libpng to strip 16 bit/color files down to 8 bits/color
		png_set_strip_16(png_ptr);
		bit_depth = 8;
	} else if (bit_depth < 8)
		// Expand pictures with less than 8bpp to 8bpp
		png_set_packing(png_ptr);

	// update
	png_read_update_info(png_ptr, info_ptr);
	png_uint_32 bytes_per_row = (png_uint_32)png_get_rowbytes(png_ptr, info_ptr);

	//png_read_image
	PixelFormat fmt;
	uint32 bpp = 1;
	// we dont support anything else
	// other than RGBImage right now
	// so!

	if (imagetype == RGBImage) {
		fmt = PixelFormat::RGBA8;
		bpp = 4;
	} else if (imagetype == GrayAlpha && bytes_per_row == 1)
		fmt = PixelFormat::R8;
	else { // pallete
		   // cant handle this
		Warn(String("PixelFormat not supported.") + params.name);
		NEX_THROW_GracefulError(EXCEPT_INVALID_CALL);
	}

	int numPass = png_set_interlace_handling(png_ptr);

	ImageData img;
	uint8* imgDest = (uint8*) NEX_ALLOC(bpp * height * width, MEMCAT_GENERAL);
	img.data = imgDest;
	img.format = fmt;
	metaInfo.metaInfoInited = true;
	metaInfo.mipLevelsToRead = 0;
	metaInfo.metaInfo.maxDepth = img.depth = 1;
	metaInfo.metaInfo.maxHeight = img.height = (uint16) height;
	metaInfo.metaInfo.maxWidth = img.width = (uint16) width;
	metaInfo.metaInfo.maxMipMapCount = img.numMipMaps = 1;
	img.numFaces = 1;

	uint8* imgRows = 0;
	if (numPass > 1) {
		imgRows = (uint8*) NEX_ALLOC(bytes_per_row * height, MEMCAT_GENERAL);
	} else
		imgRows = (uint8*) NEX_ALLOC(bytes_per_row, MEMCAT_GENERAL);

	uint32 srcBpp = bytes_per_row / width;

	for (uint32 i = 0; (int32) i < numPass; ++i) {
		for (uint32 y = 0; y < height; y++) {
			uint8* rowPtr = numPass > 1 ? imgRows + bytes_per_row * y : imgRows;
			png_read_row(png_ptr, rowPtr, NULL);

			// write only once
			if (i == numPass - 1) {
				for (uint32 x = 0; x < width; x++) {
					// bgra
					switch (fmt) {
					case PixelFormat::RGBA8:

						imgDest[0] = rowPtr[0];
						imgDest[1] = rowPtr[1];
						imgDest[2] = rowPtr[2];
						if (alpha)
							imgDest[3] = rowPtr[3];
						else
							imgDest[3] = 0xff;
						break;
					case PixelFormat::R8:
						imgDest[0] = rowPtr[0];
						break;
					}
					imgDest += bpp;
					rowPtr += srcBpp;
				}
			}
		}
	}

	png_read_end(png_ptr, (png_infop) 0);
	png_destroy_read_struct(&png_ptr, NULL, NULL);
	NEX_FREE(imgRows, MEMCAT_GENERAL);

	if (hascolorkey) {
		imgDest = (uint8*) img.data;

		for (uint32 y = 0; y < height; y++) {
			for (uint32 x = 0; x < width; x++) {
				switch (fmt) {
				case PixelFormat::RGBA8:
					if (imgDest[0] == keycolor.red
							&& imgDest[1] == keycolor.green
							&& imgDest[2] == keycolor.blue)
						imgDest[3] = 0;
					break;
				case PixelFormat::R8:
					if (imgDest[0] == keycolor.alpha)
						imgDest[0] = 0;
					break;
				}
				imgDest += bpp;
			}

		}
	}

	return img;
}
Exemplo n.º 10
0
/* Read a png header.
 */
static int
png2vips_header( Read *read, VipsImage *out )
{
	png_uint_32 width, height;
	int bit_depth, color_type;
	int interlace_type;

	png_uint_32 res_x, res_y;
	int unit_type;

	png_charp name;
	int compression_type;

	/* Well thank you, libpng.
	 */
#if PNG_LIBPNG_VER < 10400
	png_charp profile;
#else
	png_bytep profile;
#endif

	png_uint_32 proflen;

	int bands; 
	VipsInterpretation interpretation;
	double Xres, Yres;

	if( setjmp( png_jmpbuf( read->pPng ) ) ) 
		return( -1 );

	png_get_IHDR( read->pPng, read->pInfo, 
		&width, &height, &bit_depth, &color_type,
		&interlace_type, NULL, NULL );

	/* png_get_channels() gives us 1 band for palette images ... so look
	 * at colour_type for output bands.
	 *
	 * Ignore alpha, we detect that separately below.
	 */
	switch( color_type ) {
	case PNG_COLOR_TYPE_PALETTE: 
		bands = 3; 
		break;

	case PNG_COLOR_TYPE_GRAY_ALPHA: 
	case PNG_COLOR_TYPE_GRAY: 
		bands = 1; 
		break;

	case PNG_COLOR_TYPE_RGB: 
	case PNG_COLOR_TYPE_RGB_ALPHA: 
		bands = 3; 
		break;

	default:
		vips_error( "png2vips", "%s", _( "unsupported color type" ) );
		return( -1 );
	}

	if( bit_depth > 8 ) {
		if( bands < 3 )
			interpretation = VIPS_INTERPRETATION_GREY16;
		else
			interpretation = VIPS_INTERPRETATION_RGB16;
	}
	else {
		if( bands < 3 )
			interpretation = VIPS_INTERPRETATION_B_W;
		else
			interpretation = VIPS_INTERPRETATION_sRGB;
	}

	/* Expand palette images.
	 */
	if( color_type == PNG_COLOR_TYPE_PALETTE )
		png_set_palette_to_rgb( read->pPng );

	/* Expand transparency.
	 */
	if( png_get_valid( read->pPng, read->pInfo, PNG_INFO_tRNS ) ) {
		png_set_tRNS_to_alpha( read->pPng );
		bands += 1;
	}
	else if( color_type == PNG_COLOR_TYPE_GRAY_ALPHA || 
		color_type == PNG_COLOR_TYPE_RGB_ALPHA ) {
		/* Some images have no transparency chunk, but still set
		 * color_type to alpha.
		 */
		bands += 1;
	}

	/* Expand <8 bit images to full bytes.
	 */
	if( color_type == PNG_COLOR_TYPE_GRAY &&
		bit_depth < 8 ) 
		png_set_expand_gray_1_2_4_to_8( read->pPng );

	/* If we're an INTEL byte order machine and this is 16bits, we need
	 * to swap bytes.
	 */
	if( bit_depth > 8 && 
		!vips_amiMSBfirst() )
		png_set_swap( read->pPng );

	/* Get resolution. Default to 72 pixels per inch, the usual png value. 
	 */
	unit_type = PNG_RESOLUTION_METER;
	res_x = (72 / 2.54 * 100);
	res_y = (72 / 2.54 * 100);
	png_get_pHYs( read->pPng, read->pInfo, &res_x, &res_y, &unit_type );
	switch( unit_type ) {
	case PNG_RESOLUTION_METER:
		Xres = res_x / 1000.0;
		Yres = res_y / 1000.0;
		break;
	
	default:
		Xres = res_x;
		Yres = res_y;
		break;
	}

	/* Set VIPS header.
	 */
	vips_image_init_fields( out,
		width, height, bands,
		bit_depth > 8 ? 
			VIPS_FORMAT_USHORT : VIPS_FORMAT_UCHAR,
		VIPS_CODING_NONE, interpretation, 
		Xres, Yres );

	/* Sequential mode needs thinstrip to work with things like
	 * vips_shrink().
	 */
        vips_image_pipelinev( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );

	/* Fetch the ICC profile. @name is useless, something like "icc" or
	 * "ICC Profile" etc.  Ignore it.
	 *
	 * @profile was png_charpp in libpngs < 1.5, png_bytepp is the
	 * modern one. Ignore the warning, if any.
	 */
	if( png_get_iCCP( read->pPng, read->pInfo, 
		&name, &compression_type, &profile, &proflen ) ) {
		void *profile_copy;

#ifdef DEBUG
		printf( "png2vips_header: attaching %zd bytes of ICC profile\n",
			proflen );
		printf( "png2vips_header: name = \"%s\"\n", name );
#endif /*DEBUG*/

		if( !(profile_copy = vips_malloc( NULL, proflen )) ) 
			return( -1 );
		memcpy( profile_copy, profile, proflen );
		vips_image_set_blob( out, VIPS_META_ICC_NAME, 
			(VipsCallbackFn) vips_free, profile_copy, proflen );
	}

	/* Sanity-check line size.
	 */
	png_read_update_info( read->pPng, read->pInfo );
	if( png_get_rowbytes( read->pPng, read->pInfo ) != 
		VIPS_IMAGE_SIZEOF_LINE( out ) ) {
		vips_error( "vipspng", 
			"%s", _( "unable to read PNG header" ) );
		return( -1 );
	}

	return( 0 );
}
Exemplo n.º 11
0
/** 从本地磁盘中加载图像
@Param 图像文件的路径
*/
F3DImage* F3DPNGCodec::Load( const char* filename )
{
    F3DImage* image;

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

    FBYTE** row_pointers;
    png_byte buffer[8];

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return image;
}
Exemplo n.º 12
0
bool
loadPngFile(
    IMAGE_T* image,
    FILE *file)
{
    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
                                                 NULL,
                                                 NULL,
                                                 NULL);

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

    png_infop info_ptr = png_create_info_struct(png_ptr);

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

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

    //---------------------------------------------------------------------

    png_init_io(png_ptr, file);

    png_read_info(png_ptr, info_ptr);

    //---------------------------------------------------------------------

    png_byte colour_type = png_get_color_type(png_ptr, info_ptr);
    png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);

    VC_IMAGE_TYPE_T type = VC_IMAGE_RGB888;

    if (colour_type & PNG_COLOR_MASK_ALPHA)
    {
        type = VC_IMAGE_RGBA32;
    }

    initImage(image,
              type,
              png_get_image_width(png_ptr, info_ptr),
              png_get_image_height(png_ptr, info_ptr),
              false);

    //---------------------------------------------------------------------

    double gamma = 0.0;

    if (png_get_gAMA(png_ptr, info_ptr, &gamma))
    {
        png_set_gamma(png_ptr, 2.2, gamma);
    }

    //---------------------------------------------------------------------

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

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

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

    if (bit_depth == 16)
    {
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
        png_set_scale_16(png_ptr);
#else
        png_set_strip_16(png_ptr);
#endif
    }

    if (colour_type == PNG_COLOR_TYPE_GRAY ||
        colour_type == PNG_COLOR_TYPE_GRAY_ALPHA)
    {
        png_set_gray_to_rgb(png_ptr);
    }

    //---------------------------------------------------------------------

    png_read_update_info(png_ptr, info_ptr);

    //---------------------------------------------------------------------

    png_bytepp row_pointers = malloc(image->height * sizeof(png_bytep));

    png_uint_32 j = 0;
    for (j = 0 ; j < image->height ; ++j)
    {
        row_pointers[j] = image->buffer + (j * image->pitch);
    }

    //---------------------------------------------------------------------

    png_read_image(png_ptr, row_pointers);

    //---------------------------------------------------------------------

    free(row_pointers);

    png_destroy_read_struct(&png_ptr, &info_ptr, 0);

    return true;
}
Exemplo n.º 13
0
	Image* Image::_loadPng(hsbase& stream, int size)
	{
		png_structp pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
		png_infop infoPtr = png_create_info_struct(pngPtr);
		png_infop endInfo = png_create_info_struct(pngPtr);
		setjmp(png_jmpbuf(pngPtr));
		png_set_read_fn(pngPtr, &stream, &_pngZipRead);
		png_read_info(pngPtr, infoPtr);
		png_get_IHDR(pngPtr, infoPtr, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
		png_set_interlace_handling(pngPtr);
		int bpp = pngPtr->channels;
		if (pngPtr->color_type == PNG_COLOR_TYPE_PALETTE)
		{
			png_set_palette_to_rgb(pngPtr);
			bpp = 3;
		}
		if (pngPtr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && bpp > 1)
		{
			png_set_strip_alpha(pngPtr);
			bpp -= 1;
		}
		if (png_get_valid(pngPtr, infoPtr, PNG_INFO_tRNS))
		{
			png_set_tRNS_to_alpha(pngPtr);
			++bpp;
		}
		if (pngPtr->bit_depth == 16)
		{
			png_set_strip_16(pngPtr);
		}
		png_read_update_info(pngPtr, infoPtr);
		int rowBytes = png_get_rowbytes(pngPtr, infoPtr);
		png_byte* imageData = new png_byte[rowBytes * pngPtr->height];
		png_bytep* rowPointers = new png_bytep[pngPtr->height];
		for_itert (unsigned int, i, 0, pngPtr->height)
		{
			rowPointers[i] = imageData + i * rowBytes;
		}
		png_read_image(pngPtr, rowPointers);
		png_read_end(pngPtr, infoPtr);
		// assign Image data
		Image* image = new Image();
		image->data = (unsigned char*)imageData;
		image->w = pngPtr->width;
		image->h = pngPtr->height;
		switch (bpp)
		{
		case 4:
			image->format = FORMAT_RGBA;
			break;
		case 3:
			image->format = FORMAT_RGB;
			break;
		case 1:
			image->format = FORMAT_ALPHA;
			break;
		default:
			image->format = FORMAT_RGBA; // TODOaa - maybe palette should go here
			break;
		}
		// clean up
		png_destroy_read_struct(&pngPtr, &infoPtr, &endInfo);
		delete [] rowPointers;
		return image;
	}
Exemplo n.º 14
0
/**
Configure the decoder so that decoded pixels are compatible with a FREE_IMAGE_TYPE format. 
Set conversion instructions as needed. 
@param png_ptr PNG handle
@param info_ptr PNG info handle
@param flags Decoder flags
@param output_image_type Returned FreeImage converted image type
@return Returns TRUE if successful, returns FALSE otherwise
@see png_read_update_info
*/
static BOOL 
ConfigureDecoder(png_structp png_ptr, png_infop info_ptr, int flags, FREE_IMAGE_TYPE *output_image_type) {
	// get original image info
	const int color_type = png_get_color_type(png_ptr, info_ptr);
	const int bit_depth = png_get_bit_depth(png_ptr, info_ptr);
	const int pixel_depth = bit_depth * png_get_channels(png_ptr, info_ptr);

	FREE_IMAGE_TYPE image_type = FIT_BITMAP;	// assume standard image type

	// check for transparency table or single transparent color
	BOOL bIsTransparent = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) == PNG_INFO_tRNS ? TRUE : FALSE;

	// check allowed combinations of colour type and bit depth
	// then get converted FreeImage type

	switch(color_type) {
		case PNG_COLOR_TYPE_GRAY:		// color type '0', bitdepth = 1, 2, 4, 8, 16
			switch(bit_depth) {
				case 1:
				case 2:
				case 4:
				case 8:
					// expand grayscale images to the full 8-bit from 2-bit/pixel
					if (pixel_depth == 2) {
						png_set_expand_gray_1_2_4_to_8(png_ptr);
					}

					// if a tRNS chunk is provided, we must also expand the grayscale data to 8-bits,
					// this allows us to make use of the transparency table with existing FreeImage methods
					if (bIsTransparent && (pixel_depth < 8)) {
						png_set_expand_gray_1_2_4_to_8(png_ptr);
					}
					break;

				case 16:
					image_type = (pixel_depth == 16) ? FIT_UINT16 : FIT_UNKNOWN;

					// 16-bit grayscale images can contain a transparent value (shade)
					// if found, expand the transparent value to a full alpha channel
					if (bIsTransparent && (image_type != FIT_UNKNOWN)) {
						// expand tRNS to a full alpha channel
						png_set_tRNS_to_alpha(png_ptr);
						
						// expand new 16-bit gray + 16-bit alpha to full 64-bit RGBA
						png_set_gray_to_rgb(png_ptr);

						image_type = FIT_RGBA16;
					}
					break;

				default:
					image_type = FIT_UNKNOWN;
					break;
			}
			break;

		case PNG_COLOR_TYPE_RGB:		// color type '2', bitdepth = 8, 16
			switch(bit_depth) {
				case 8:
					image_type = (pixel_depth == 24) ? FIT_BITMAP : FIT_UNKNOWN;
					break;
				case 16:
					image_type = (pixel_depth == 48) ? FIT_RGB16 : FIT_UNKNOWN;
					break;
				default:
					image_type = FIT_UNKNOWN;
					break;
			}
			// sometimes, 24- or 48-bit images may contain transparency information
			// check for this use case and convert to an alpha-compatible format
			if (bIsTransparent && (image_type != FIT_UNKNOWN)) {
				// if the image is 24-bit RGB, mark it as 32-bit; if it is 48-bit, mark it as 64-bit
				image_type = (pixel_depth == 24) ? FIT_BITMAP : (pixel_depth == 48) ? FIT_RGBA16 : FIT_UNKNOWN;
				// expand tRNS chunk to alpha channel
				png_set_tRNS_to_alpha(png_ptr);
			}
			break;

		case PNG_COLOR_TYPE_PALETTE:	// color type '3', bitdepth = 1, 2, 4, 8
			switch(bit_depth) {
				case 1:
				case 2:
				case 4:
				case 8:
					// expand palette images to the full 8 bits from 2 bits/pixel
					if (pixel_depth == 2) {
						png_set_packing(png_ptr);
					}

					// if a tRNS chunk is provided, we must also expand the palletized data to 8-bits,
					// this allows us to make use of the transparency table with existing FreeImage methods
					if (bIsTransparent && (pixel_depth < 8)) {
						png_set_packing(png_ptr);
					}
					break;

				default:
					image_type = FIT_UNKNOWN;
					break;
			}
			break;

		case PNG_COLOR_TYPE_GRAY_ALPHA:	// color type '4', bitdepth = 8, 16
			switch(bit_depth) {
				case 8:
					// 8-bit grayscale + 8-bit alpha => convert to 32-bit RGBA
					image_type = (pixel_depth == 16) ? FIT_BITMAP : FIT_UNKNOWN;
					break;
				case 16:
					// 16-bit grayscale + 16-bit alpha => convert to 64-bit RGBA
					image_type = (pixel_depth == 32) ? FIT_RGBA16 : FIT_UNKNOWN;
					break;
				default:
					image_type = FIT_UNKNOWN;
					break;
			}
			// expand 8-bit greyscale + 8-bit alpha to 32-bit
			// expand 16-bit greyscale + 16-bit alpha to 64-bit
			png_set_gray_to_rgb(png_ptr);
			break;

		case PNG_COLOR_TYPE_RGB_ALPHA:	// color type '6', bitdepth = 8, 16
			switch(bit_depth) {
				case 8:
					break;
				case 16:
					image_type = (pixel_depth == 64) ? FIT_RGBA16 : FIT_UNKNOWN;
					break;
				default:
					image_type = FIT_UNKNOWN;
					break;
			}
			break;
	}

	// check for unknown or invalid formats
	if(image_type == FIT_UNKNOWN) {
		*output_image_type = image_type;
		return FALSE;
	}

#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						

#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
	if((image_type == FIT_BITMAP) && ((color_type == PNG_COLOR_TYPE_RGB) || (color_type == PNG_COLOR_TYPE_RGB_ALPHA))) {
		// flip the RGB pixels to BGR (or RGBA to BGRA)
		png_set_bgr(png_ptr);
	}
#endif

	// gamma correction
	// 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);

	// return the output image type
	*output_image_type = image_type;

	return TRUE;
}
Exemplo n.º 15
0
//! @brief PNGファイルを読み込みます
//!
//! @param[in] filename ファイル名
//! @param[out] outTextureWidth 読み込んだテクスチャの幅
//! @param[out] outTextureWidth 読み込んだテクスチャの高さ
//!
//! @return 32bit非圧縮RGBAバイトデータ配列
EEbuffer EECFileIO::LoadPngFile(
    crEEstring filename,
    pEEuint    outTextureWidth,
    pEEuint    outTextureHeight
    ) {

    // ファイルポインタを取得する
    FILE *file = NULL;
    _tfopen_s(&file, filename.c_str(), _T("rb"));
    
    if( file == NULL ) {
        __EEDEF_DEBUG_ERROR(__EEDEF_FUNCTION_NAME, _EESTR("fail file open."));
        return EEbuffer();
    }

    // PNGのシグネチャをチェックする
    EEubyte header[8] = { };
    size_t header_size = sizeof(header);
    fread_s(header, header_size, header_size, 1, file);

    if( png_sig_cmp(header, 0, header_size) != 0) {
        fclose(file);
        __EEDEF_DEBUG_ERROR(__EEDEF_FUNCTION_NAME, _EESTR("unknown signature."));
        return EEbuffer();
    }

    // PNG構造体を初期化する
    png_structp png_ptr = png_create_read_struct(
        PNG_LIBPNG_VER_STRING,      // 使用するlibpngのバージョン
        (png_voidp)NULL,            // 使用する構造体
        (png_error_ptr)NULL,        // エラー用関数ポインタ
        (png_error_ptr)NULL         // 警告用関数ポインタ
        );

    if( png_ptr == NULL ) {
        fclose(file);
        __EEDEF_DEBUG_ERROR(__EEDEF_FUNCTION_NAME, _EESTR("unknown structure."));
        return EEbuffer();
    }

    // ヘッダー情報のチャンクを初期化する
    png_infop info_ptr = png_create_info_struct(png_ptr);

    if( info_ptr == NULL ) {
        png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
        fclose(file);
        __EEDEF_DEBUG_ERROR(__EEDEF_FUNCTION_NAME, _EESTR("unknown header info."));
        return EEbuffer();
    }

    // フッター情報のチャンクを初期化する
    png_infop end_info = png_create_info_struct(png_ptr);

    if( end_info == NULL ) {
        png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
        fclose(file);
        __EEDEF_DEBUG_ERROR(__EEDEF_FUNCTION_NAME, _EESTR("unknown footer info."));
        return EEbuffer();
    }

    // ファイルポインタをライブラリに設定する
    png_init_io(png_ptr, file);

    // シグネチャのチェックを行った場合は、データを読み込む前にその通知をする
    png_set_sig_bytes(png_ptr, header_size);

    // ヘッダ情報を読み込む
    png_read_info(png_ptr, info_ptr);

    png_uint_32 png_width       = 0;
    png_uint_32 png_height      = 0;
    EEint       png_bit_depth   = 0;
    EEint       png_color_type  = 0;

    // IHDRチャンク情報を読み込む
    png_get_IHDR(
        png_ptr,                // PNG構造体
        info_ptr,               // ヘッダー情報チャンク
        &png_width,             // [出力] 画像の幅
        &png_height,            // [出力] 画像の高さ
        &png_bit_depth,         // [出力] ビット深度
        &png_color_type,        // [出力] カラータイプ
        NULL,                   // 
        NULL,                   // 
        NULL                    // 
        );

    if( png_bit_depth == 1 || png_bit_depth == 2 || png_bit_depth == 4 ) {
        // 1,2,4bit → 8bit
        png_set_packing(png_ptr);

    } else if( png_bit_depth == 16 ) {
        // 16bit → 8bit
        png_set_strip_16(png_ptr);
    }

    if( png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ) {
        // tRNSチャンクがある → アルファチャンネルに変換
        png_set_tRNS_to_alpha(png_ptr);
    } else if ( !IS_BIT_STAND(png_color_type, PNG_COLOR_MASK_ALPHA) ) {
        // アルファチャンネルがない → アルファチャンネルを追加
        png_set_add_alpha(png_ptr, 255, PNG_FILLER_AFTER);

    }

    if ( IS_BIT_STAND(png_color_type, PNG_COLOR_MASK_PALETTE) ) {
        // カラーパレットがある → RGBフルカラーへ変換
        png_set_palette_to_rgb(png_ptr);
    }
    if ( !IS_BIT_STAND(png_color_type, PNG_COLOR_MASK_COLOR) ) {
        // グレースケールである → RGBフルカラーへ変換
        png_set_gray_to_rgb(png_ptr);
    }

    // 変換を反映する
    png_read_update_info(png_ptr, info_ptr);

    // 領域の確保
    png_size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr);
    EEbuffer returnBuffer(rowbytes * png_height);

    // 行配列にデータを取得する
    png_bytepp image_row_pointer = new png_bytep[png_height];

    for( png_uint_32 i = 0; i < png_height; i++ ) {
        image_row_pointer[i] = &returnBuffer[i * rowbytes];
    }
    
    png_read_image(png_ptr, image_row_pointer);

    delete[] image_row_pointer;

    // 不要になったデータを破棄
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    fclose(file);

    // 出力
    __EEDEF_DEBUG_MESSAGE(__EEDEF_FUNCTION_NAME, _EESTR("success."));
    if( outTextureWidth  != EENULL ) *outTextureWidth  = png_width;
    if( outTextureHeight != EENULL ) *outTextureHeight = png_height;
    return returnBuffer;
}
Exemplo n.º 16
0
void png::load(const std::string& file_name)
{
    // unfortunately, we need to break down to the C-code level here, since
    // libpng is written in C itself

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

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

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

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

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

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

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

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

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

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

    png_read_update_info(png_ptr, info_ptr);

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

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

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

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

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

    // cleanup
    delete[] row;
    png_read_end(png_ptr, nullptr);
    png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
    fclose(fp);
}
Exemplo n.º 17
0
/* Read a PNG file.  You may want to return an error code if the read
 * fails (depending upon the failure).  There are two "prototypes" given
 * here - one where we are given the filename, and we need to open the
 * file, and the other where we are given an open file (possibly with
 * some or all of the magic bytes read - see comments above).
 */
#ifdef open_file /* prototype 1 */
void read_png(char *file_name)  /* We need to open the file */
{
   png_structp png_ptr;
   png_infop info_ptr;
   unsigned int sig_read = 0;
   png_uint_32 width, height;
   int bit_depth, color_type, interlace_type;
   FILE *fp;

   if ((fp = fopen(file_name, "rb")) == NULL)
      return (ERROR);
#else no_open_file /* prototype 2 */
void read_png(FILE *fp, unsigned int sig_read)  /* file is already open */
{
   png_structp png_ptr;
   png_infop info_ptr;
   png_uint_32 width, height;
   int bit_depth, color_type, interlace_type;
#endif no_open_file /* only use one prototype! */

   /* 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,
      png_voidp user_error_ptr, user_error_fn, user_warning_fn);

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

   /* 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 (ERROR);
   }

   /* 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 (ERROR);
   }

   /* One of the following I/O initialization methods is REQUIRED */
#ifdef streams /* PNG file I/O method 1 */
   /* Set up the input control if you are using standard C streams */
   png_init_io(png_ptr, fp);

#else no_streams /* PNG file I/O method 2 */
   /* If you are using replacement read functions, instead of calling
    * png_init_io() here you would call:
    */
   png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn);
   /* where user_io_ptr is a structure you want available to the callbacks */
#endif no_streams /* Use only one I/O method! */

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

#ifdef hilevel
   /*
    * 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_read_png(png_ptr, info_ptr, png_transforms, png_voidp_NULL);
#else
   /* OK, you're doing it the hard way, with the lower-level functions */

   /* The call to png_read_info() gives us all of the information from the
    * PNG file before the first IDAT (image data chunk).  REQUIRED
    */
   png_read_info(png_ptr, info_ptr);

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

/* Set up the data transformations you want.  Note that these are all
 * optional.  Only call them if you want/need them.  Many of the
 * transformations only work on specific types of images, and many
 * are mutually exclusive.
 */

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

   /* Strip alpha bytes from the input data without combining with the
    * background (not recommended).
    */
   png_set_strip_alpha(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);

   /* Change the order of packed pixels to least significant bit first
    * (not useful if you are using png_set_packing). */
   png_set_packswap(png_ptr);

   /* Expand paletted colors into true RGB triplets */
   if (color_type == PNG_COLOR_TYPE_PALETTE)
      png_set_palette_to_rgb(png_ptr);

   /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
   if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
      png_set_expand_gray_1_2_4_to_8(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))
      png_set_tRNS_to_alpha(png_ptr);

   /* Set the background color to draw transparent and alpha images over.
    * It is possible to set the red, green, and blue components directly
    * for paletted images instead of supplying a palette index.  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_16 my_background, *image_background;

   if (png_get_bKGD(png_ptr, info_ptr, &image_background))
      png_set_background(png_ptr, image_background,
                         PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
   else
      png_set_background(png_ptr, &my_background,
                         PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);

   /* Some suggestions as to how to get a screen gamma value */

   /* Note that screen gamma is the display_exponent, which includes
    * the CRT_exponent and any correction for viewing conditions */
   if (/* We have a user-defined screen gamma value */)
   {
      screen_gamma = user-defined screen_gamma;
   }
   /* This is one way that applications share the same screen gamma value */
   else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL)
Exemplo n.º 18
0
static int ReadPNG(FILE* in_file, WebPPicture* const pic, int keep_alpha) {
  png_structp png;
  png_infop info;
  int color_type, bit_depth, interlaced;
  int has_alpha;
  int num_passes;
  int p;
  int ok = 0;
  png_uint_32 width, height, y;
  int stride;
  uint8_t* rgb = NULL;

  png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
  if (png == NULL) {
    goto End;
  }

  png_set_error_fn(png, 0, error_function, NULL);
  if (setjmp(png_jmpbuf(png))) {
 Error:
    png_destroy_read_struct(&png, NULL, NULL);
    if (rgb) free(rgb);
    goto End;
  }

  info = png_create_info_struct(png);
  if (info == NULL) goto Error;

  png_init_io(png, in_file);
  png_read_info(png, info);
  if (!png_get_IHDR(png, info,
                    &width, &height, &bit_depth, &color_type, &interlaced,
                    NULL, NULL)) goto Error;

  png_set_strip_16(png);
  png_set_packing(png);
  if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png);
  if (color_type == PNG_COLOR_TYPE_GRAY) {
    if (bit_depth < 8) {
      png_set_expand_gray_1_2_4_to_8(png);
    }
    png_set_gray_to_rgb(png);
  }
  if (png_get_valid(png, info, PNG_INFO_tRNS)) {
    png_set_tRNS_to_alpha(png);
    has_alpha = 1;
  } else {
    has_alpha = !!(color_type & PNG_COLOR_MASK_ALPHA);
  }

  if (!keep_alpha) {
    png_set_strip_alpha(png);
    has_alpha = 0;
  }
#ifdef WEBP_EXPERIMENTAL_FEATURES
  if (has_alpha) {
    pic->colorspace |= WEBP_CSP_ALPHA_BIT;
  }
#endif

  num_passes = png_set_interlace_handling(png);
  png_read_update_info(png, info);
  stride = (has_alpha ? 4 : 3) * width * sizeof(*rgb);
  rgb = (uint8_t*)malloc(stride * height);
  if (rgb == NULL) goto Error;
  for (p = 0; p < num_passes; ++p) {
    for (y = 0; y < height; ++y) {
      png_bytep row = rgb + y * stride;
      png_read_rows(png, &row, NULL, 1);
    }
  }
  png_read_end(png, info);
  png_destroy_read_struct(&png, &info, NULL);

  pic->width = width;
  pic->height = height;
  ok = has_alpha ? WebPPictureImportRGBA(pic, rgb, stride)
                 : WebPPictureImportRGB(pic, rgb, stride);
  free(rgb);

 End:
  return ok;
}
Exemplo n.º 19
0
 void set_tRNS_to_alpha() const
 {
     TRACE_IO_TRANSFORM("png_set_tRNS_to_alpha\n");
     png_set_tRNS_to_alpha(m_png);
 }
Exemplo n.º 20
0
bool Cc3dImage::_initWithPngData(void * pData, int nDatalen)
{
// length of bytes to check if it is a valid png file
#define PNGSIGSIZE  8
    bool bRet = false;
    png_byte        header[PNGSIGSIZE]   = {0}; 
    png_structp     png_ptr     =   0;
    png_infop       info_ptr    = 0;

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

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

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

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


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

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

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

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

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

        bRet = true;
    } while (0);

    if (png_ptr)
    {
        png_destroy_read_struct(&png_ptr, (info_ptr) ? &info_ptr : 0, 0);
    }
    return bRet;
}
Exemplo n.º 21
0
GLuint MaterialLibrary::loadImage(const char *filename)
{
	GLuint texture;
	png_structp png_ptr = NULL;
	png_infop info_ptr = NULL;
	png_bytep *row_pointers = NULL;
	int bitDepth, colourType;

	FILE *pngFile;
	fopen_s(&pngFile, filename, "rb");

	if(!pngFile)
		return 0;

	png_byte sig[8];

	fread(&sig, 8, sizeof(png_byte), pngFile);
	rewind(pngFile);
	if(!png_check_sig(sig, 8))
		return 0;

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

	if(!png_ptr)
		return 0;

	if(setjmp(png_jmpbuf(png_ptr)))
		return 0;

	info_ptr = png_create_info_struct(png_ptr);

	if(!info_ptr)
		return 0;

	png_init_io(png_ptr, pngFile);

	png_read_info(png_ptr, info_ptr);

	bitDepth = png_get_bit_depth(png_ptr, info_ptr);

	colourType = png_get_color_type(png_ptr, info_ptr);

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

	if(colourType == PNG_COLOR_TYPE_GRAY && 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);
	else if(bitDepth < 8)
		png_set_packing(png_ptr);

	png_read_update_info(png_ptr, info_ptr);

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

	int components = GetTextureInfo(colourType);

	if(components == -1)
	{
		if(png_ptr)
			png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		return 0;
	}

	GLubyte *pixels = (GLubyte *)malloc(sizeof(GLubyte) * (width * height * components));

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

	for(unsigned int i = 0; i < height; ++i)
		row_pointers[i] = (png_bytep)(pixels + (i * width * components));

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


	// make it
	glGenTextures(1, &texture);
	// bind it
	glBindTexture(GL_TEXTURE_2D, texture);

	// here we has the problems
	GLuint glcolours;
	(components==4) ? (glcolours = GL_RGBA): (0);
	(components==3) ? (glcolours = GL_RGB): (0);
	(components==2) ? (glcolours = GL_LUMINANCE_ALPHA): (0);
	(components==1) ? (glcolours = GL_LUMINANCE): (0);


	GLubyte a[1000];
	strcpy_s((char*)a, sizeof(a), (char*)glGetString(GL_VERSION));


	// stretch it
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

	//OpenGL 1.1
	//	gluBuild2DMipmaps(GL_TEXTURE_2D, components, width, height, glcolours, GL_UNSIGNED_BYTE, pixels);

	//OpenGL 1.4
	//	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 
	//	glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); 

	
	//OpenGL 3.0
	//	http://www.opengl.org/wiki/Common_Mistakes#gluBuild2DMipmaps
	//On ATI glEnable(GL_TEXTURE_2D);
	//Warning: It has been reported that on some ATI drivers, 
	//glGenerateMipmap(GL_TEXTURE_2D) has no effect unless you 
	//precede it with a call to glEnable(GL_TEXTURE_2D) in this particular case. 
	//Once again, to be clear, bind the texture, glEnable, then glGenerateMipmap. 
	//This is a bug and has been in the ATI drivers for a while. 
	//Perhaps by the time you read this, it will have been corrected. 
	//(glGenerateMipmap doesn't work on ATI as of 2011)
	// 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 
	// 	glGenerateMipmap(GL_TEXTURE_2D);  //Generate mipmaps now!!!

	glTexImage2D(GL_TEXTURE_2D, 0, components, width, height, 0, glcolours, GL_UNSIGNED_BYTE, pixels);

	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

	fclose(pngFile);
	free(row_pointers);
	free(pixels);

	return texture;
}
Exemplo n.º 22
0
  Load_SBit_Png( FT_GlyphSlot     slot,
                 FT_Int           x_offset,
                 FT_Int           y_offset,
                 FT_Int           pix_bits,
                 TT_SBit_Metrics  metrics,
                 FT_Memory        memory,
                 FT_Byte*         data,
                 FT_UInt          png_len,
                 FT_Bool          populate_map_and_metrics )
  {
    FT_Bitmap    *map   = &slot->bitmap;
    FT_Error      error = FT_Err_Ok;
    FT_StreamRec  stream;

    png_structp  png;
    png_infop    info;
    png_uint_32  imgWidth, imgHeight;

    int         bitdepth, color_type, interlace;
    FT_Int      i;
    png_byte*  *rows = NULL; /* pacify compiler */


    if ( x_offset < 0 ||
         y_offset < 0 )
    {
      error = FT_THROW( Invalid_Argument );
      goto Exit;
    }

    if ( !populate_map_and_metrics                            &&
         ( (FT_UInt)x_offset + metrics->width  > map->width ||
           (FT_UInt)y_offset + metrics->height > map->rows  ||
           pix_bits != 32                                   ||
           map->pixel_mode != FT_PIXEL_MODE_BGRA            ) )
    {
      error = FT_THROW( Invalid_Argument );
      goto Exit;
    }

    FT_Stream_OpenMemory( &stream, data, png_len );

    png = png_create_read_struct( PNG_LIBPNG_VER_STRING,
                                  &error,
                                  error_callback,
                                  warning_callback );
    if ( !png )
    {
      error = FT_THROW( Out_Of_Memory );
      goto Exit;
    }

    info = png_create_info_struct( png );
    if ( !info )
    {
      error = FT_THROW( Out_Of_Memory );
      png_destroy_read_struct( &png, NULL, NULL );
      goto Exit;
    }

    if ( ft_setjmp( png_jmpbuf( png ) ) )
    {
      error = FT_THROW( Invalid_File_Format );
      goto DestroyExit;
    }

    png_set_read_fn( png, &stream, read_data_from_FT_Stream );

    png_read_info( png, info );
    png_get_IHDR( png, info,
                  &imgWidth, &imgHeight,
                  &bitdepth, &color_type, &interlace,
                  NULL, NULL );

    if ( error                                        ||
         ( !populate_map_and_metrics                &&
           ( (FT_Int)imgWidth  != metrics->width  ||
             (FT_Int)imgHeight != metrics->height ) ) )
      goto DestroyExit;

    if ( populate_map_and_metrics )
    {
      FT_ULong  size;


      metrics->width  = (FT_UShort)imgWidth;
      metrics->height = (FT_UShort)imgHeight;

      map->width      = metrics->width;
      map->rows       = metrics->height;
      map->pixel_mode = FT_PIXEL_MODE_BGRA;
      map->pitch      = (int)( map->width * 4 );
      map->num_grays  = 256;

      /* reject too large bitmaps similarly to the rasterizer */
      if ( map->rows > 0x7FFF || map->width > 0x7FFF )
      {
        error = FT_THROW( Array_Too_Large );
        goto DestroyExit;
      }

      /* this doesn't overflow: 0x7FFF * 0x7FFF * 4 < 2^32 */
      size = map->rows * (FT_ULong)map->pitch;

      error = ft_glyphslot_alloc_bitmap( slot, size );
      if ( error )
        goto DestroyExit;
    }

    /* convert palette/gray image to rgb */
    if ( color_type == PNG_COLOR_TYPE_PALETTE )
      png_set_palette_to_rgb( png );

    /* expand gray bit depth if needed */
    if ( color_type == PNG_COLOR_TYPE_GRAY )
    {
#if PNG_LIBPNG_VER >= 10209
      png_set_expand_gray_1_2_4_to_8( png );
#else
      png_set_gray_1_2_4_to_8( png );
#endif
    }

    /* transform transparency to alpha */
    if ( png_get_valid(png, info, PNG_INFO_tRNS ) )
      png_set_tRNS_to_alpha( png );

    if ( bitdepth == 16 )
      png_set_strip_16( png );

    if ( bitdepth < 8 )
      png_set_packing( png );

    /* convert grayscale to RGB */
    if ( color_type == PNG_COLOR_TYPE_GRAY       ||
         color_type == PNG_COLOR_TYPE_GRAY_ALPHA )
      png_set_gray_to_rgb( png );

    if ( interlace != PNG_INTERLACE_NONE )
      png_set_interlace_handling( png );

    png_set_filler( png, 0xFF, PNG_FILLER_AFTER );

    /* recheck header after setting EXPAND options */
    png_read_update_info(png, info );
    png_get_IHDR( png, info,
                  &imgWidth, &imgHeight,
                  &bitdepth, &color_type, &interlace,
                  NULL, NULL );

    if ( bitdepth != 8                              ||
        !( color_type == PNG_COLOR_TYPE_RGB       ||
           color_type == PNG_COLOR_TYPE_RGB_ALPHA ) )
    {
      error = FT_THROW( Invalid_File_Format );
      goto DestroyExit;
    }

    switch ( color_type )
    {
    default:
      /* Shouldn't happen, but fall through. */

    case PNG_COLOR_TYPE_RGB_ALPHA:
      png_set_read_user_transform_fn( png, premultiply_data );
      break;

    case PNG_COLOR_TYPE_RGB:
      /* Humm, this smells.  Carry on though. */
      png_set_read_user_transform_fn( png, convert_bytes_to_data );
      break;
    }

    if ( FT_NEW_ARRAY( rows, imgHeight ) )
    {
      error = FT_THROW( Out_Of_Memory );
      goto DestroyExit;
    }

    for ( i = 0; i < (FT_Int)imgHeight; i++ )
      rows[i] = map->buffer + ( y_offset + i ) * map->pitch + x_offset * 4;

    png_read_image( png, rows );

    FT_FREE( rows );

    png_read_end( png, info );

  DestroyExit:
    png_destroy_read_struct( &png, &info, NULL );
    FT_Stream_Close( &stream );

  Exit:
    return error;
  }
Exemplo n.º 23
0
	bool LoadPNG(const String& filename, png_byte* &PNG_image_buffer, png_uint_32 &width, png_uint_32 &height)
	{
		FILE *PNG_file = fopen(filename.c_str(), "rb");
		if (PNG_file == NULL)
		{
			sysLog.Printf("ERROR: Couldn't open %s.", filename.c_str());
			return false;
		}
		
		GLubyte PNG_header[8];
		
		fread(PNG_header, 1, 8, PNG_file);
		if (png_sig_cmp(PNG_header, 0, 8) != 0)
		{
			sysLog.Printf("ERROR: %s is not a PNG.", filename.c_str());
			return false;
		}
		
		png_structp PNG_reader = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
		if (PNG_reader == NULL)
		{
			sysLog.Printf("ERROR: Can't start reading %s.", filename.c_str());
			fclose(PNG_file);
			return false;
		}
		
		png_infop PNG_info = png_create_info_struct(PNG_reader);
		if (PNG_info == NULL)
		{
			sysLog.Printf("ERROR: Can't get info for %s.", filename.c_str());
			png_destroy_read_struct(&PNG_reader, NULL, NULL);
			fclose(PNG_file);
			return false;
		}
		
		png_infop PNG_end_info = png_create_info_struct(PNG_reader);
		if (PNG_end_info == NULL)
		{
			sysLog.Printf("ERROR: Can't get end info for %s.", filename.c_str());
			png_destroy_read_struct(&PNG_reader, &PNG_info, NULL);
			fclose(PNG_file);
			return false;
		}
		
		if (setjmp(png_jmpbuf(PNG_reader)))
		{
			sysLog.Printf("ERROR: Can't load %s.", filename.c_str());
			png_destroy_read_struct(&PNG_reader, &PNG_info, &PNG_end_info);
			fclose(PNG_file);
			return false;
		}

		png_init_io(PNG_reader, PNG_file);
		png_set_sig_bytes(PNG_reader, 8);
		
		png_read_info(PNG_reader, PNG_info);
		
		width = png_get_image_width(PNG_reader, PNG_info);
		height = png_get_image_height(PNG_reader, PNG_info);

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

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

		if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) 
		{
			png_set_expand_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_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_read_image(PNG_reader, PNG_rows);

		free(PNG_rows);

		png_destroy_read_struct(&PNG_reader, &PNG_info, &PNG_end_info);
		fclose(PNG_file);

		return true;
	}
Exemplo n.º 24
0
static pixman_image_t *
load_png(FILE *fp)
{
	png_struct *png;
	png_info *info;
	png_byte *data = NULL;
	png_byte **row_pointers = NULL;
	png_uint_32 width, height;
	int depth, color_type, interlace, stride;
	unsigned int i;

	png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
				     png_error_callback, NULL);
	if (!png)
		return NULL;

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

	if (setjmp(png_jmpbuf(png))) {
		if (data)
			free(data);
		if (row_pointers)
			free(row_pointers);
		png_destroy_read_struct(&png, &info, NULL);
		return NULL;
	}

	png_set_read_fn(png, fp, read_func);
	png_read_info(png, info);
	png_get_IHDR(png, info,
		     &width, &height, &depth,
		     &color_type, &interlace, NULL, NULL);

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

	if (color_type == PNG_COLOR_TYPE_GRAY)
		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);

	if (depth == 16)
		png_set_strip_16(png);

	if (depth < 8)
		png_set_packing(png);

	if (color_type == PNG_COLOR_TYPE_GRAY ||
	    color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
		png_set_gray_to_rgb(png);

	if (interlace != PNG_INTERLACE_NONE)
		png_set_interlace_handling(png);

	png_set_filler(png, 0xff, PNG_FILLER_AFTER);
	png_set_read_user_transform_fn(png, premultiply_data);
	png_read_update_info(png, info);
	png_get_IHDR(png, info,
		     &width, &height, &depth,
		     &color_type, &interlace, NULL, NULL);


	stride = stride_for_width(width);
	data = malloc(stride * height);
	if (!data) {
		png_destroy_read_struct(&png, &info, NULL);
		return NULL;
	}

	row_pointers = malloc(height * sizeof row_pointers[0]);
	if (row_pointers == NULL) {
		free(data);
		png_destroy_read_struct(&png, &info, NULL);
		return NULL;
	}

	for (i = 0; i < height; i++)
		row_pointers[i] = &data[i * stride];

	png_read_image(png, row_pointers);
	png_read_end(png, info);

	free(row_pointers);
	png_destroy_read_struct(&png, &info, NULL);

	return pixman_image_create_bits(PIXMAN_a8r8g8b8, width, height,
					(uint32_t *) data, stride);
}
Exemplo n.º 25
0
int simpl_image_load_png(SimplImage **image,
                         SimplInStream istream)
{
    png_structp png_ptr;
    png_infop info_ptr;
    png_byte color_type, bitdepth, *row_data=NULL;
    png_bytep* row_ptrs=NULL;
    
    png_uint_32 i, j, width, height, row_size;
    
    SimplColorPixel *iptr;
    SimplPixel *aptr;
    
    int out = SIMPL_INTERNAL;
    
    /* Create a read struct. */
    if (!(png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0))) {
        return SIMPL_INTERNAL;
    }
    
    /* Create an info struct. */
    if (!(info_ptr = png_create_info_struct(png_ptr))) {
        goto error;
    }
    
    /* Handle libpng errors with a magic setjmp. */
    if (setjmp(png_jmpbuf(png_ptr))) {
        goto error;
    }
    
    /* Set the stream-based data source. */
    png_set_read_fn(png_ptr, istream, StreamReadData);
    
    /* Read the info chunk. */
    png_read_info(png_ptr, info_ptr);
    
    /* Get the dimensions and color information. */
    width = png_get_image_width(png_ptr, info_ptr);
    height = png_get_image_height(png_ptr, info_ptr);
    bitdepth = png_get_bit_depth(png_ptr, info_ptr);
    color_type = png_get_color_type(png_ptr, info_ptr);
    
    /* If palette, low bit depth gray, transparent w/o alpha, or 16 bit, fix it. */
    if (color_type == PNG_COLOR_TYPE_PALETTE) {
        png_set_palette_to_rgb(png_ptr);
        color_type = png_get_color_type(png_ptr, info_ptr);
    } else if (color_type == PNG_COLOR_TYPE_GRAY) {
        if (bitdepth<8) png_set_expand_gray_1_2_4_to_8(png_ptr);
        bitdepth = 8;
    }
    
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
        png_set_tRNS_to_alpha(png_ptr);
        color_type = png_get_color_type(png_ptr, info_ptr);
    }
    
    png_set_strip_16(png_ptr);
    
    /* Either allocate a row, or load the entire image into a buffer. This is
     * because single row access uses less memory but doesn't work for
     * interlaced PNGs.
     */
    row_size = png_get_rowbytes(png_ptr, info_ptr);
    if (png_get_interlace_type(png_ptr, info_ptr)==PNG_INTERLACE_NONE) {
        row_data = (png_byte *)malloc(sizeof(png_byte) * row_size);
        if (!row_data) {
            out = SIMPL_NOMEM;
            goto error;
        }
    } else {
        row_ptrs = (png_bytep*)calloc(height, sizeof(png_bytep));
        if (!row_ptrs) {
            out = SIMPL_NOMEM;
            goto error;
        }
        
        for (j=0; j<height; ++j) {
            row_ptrs[j] = (png_byte *)malloc(sizeof(png_byte) * row_size);
            if (!row_ptrs[j]) {
                out = SIMPL_NOMEM;
                goto error;
            }
        }
        
        png_read_image(png_ptr, row_ptrs);
    }
        
    /* Allocate an image of the specified size. */
    out = simpl_image(image, width, height);
    if (out != SIMPL_OK) goto error;
        
    /* Store the decoded image into our format. */
    if (color_type == PNG_COLOR_TYPE_RGB) {
        for (j=0; j<height; j++) {
            if (row_ptrs) row_data = row_ptrs[j];
            else png_read_row(png_ptr, row_data, NULL);
            
            iptr = (*image)->image + j * width;
            for (i=0; i<3*width; i+=3) {
                iptr->red   = row_data[i];
                iptr->green = row_data[i+1];
                iptr->blue  = row_data[i+2];
                iptr++;
            }
        }
    } else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
        simpl_alpha_create(*image);
        for (j=0; j<height; j++) {
            if (row_ptrs) row_data = row_ptrs[j];
            else png_read_row(png_ptr, row_data, NULL);
            
            iptr = (*image)->image + j * width;
            aptr = (*image)->alpha + j * width;
            for (i=0; i<4*width; i+=4) {
                iptr->red   = row_data[i];
                iptr->green = row_data[i+1];
                iptr->blue  = row_data[i+2];
                iptr++;
            
                *aptr++ = row_data[i+3];
            }
        }
    } else if (color_type == PNG_COLOR_TYPE_GRAY) {
        for (j=0; j<height; j++) {
            if (row_ptrs) row_data = row_ptrs[j];
            else png_read_row(png_ptr, row_data, NULL);
            
            iptr = (*image)->image + j * width;
            for (i=0; i<width; i++) {
                iptr->red   = row_data[i];
                iptr->green = row_data[i];
                iptr->blue  = row_data[i];
                iptr++;
            }
        }
    } else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
        simpl_alpha_create(*image);
        for (j=0; j<height; j++) {
            if (row_ptrs) row_data = row_ptrs[j];
            else png_read_row(png_ptr, row_data, NULL);
            
            iptr = (*image)->image + j * width;
            aptr = (*image)->alpha + j * width;
            for (i=0; i<2*width; i+=2) {
                iptr->red   = row_data[i];
                iptr->green = row_data[i];
                iptr->blue  = row_data[i];
                iptr++;
            
                *aptr++ = row_data[i+1];
            }
        }
    } else goto error;
    
error:
    if (row_ptrs) {
        for (j=0; j<height; ++j) {
            if (row_ptrs[j]) free((void *)row_ptrs[j]);
        }
        
        free((void *)row_ptrs);
    } else {
        if (row_data) free((void *)row_data);
    }
    
    png_destroy_read_struct(&png_ptr, &info_ptr, 0);
    return out;
}
Exemplo n.º 26
0
/* really_load_png:
 *  Worker routine, used by load_png and load_memory_png.
 */
static BITMAP *really_load_png(png_structp png_ptr, png_infop info_ptr, RGB *pal)
{
    BITMAP *bmp;
    PALETTE tmppal;
    png_uint_32 width, height, rowbytes;
    int bit_depth, color_type, interlace_type;
    double image_gamma, screen_gamma;
    int intent;
    int bpp, dest_bpp;
    int tRNS_to_alpha = FALSE;
    int number_passes, pass;

    ASSERT(png_ptr && info_ptr && rgb);

    /* The call to png_read_info() gives us all of the information from the
     * PNG file before the first IDAT (image data chunk).
     */
    png_read_info(png_ptr, info_ptr);

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

    /* 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 grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
    if ((color_type == PNG_COLOR_TYPE_GRAY) && (bit_depth < 8))
	png_set_expand(png_ptr);

    /* Adds a full alpha channel if there is transparency information
     * in a tRNS chunk. */
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
	png_set_tRNS_to_alpha(png_ptr);
	tRNS_to_alpha = TRUE;
    }

    /* Convert 16-bits per colour component to 8-bits per colour component. */
    if (bit_depth == 16)
	png_set_strip_16(png_ptr);

    /* Convert grayscale to RGB triplets */
    if ((color_type == PNG_COLOR_TYPE_GRAY) ||
	(color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
	png_set_gray_to_rgb(png_ptr);

    /* Optionally, tell libpng to handle the gamma correction for us. */
    if (_png_screen_gamma != 0.0) {
	screen_gamma = get_gamma();

	if (png_get_sRGB(png_ptr, info_ptr, &intent))
	    png_set_gamma(png_ptr, screen_gamma, 0.45455);
	else {
	    if (png_get_gAMA(png_ptr, info_ptr, &image_gamma))
		png_set_gamma(png_ptr, screen_gamma, image_gamma);
	    else
		png_set_gamma(png_ptr, screen_gamma, 0.45455);
	}
    }

    /* Turn on interlace handling. */
    number_passes = png_set_interlace_handling(png_ptr);
    
    /* Call to gamma correct and add the background to the palette
     * and update info structure.
     */
    png_read_update_info(png_ptr, info_ptr);
    
    /* Even if the user doesn't supply space for a palette, we want
     * one for the load process.
     */
    if (!pal)
	pal = tmppal;
    
    /* Palettes. */
    if (color_type & PNG_COLOR_MASK_PALETTE) {
	int num_palette, i;
	png_colorp palette;

	if (png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)) {
	    /* We don't actually dither, we just copy the palette. */
	    for (i = 0; ((i < num_palette) && (i < 256)); i++) {
		pal[i].r = palette[i].red >> 2;		/* 256 -> 64 */
		pal[i].g = palette[i].green >> 2;
		pal[i].b = palette[i].blue >> 2;
	    }

	    for (; i < 256; i++)
		pal[i].r = pal[i].g = pal[i].b = 0;
	}
    }
Exemplo n.º 27
0
void LoadPNG( const char *name, byte **pic, int *width, int *height,
	      int *numLayers, int *numMips, int *bits, byte alphaByte )
{
	int          bit_depth;
	int          color_type;
	png_uint_32  w;
	png_uint_32  h;
	unsigned int row;
//	size_t          rowbytes;
	png_infop    info;
	png_structp  png;
	png_bytep    *row_pointers;
	byte         *data;
	byte         *out;
//	int             size;

	// load png
	ri.FS_ReadFile( name, ( void ** ) &data );

	if ( !data )
	{
		return;
	}

	//png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	png = png_create_read_struct( PNG_LIBPNG_VER_STRING, ( png_voidp ) NULL, png_user_error_fn, png_user_warning_fn );

	if ( !png )
	{
		ri.Printf( PRINT_WARNING, "LoadPNG: png_create_write_struct() failed for (%s)\n", name );
		ri.FS_FreeFile( data );
		return;
	}

	// allocate/initialize the memory for image information.  REQUIRED
	info = png_create_info_struct( png );

	if ( !info )
	{
		ri.Printf( PRINT_WARNING, "LoadPNG: png_create_info_struct() failed for (%s)\n", name );
		ri.FS_FreeFile( data );
		png_destroy_read_struct( &png, ( png_infopp ) NULL, ( png_infopp ) NULL );
		return;
	}

	/*
	 * Set error handling if you are using the setjmp/longjmp method (this is
	 * the common 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 ) ) )
	{
		// if we get here, we had a problem reading the file
		ri.Printf( PRINT_WARNING, "LoadPNG: first exception handler called for (%s)\n", name );
		ri.FS_FreeFile( data );
		png_destroy_read_struct( &png, ( png_infopp ) & info, ( png_infopp ) NULL );
		return;
	}

	//png_set_write_fn(png, buffer, png_write_data, png_flush_data);
	png_set_read_fn( png, data, png_read_data );

	png_set_sig_bytes( png, 0 );

	// The call to png_read_info() gives us all of the information from the
	// PNG file before the first IDAT (image data chunk).  REQUIRED
	png_read_info( png, info );

	// get picture info
	png_get_IHDR( png, info, ( png_uint_32 * ) &w, ( png_uint_32 * ) &h, &bit_depth, &color_type, NULL, NULL, NULL );

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

	// expand paletted images to RGB triplets
	if ( color_type & PNG_COLOR_MASK_PALETTE )
	{
		png_set_expand( png );
	}

	// expand gray-scaled images to RGB triplets
	if ( !( color_type & PNG_COLOR_MASK_COLOR ) )
	{
		png_set_gray_to_rgb( png );
	}

	// expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel
	//if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
	//  png_set_gray_1_2_4_to_8(png);

	// 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, info, PNG_INFO_tRNS ) )
	{
		png_set_tRNS_to_alpha( png );
	}

	// if there is no alpha information, fill with alphaByte
	if ( !( color_type & PNG_COLOR_MASK_ALPHA ) )
	{
		png_set_filler( png, alphaByte, PNG_FILLER_AFTER );
	}

	// expand pictures with less than 8bpp to 8bpp
	if ( bit_depth < 8 )
	{
		png_set_packing( png );
	}

	// update structure with the above settings
	png_read_update_info( png, info );

	// allocate the memory to hold the image
	*width = w;
	*height = h;
	*pic = out = ( byte * ) ri.Z_Malloc( w * h * 4 );

	row_pointers = ( png_bytep * ) ri.Hunk_AllocateTempMemory( sizeof( png_bytep ) * h );

	// set a new exception handler
	if ( setjmp( png_jmpbuf( png ) ) )
	{
		ri.Printf( PRINT_WARNING, "LoadPNG: second exception handler called for (%s)\n", name );
		ri.Hunk_FreeTempMemory( row_pointers );
		ri.FS_FreeFile( data );
		png_destroy_read_struct( &png, ( png_infopp ) & info, ( png_infopp ) NULL );
		return;
	}

	//rowbytes = png_get_rowbytes(png, info);

	for ( row = 0; row < h; row++ )
	{
		row_pointers[ row ] = ( png_bytep )( out + ( row * 4 * w ) );
	}

	// read image data
	png_read_image( png, row_pointers );

	// read rest of file, and get additional chunks in info
	png_read_end( png, info );

	// clean up after the read, and free any memory allocated
	png_destroy_read_struct( &png, &info, ( png_infopp ) NULL );

	ri.Hunk_FreeTempMemory( row_pointers );
	ri.FS_FreeFile( data );
}
Exemplo n.º 28
0
// load in the image data
Picture PictureLoaderPng::load( io::NFile file ) const
{
  if(!file.isOpen())
  {
    Logger::warning( "LOAD PNG: can't open file %s", file.getFileName().toString().c_str() );
    return Picture::getInvalid();
  }

  png_byte buffer[8];
  // Read the first few bytes of the PNG file
  if( file.read(buffer, 8) != 8 )
  {
    Logger::warning( "LOAD PNG: can't read file %s", file.getFileName().toString().c_str() );
    return Picture::getInvalid();
  }

  // Check if it really is a PNG file
  if( png_sig_cmp(buffer, 0, 8) )
  {
    Logger::warning( "LOAD PNG: not really a png %s", file.getFileName().toString().c_str() );
    return Picture::getInvalid();
  }

  // Allocate the png read struct
  png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING,
                                                NULL, (png_error_ptr)png_cpexcept_error,
                                                (png_error_ptr)png_cpexcept_warn);
  if( !png_ptr )
  {
    Logger::warning( "LOAD PNG: Internal PNG create read struct failure %s", file.getFileName().toString().c_str() );
    return Picture::getInvalid();
  }

  // Allocate the png info struct
  png_infop info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr)
  {
    Logger::warning( "LOAD PNG: Internal PNG create info struct failure 5s", file.getFileName().toString().c_str() );
    png_destroy_read_struct(&png_ptr, NULL, NULL);
    return Picture::getInvalid();
  }

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

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

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

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

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

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

  // Convert low bit colors to 8 bit colors
  if (BitDepth < 8)
  {
        if (ColorType==PNG_COLOR_TYPE_GRAY || ColorType==PNG_COLOR_TYPE_GRAY_ALPHA)
                png_set_expand_gray_1_2_4_to_8(png_ptr);
        else
                png_set_packing(png_ptr);
  }

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

  // Convert high bit colors to 8 bit colors
  if (BitDepth == 16)
        png_set_strip_16(png_ptr);

  // Convert gray color to true color
  if (ColorType==PNG_COLOR_TYPE_GRAY || ColorType==PNG_COLOR_TYPE_GRAY_ALPHA)
        png_set_gray_to_rgb(png_ptr);

  int intent;
  const double screen_gamma = 2.2;

  if (png_get_sRGB(png_ptr, info_ptr, &intent))
        png_set_gamma(png_ptr, screen_gamma, 0.45455);
  else
  {
        double image_gamma;
        if (png_get_gAMA(png_ptr, info_ptr, &image_gamma))
                png_set_gamma(png_ptr, screen_gamma, image_gamma);
        else
                png_set_gamma(png_ptr, screen_gamma, 0.45455);
  }

  // Update the changes in between, as we need to get the new color type
  // for proper processing of the RGBA type
  png_read_update_info(png_ptr, info_ptr);
  {
     // Use temporary variables to avoid passing casted pointers
     png_uint_32 w,h;
     // Extract info
     png_get_IHDR(png_ptr, info_ptr,
             &w, &h,
             &BitDepth, &ColorType, NULL, NULL, NULL);
     Width=w;
     Height=h;
  }

  // Convert RGBA to BGRA
  if (ColorType==PNG_COLOR_TYPE_RGB_ALPHA)
  {
    png_set_bgr(png_ptr);
  }

  // Create the image structure to be filled by png data
  Picture* pic = GfxEngine::instance().createPicture( Size( Width, Height ) );
  GfxEngine::instance().loadPicture( *pic );

  if( pic->getSize().getArea() == 0 )
  {
    Logger::warning( "LOAD PNG: Internal PNG create image struct failure %s", file.getFileName().toString().c_str() );
    png_destroy_read_struct(&png_ptr, NULL, NULL);
    return Picture::getInvalid();
  }

  if( !Height )
  {
    Logger::warning( "LOAD PNG: Internal PNG create row pointers failure %s", file.getFileName().toString().c_str() );
    png_destroy_read_struct(&png_ptr, NULL, NULL);
    return Picture::getInvalid();
  }

  // Create array of pointers to rows in image data
  ScopedPtr<unsigned char*> RowPointers( (unsigned char**)new png_bytep[ Height ] );

  // Fill array of pointers to rows in image data
  SDL_LockSurface( pic->getSurface() );
  unsigned char* data = (unsigned char*)pic->getSurface()->pixels;
  for(unsigned int i=0; i<Height; ++i)
  {
    RowPointers.data()[i] = data;
    data += pic->getSurface()->pitch;
  }

  // for proper error handling
  if( setjmp( png_jmpbuf( png_ptr ) ) )
  {
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    GfxEngine::instance().deletePicture( pic );
    return Picture::getInvalid();
  }

  // Read data using the library function that handles all transformations including interlacing
  png_read_image( png_ptr, RowPointers.data() );

  png_read_end( png_ptr, NULL );
  png_destroy_read_struct( &png_ptr, &info_ptr, 0 ); // Clean up memory

  SDL_UnlockSurface(pic->getSurface());

  return *pic;
}
Exemplo n.º 29
0
/****************************************************************************
 * DecodeBlock: the whole thing
 ****************************************************************************
 * This function must be fed with a complete compressed frame.
 ****************************************************************************/
static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_block;
    picture_t *p_pic = 0;

    png_uint_32 i_width, i_height;
    int i_color_type, i_interlace_type, i_compression_type, i_filter_type;
    int i_bit_depth, i;

    png_structp p_png;
    png_infop p_info, p_end_info;
    png_bytep *p_row_pointers = NULL;

    if( !pp_block || !*pp_block ) return NULL;

    p_block = *pp_block;
    p_sys->b_error = false;

    if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY )
    {
        block_Release( p_block ); *pp_block = NULL;
        return NULL;
    }

    p_png = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 );
    if( p_png == NULL )
    {
        block_Release( p_block ); *pp_block = NULL;
        return NULL;
    }

    p_info = png_create_info_struct( p_png );
    if( p_info == NULL )
    {
        png_destroy_read_struct( &p_png, NULL, NULL );
        block_Release( p_block ); *pp_block = NULL;
        return NULL;
    }

    p_end_info = png_create_info_struct( p_png );
    if( p_end_info == NULL )
    {
        png_destroy_read_struct( &p_png, &p_info, NULL );
        block_Release( p_block ); *pp_block = NULL;
        return NULL;
    }

    /* libpng longjmp's there in case of error */
    if( setjmp( png_jmpbuf( p_png ) ) )
        goto error;

    png_set_read_fn( p_png, (void *)p_block, user_read );
    png_set_error_fn( p_png, (void *)p_dec, user_error, user_warning );

    png_read_info( p_png, p_info );
    if( p_sys->b_error ) goto error;

    png_get_IHDR( p_png, p_info, &i_width, &i_height,
                  &i_bit_depth, &i_color_type, &i_interlace_type,
                  &i_compression_type, &i_filter_type);
    if( p_sys->b_error ) goto error;

    /* Set output properties */
    p_dec->fmt_out.i_codec = VLC_CODEC_RGBA;
    p_dec->fmt_out.video.i_visible_width = p_dec->fmt_out.video.i_width = i_width;
    p_dec->fmt_out.video.i_visible_height = p_dec->fmt_out.video.i_height = i_height;
    p_dec->fmt_out.video.i_sar_num = 1;
    p_dec->fmt_out.video.i_sar_den = 1;
    p_dec->fmt_out.video.i_rmask = 0x000000ff;
    p_dec->fmt_out.video.i_gmask = 0x0000ff00;
    p_dec->fmt_out.video.i_bmask = 0x00ff0000;

    if( i_color_type == PNG_COLOR_TYPE_PALETTE )
        png_set_palette_to_rgb( p_png );

    if( i_color_type == PNG_COLOR_TYPE_GRAY ||
        i_color_type == PNG_COLOR_TYPE_GRAY_ALPHA )
          png_set_gray_to_rgb( p_png );

    /* Strip to 8 bits per channel */
    if( i_bit_depth == 16 ) png_set_strip_16( p_png );

    if( png_get_valid( p_png, p_info, PNG_INFO_tRNS ) )
    {
        png_set_tRNS_to_alpha( p_png );
    }
    else if( !(i_color_type & PNG_COLOR_MASK_ALPHA) )
    {
        p_dec->fmt_out.i_codec = VLC_CODEC_RGB24;
    }

    /* Get a new picture */
    p_pic = decoder_NewPicture( p_dec );
    if( !p_pic ) goto error;

    /* Decode picture */
    p_row_pointers = malloc( sizeof(png_bytep) * i_height );
    if( !p_row_pointers )
        goto error;
    for( i = 0; i < (int)i_height; i++ )
        p_row_pointers[i] = p_pic->p->p_pixels + p_pic->p->i_pitch * i;

    png_read_image( p_png, p_row_pointers );
    if( p_sys->b_error ) goto error;
    png_read_end( p_png, p_end_info );
    if( p_sys->b_error ) goto error;

    png_destroy_read_struct( &p_png, &p_info, &p_end_info );
    free( p_row_pointers );

    p_pic->date = p_block->i_pts > VLC_TS_INVALID ? p_block->i_pts : p_block->i_dts;

    block_Release( p_block ); *pp_block = NULL;
    return p_pic;

 error:

    free( p_row_pointers );
    png_destroy_read_struct( &p_png, &p_info, &p_end_info );
    block_Release( p_block ); *pp_block = NULL;
    return NULL;
}
Exemplo n.º 30
0
void png_load_from_memory(aasset_buffer_t& buf, raw_bitmap_t* out_bitmap)
{
    //png header - 8 bytes
    if (png_sig_cmp(buf.data(), 0, 8))
    {
        my_assert(false && "Couldn't load texture. It isn't png file.");
        return;
    }

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

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

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

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

    png_read_info(png_ptr, info_ptr);

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

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

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

        case PNG_COLOR_TYPE_RGBA:
            format = GL_RGBA;
            break;

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

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

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

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

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

    png_read_image(png_ptr, row_ptrs);
}