【问题标题】:C++ libpng into GLFWimage into GLFWcursor causing distortion and intermittent behaviourC++ libpng 转换为 GLFWimage 转换为 GLFWcursor 导致失真和间歇性行为
【发布时间】:2015-03-23 19:31:01
【问题描述】:

编辑:

我现在正在使用 Brett 的代码加载一个 png,当渲染到 opengl 中的纹理(作为软件光标)时它可以正常工作,但是每次我作为 GLFWcursor 加载时,我都会得到一个扭曲的图像(每次都不同)并且那里是 GLFWcursor 将只使用最后加载的 GLFWimage 的问题。我输入的像素不是我输出的像素。

编辑:

GLFWimage CursorManager::LoadImageFromFile(string filename)
{
    FILE* file = fopen(filename.c_str(), "rb");
   if (!file) {
     //return NULL;
   }
    unsigned int width = 0;
    unsigned int height = 0;
    unsigned char* buffer = NULL;

    int error = png_rgba_load(file
    ,&width
    ,&height
    ,&buffer);

    if(error == 0)
    {
        GLFWimage image;

        int w = 32; //32
        int h = 32; //32
        unsigned char pixels[w * h * 4];
        memcpy(pixels, buffer, sizeof(pixels));

        //for(int i=0;i<sizeof(pixels);i++)
        //  cout << pixels[i];

        cout << "unsigned char pixels:" << endl;

        for(int i=0;i<sizeof(pixels);i++)
            cout << hex((int)pixels[i]);

        cout << endl << "image.pixels:" << endl;

        image.width = w;
        image.height = h;
        image.pixels = pixels;

        for(int i=0;i<sizeof(image.pixels);i++)
            cout << hex((int)image.pixels[i]);

        return image;
    }
    else
    {
        cout << "ERROR @ png_rgba_load" << endl;
        //return NULL;
    }
    fclose(file);
        //if (fclose(file) != 0) /* filesystem I/O error (?) */
    //    goto fail;
}

-

cout << "Loading GLimage " << m_sFileName_Arrow << endl;
m_oArrow     = LoadImageFromFile(m_sFileName_Arrow);
cout << "Loading GLimage " << m_sFileName_Text << endl;
m_oText      = LoadImageFromFile(m_sFileName_Text);
cout << "Loading GLimage " << m_sFileName_Crosshair << endl;
m_oCrosshair = LoadImageFromFile(m_sFileName_Crosshair);
cout << "Loading GLimage " << m_sFileName_Hand << endl;
m_oHand      = LoadImageFromFile(m_sFileName_Hand);
cout << "Loading GLimage " << m_sFileName_Hresize << endl;
m_oHresize   = LoadImageFromFile(m_sFileName_Hresize);
cout << "Loading GLimage " << m_sFileName_Vresize << endl;
m_oVresize   = LoadImageFromFile(m_sFileName_Vresize);

-

    cout << "Set cursor to Crosshair" << endl;
    cur = glfwCreateCursor(&m_oCrosshair,0,0);

光标从从 libpng 加载的 GLFWimage 加载,但是 (1) 它每次都有不同的随机像素。 (2) 另外,无论我将什么图像设置为新光标,它总是显示最后一个加载的图像,即 m_oVresize (3) 将 image.pixels 设置为与像素不匹配后的十六进制打印时

无符号字符像素: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FFD97400FF272D70FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FFD97400FFD97400FFD97400FF272D70FF0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FFD97400FFD97400FFD97400FFD97400FFD97400FF272D70FF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF272D70FF272D70FF272D70FF272D70FF272D70FF272D70FF272D70FF272D70FF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF00000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF00000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF00000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FF272D70FF272D70FF 272D70FF272D70FF272D70FF272D70FF272D70FF272D70FF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FFD97400FFD97400FFD97400FFD97400FFD97400FF272D70FF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FFD97400FFD97400FFD97400FF272D70FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000272D70FFD97400FF272D70FF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000272D70FF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 image.pixels: 0000000000000000

【问题讨论】:

  • 段错误发生在哪里?
  • glTexImage2D之前,你可以试试:glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  • 这里有一些问题。如果在png_read_image 期间发生setjmp 调用,则您对调用的使用会出现问题——内存永远不会被释放。我也不相信您已将代码设置为 强制 转换为 RGBA 结构。
  • @CHris:根据 GLFW 文档,设置光标需要每通道 RGBA 8 位格式的图像,没有任何填充。在您的代码中,是否会获得合适的格式取决于文件。 IIRC,使用 libpng,您还可以定义一些输入转换,以便如果数据与文件中存储的格式不同,它会自动将数据转换为所需的格式。
  • 您将image.pixels 设置为一块内存,然后在返回之前释放它。

