func: static int send_png_rect(VncState *vs, int x, int y, int w, int h,
  
                           VncPalette *palette)
  
  {
  
      png_byte color_type;
  
      png_structp png_ptr;
  
      png_infop info_ptr;
  
      png_colorp png_palette = NULL;
  
      pixman_image_t *linebuf;
  
      int level = tight_png_conf[vs->tight.compression].png_zlib_level;
  
      int filters = tight_png_conf[vs->tight.compression].png_filters;
  
      uint8_t *buf;
  
      int dy;
  
  
  
      png_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL,
  
                                          NULL, vnc_png_malloc, vnc_png_free);
  
  
  
      if (png_ptr == NULL)
  
          return -1;
  
  
  
      info_ptr = png_create_info_struct(png_ptr);
  
  
  
      if (info_ptr == NULL) {
  
          png_destroy_write_struct(&png_ptr, NULL);
  
          return -1;
  
      }
  
  
  
      png_set_write_fn(png_ptr, (void *) vs, png_write_data, png_flush_data);
  
      png_set_compression_level(png_ptr, level);
  
      png_set_filter(png_ptr, PNG_FILTER_TYPE_DEFAULT, filters);
  
  
  
      if (palette) {
  
          color_type = PNG_COLOR_TYPE_PALETTE;
  
      } else {
  
          color_type = PNG_COLOR_TYPE_RGB;
  
      }
  
  
  
      png_set_IHDR(png_ptr, info_ptr, w, h,
  
                   8, color_type, PNG_INTERLACE_NONE,
  
                   PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
  
  
  
      if (color_type == PNG_COLOR_TYPE_PALETTE) {
  
          struct palette_cb_priv priv;
  
  
  
          png_palette = png_malloc(png_ptr, sizeof(*png_palette) *
  
                                   palette_size(palette));
  
  
  
          priv.vs = vs;
  
          priv.png_palette = png_palette;
  
          palette_iter(palette, write_png_palette, &priv);
  
  
  
          png_set_PLTE(png_ptr, info_ptr, png_palette, palette_size(palette));
  
  
  
          if (vs->client_pf.bytes_per_pixel == 4) {
  
              tight_encode_indexed_rect32(vs->tight.tight.buffer, w * h, palette);
  
          } else {
  
              tight_encode_indexed_rect16(vs->tight.tight.buffer, w * h, palette);
  
          }
  
      }
  
  
  
      png_write_info(png_ptr, info_ptr);
  
  
  
      buffer_reserve(&vs->tight.png, 2048);
  
      linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, w);
  
      buf = (uint8_t *)pixman_image_get_data(linebuf);
  
      for (dy = 0; dy < h; dy++)
  
      {
  
          if (color_type == PNG_COLOR_TYPE_PALETTE) {
  
              memcpy(buf, vs->tight.tight.buffer + (dy * w), w);
  
          } else {
  
              qemu_pixman_linebuf_fill(linebuf, vs->vd->server, w, dy);
  
          }
  
          png_write_row(png_ptr, buf);
  
      }
  
      qemu_pixman_image_unref(linebuf);
  
  
  
      png_write_end(png_ptr, NULL);
  
  
  
      if (color_type == PNG_COLOR_TYPE_PALETTE) {
  
          png_free(png_ptr, png_palette);
  
      }
  
  
  
      png_destroy_write_struct(&png_ptr, &info_ptr);
  
  
  
      vnc_write_u8(vs, VNC_TIGHT_PNG << 4);
  
  
  
      tight_send_compact_size(vs, vs->tight.png.offset);
  
      vnc_write(vs, vs->tight.png.buffer, vs->tight.png.offset);
  
      buffer_reset(&vs->tight.png);
  
      return 1;
  
  }
  