标签: c++ image opengl glfw libpng


【解决方案1】:

试着把它放在 png_read_image() 之前:

png_set_expand(png_ptr);       // expand to RGB or RGBA
png_set_add_alpha(png_ptr, filler, PNG_FILLER_AFTER);
//"filler" contains the alpha value to assign to each pixel.

即使您的图像已经是 RGB 或 RGBA,执行此操作也是安全的。 如果您正在编写一个 8-bit-per-sample 图像并且 您希望像素不透明。

【讨论】:

  • 错误:函数'void png_set_add_alpha(png_structp,png_uint_32,int)'(控件)的参数太少
【解决方案2】:

这可能是 S.O. 的太多代码转储,但它可能对其他人充满了有用的提示。尝试阅读 PNG API 和各种示例等是一种折磨。最后,这是我提供的(相对)简单的界面:

(至于“版权”——随心所欲,只要你别管我,等等)

/*******************************************************************************
*
* png_rgba.h : PNG file I/O in (8) bits per channel RGBA format:
*
* Copyright (c) Brett Hale 2008, 2012. Public Domain.
*
*******************************************************************************/


#ifndef _PNG_RGBA_H
#define _PNG_RGBA_H

#if defined (__cplusplus) /* ISO C declaration scope: */

#define _PNG_RGBA_INIT_DECL extern "C" {
#define _PNG_RGBA_FINI_DECL }

#else

#define _PNG_RGBA_INIT_DECL
#define _PNG_RGBA_FINI_DECL

#endif /* defined (__cplusplus) */


#include <stddef.h>
#include <stdlib.h>

#include <stdio.h> /* ISO C : standard I/O library. */


_PNG_RGBA_INIT_DECL


/******************************************************************************/

/* load a PNG image using an opened file stream. return the image data
 * as a (malloc) allocated RGBA image buffer, with the width: (w), and
 * height: (h). return (0) on success: */

/* if the operation fails, then the dimensions are set to (0), and the
 * buffer is set to (NULL). */

/* the operation fails if the image has zero area, or if the number of
 * pixels exceeds PNG_RGBA_PIXEL_LIMIT. */

/* asserts that 'unsigned int' has a width of at least 32 bits. */


#define PNG_RGBA_PIXEL_LIMIT (0x1000000)

int png_rgba_load (FILE *, unsigned *w, unsigned *h, unsigned char **);


/******************************************************************************/

/* save an RGBA image buffer, with the width: (w), and height: (h), as
 * a PNG image, using an opened file stream. return (0) on success: */

/* the operation fails if the image has zero area, or if the number of
 * pixels exceeds PNG_RGBA_PIXEL_LIMIT. */

/* asserts that 'unsigned int' has a width of at least 32 bits. */


int png_rgba_save (FILE *, unsigned w, unsigned h, const unsigned char *);


/******************************************************************************/


_PNG_RGBA_FINI_DECL


#endif /* _PNG_RGBA_H */

以及实现:

/*******************************************************************************
*
* png_rgba.c : PNG file I/O in (8) bits per channel RGBA format:
*
* Copyright (c) Brett Hale 2008, 2012. Public Domain.
*
*******************************************************************************/


#include "png_rgba.h"

#include <png.h> /* PNG library. */


#define PNG_SIG_BYTES (8) /* bytes in the PNG file signature. */


/******************************************************************************/


static int
png_rgba_pixel_limit (png_uint_32 w, png_uint_32 h)
{
    double da;

    /* assert(w != 0 && h != 0); */

    if (w > PNG_RGBA_PIXEL_LIMIT || h > PNG_RGBA_PIXEL_LIMIT)
        return (1); /* since both (w) and (h) are non-zero. */

    /* since an IEEE-754 double has a 53 bit mantissa, it can
     * represent the maximum area: (w * h == 2^48) exactly. */

    da = ((double) w) * ((double) h);

    if (da > ((double) PNG_RGBA_PIXEL_LIMIT))
        return (1);

    return (0); /* the PNG image is within the pixel limit. */
}


/******************************************************************************/


int png_rgba_load
(
    FILE *fp, unsigned *w, unsigned *h, unsigned char **buf)
{
    png_byte magic[PNG_SIG_BYTES]; /* (signature byte buffer) */

    png_structp png_ctx;
    png_infop info_ctx;

    png_uint_32 img_width, img_height, row;
    png_byte img_depth, img_color_type;

    /* 'volatile' qualifier forces reload in setjmp cleanup: */

    png_byte *volatile img_data = NULL;
    png_bytep *volatile row_data = NULL;

    *w = 0, *h = 0, *buf = NULL;


    /* it is assumed that 'longjmp' can be invoked within this
     * code to efficiently unwind resources for *all* errors. */

    /* PNG structures and resource unwinding: */

    if ((png_ctx = png_create_read_struct(
             PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL)
        return (1); /* ENOMEM (?) */

    if ((info_ctx = png_create_info_struct(png_ctx)) == NULL)
    {
        png_destroy_read_struct(& png_ctx, NULL, NULL);
        return (1); /* ENOMEM (?) */
    }

    if (setjmp(png_jmpbuf(png_ctx)) != 0)
    {
        png_destroy_read_struct(& png_ctx, & info_ctx, NULL);
        free(img_data); free(row_data);

        return (1); /* libpng feedback (?) */
    }

    /* check PNG file signature: */

    if (fread(magic, (1), PNG_SIG_BYTES, fp) != PNG_SIG_BYTES)
        png_error(png_ctx, "invalid PNG file");

    if (png_sig_cmp(magic, 0, PNG_SIG_BYTES))
        png_error(png_ctx, "invalid PNG file");


    /* set the input file stream and get the PNG image info: */

    png_init_io(png_ctx, fp);
    png_set_sig_bytes(png_ctx, PNG_SIG_BYTES);

    png_read_info(png_ctx, info_ctx);

    img_width = png_get_image_width(png_ctx, info_ctx);
    img_height = png_get_image_height(png_ctx, info_ctx);

#if (1) /* PNG doesn't support zero area image? */

    if (img_width == 0 || img_height == 0)
        png_error(png_ctx, "zero area PNG image");
#endif

    if (png_rgba_pixel_limit(img_width, img_height))
        png_error(png_ctx, "PNG image exceeds pixel limits");

    img_depth = png_get_bit_depth(png_ctx, info_ctx);
    img_color_type = png_get_color_type(png_ctx, info_ctx);

    /* ignored image interlacing, compression and filtering. */

    /* force 8-bit color channels: */

    if (img_depth == 16)
        png_set_strip_16(png_ctx);

    else if (img_depth < 8)
        png_set_packing(png_ctx);

    /* force formats to RGB: */

    if (img_color_type != PNG_COLOR_TYPE_RGBA)
        png_set_expand(png_ctx);

    if (img_color_type == PNG_COLOR_TYPE_PALETTE)
        png_set_palette_to_rgb(png_ctx);

    if (img_color_type == PNG_COLOR_TYPE_GRAY)
        png_set_gray_to_rgb(png_ctx);

    if (img_color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
        png_set_gray_to_rgb(png_ctx);

    /* add full opacity alpha channel if required: */

    if (img_color_type != PNG_COLOR_TYPE_RGBA)
        png_set_filler(png_ctx, 0xff, PNG_FILLER_AFTER);

    /* apply the output transforms before reading image data: */

    png_read_update_info(png_ctx, info_ctx);


    /* allocate RGBA image data: */

    img_data = (png_byte *)
        malloc((size_t) (img_width * img_height * (4)));

    if (img_data == NULL)
        png_error(png_ctx, "error allocating image buffer");

    /* allocate row pointers: */

    row_data = (png_bytep *)
        malloc((size_t) (img_height * sizeof(png_bytep)));

    if (row_data == NULL)
        png_error(png_ctx, "error allocating row pointers");

    /* set the row pointers and read the RGBA image data: */

    for (row = 0; row < img_height; row++)
        row_data[row] = img_data +
            (img_height - (row + 1)) * (img_width * (4));

    png_read_image(png_ctx, row_data);

    /* libpng and dynamic resource unwinding: */

    png_read_end(png_ctx, NULL);
    png_destroy_read_struct(& png_ctx, & info_ctx, NULL);

    free(row_data);

    *w = (unsigned) img_width, *h = (unsigned) img_height;

    *buf = img_data; /* (asserts png_byte is an unsigned char) */

    return (0);
}


/******************************************************************************/


int png_rgba_save
(
    FILE *fp, unsigned w, unsigned h, const unsigned char *data)
{
    png_structp png_ctx;
    png_infop info_ctx;

    png_uint_32 img_width, img_height, row;

    img_width = (png_uint_32) w, img_height = (png_uint_32) h;


    /* it is assumed that 'longjmp' can be invoked within this
     * code to efficiently unwind resources for *all* errors. */

    /* PNG structures and resource unwinding: */

    if ((png_ctx = png_create_write_struct(
             PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL)
        return (1); /* ENOMEM (?) */

    if ((info_ctx = png_create_info_struct(png_ctx)) == NULL)
    {
        png_destroy_write_struct(& png_ctx, NULL);
        return (1); /* ENOMEM (?) */
    }

    if (setjmp(png_jmpbuf(png_ctx)) != 0)
    {
        png_destroy_write_struct(& png_ctx, & info_ctx);

        return (1); /* libpng feedback (?) */
    }


    /* set the output file stream and set the PNG image HDR: */

    png_init_io(png_ctx, fp);

    if (png_rgba_pixel_limit(img_width, img_height))
        png_error(png_ctx, "PNG image exceeds pixel limits");

    png_set_IHDR(
        png_ctx, info_ctx, img_width, img_height, (8),
        PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
        PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);


    /* write the RGBA image data from the bottom to top row: */

    png_write_info(png_ctx, info_ctx);

    for (row = img_height; row != 0; row--)
    {
        png_bytep row_data = (png_bytep)
            (data + (row - 1) * (img_width * (4)));

        png_write_row(png_ctx, row_data); /* non-interlaced. */
    }

    /* libpng and dynamic resource unwinding: */

    png_write_end(png_ctx, NULL);
    png_destroy_write_struct(& png_ctx, & info_ctx);

    return (0); /* (much easier when the data format is known) */
}


/******************************************************************************/

#if (0)

int main (int argc, char **argv)
{
    /* test the ability to read any PNG file and save as RGBA: */

    FILE *ifile = NULL, *ofile = NULL;
    int load_error, save_error;

    unsigned int img_width, img_height;
    unsigned char *img_data = NULL;

    if (argc < 3)
    {
        fprintf(stderr, "png_rgba <infile> <outfile>\n");
        return (1);
    }

    if ((ifile = fopen(argv[1], "rb")) == NULL)
        goto fail;

    load_error = png_rgba_load(
        ifile, & img_width, & img_height, & img_data);

    if (fclose(ifile) != 0) /* filesystem I/O error (?) */
        goto fail;

    if (load_error)
    {
        fprintf(stderr, "could not load '%s'\n", argv[1]);
        return (1);
    }

    if ((ofile = fopen(argv[2], "wb")) == NULL)
        goto fail;

    save_error = png_rgba_save(
        ofile, img_width, img_height, img_data);

    if (fclose(ofile) != 0) /* filesystem I/O error (?) */
        goto fail;

    if (save_error)
    {
        fprintf(stderr, "could not save '%s'\n", argv[2]);
        return (1);
    }

    fprintf(stdout, "%u x %u image\n", img_width, img_height);
    return (0);

fail:

    perror("png_rgba"); /* prepend to the system error message. */
    return (1);
}

#endif

/******************************************************************************/

malloc 的大多数实现至少会产生 8 字节对齐 - 在 x86[-64] 等平台上通常会产生 16 字节对齐。因此对于 OpenGL,可以安全地假设行是 4 字节 (RGBA) 对齐的,实际上。这是glPixelStore 的默认值 - 如果有疑问,请使用:

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);glTexImage2D 调用之前。

【讨论】:

  • 这可行,但由于某种原因,我看到随机像素出现在光标底部,每次都不同。我也有一个问题,当尝试将光标设置为不同的存储图像时,总是显示相同的图像。
  • 我认为这与您的代码没有任何关系,所以 +1
【解决方案3】:

如果将 png 图像加载到纹理中是您唯一需要做的事情,我建议您可以放弃 libpng 并改用 stb_image。这是一个非常易于使用的仅包含标头的库,可以为您提供来自 PNG 的原始 RGB 数据。

【讨论】:

  • 加载图像不是问题,Brett 发布了一些很棒的代码,改进了我已经使用的代码。问题是一旦图像被加载,转换为 GLFWimage 并作为 GLFWcursor 加载,图像被扭曲为光标,有时它会在水平方向和垂直方向重复四次两次,每次都有不同的偏移量和随机像素已更改,这意味着问题是图像在作为 GLFW 中的光标加载时会失真。
  • 我放入 GLFW 光标的东西,并不是我从中得到的东西。我需要有人自己尝试并确认他们有同样的问题,提供 GLFW 的问题,或者验证我的实现无效。
【解决方案4】:

您还可以使用Soil 获取PNG 的像素数据。

我用它来设置窗口图标,但是根据cursor specification,这个方法也应该在那里工作。

GLFWimage icons[1];
icons[0].pixels = SOIL_load_image("icon.png", &icons[0].width, &icons[0].height, 0, SOIL_LOAD_RGBA);
glfwSetWindowIcon(window.window, 1, icons);
SOIL_free_image_data(icons[0].pixels);

【讨论】:

    猜你喜欢
    • 2014-08-28
    • 1970-01-01
    • 1970-01-01
    • 2017-10-16
    • 2016-02-08
    • 2012-12-05
    • 2016-05-17
    • 1970-01-01
    相关资源
    最近更新 更多