Ejemplo n.º 1
0
void PNG_recycle(PNG* png)
{
  if (png == NULL) {
    return;
  }

  free(png->buffer);
  png->buffer = NULL;

  free_frame_info_array(png->frame_info_array, png->frame_count);
  png->frame_info_array = NULL;

  free(png->backup);
  png->backup = NULL;

  if (png->png_ptr != NULL && png->info_ptr != NULL) {
    png_destroy_read_struct(&png->png_ptr, &png->info_ptr, NULL);
  }
  png->png_ptr = NULL;
  png->info_ptr = NULL;

  if (png->patch_head_input_stream != NULL) {
    close_patch_head_input_stream(get_env(), png->patch_head_input_stream);
    destroy_patch_head_input_stream(get_env(), &png->patch_head_input_stream);
    png->patch_head_input_stream = NULL;
  }
}
Ejemplo n.º 2
0
bool PNG_complete(PNG* png)
{
  int i;

  if (!png->partially) {
    return true;
  }

  if (png->png_ptr == NULL || png->info_ptr == NULL || png->patch_head_input_stream == NULL) {
    LOGE(EMSG("Some stuff is NULL"));
    return false;
  }

  // Read left frames
  for (i = 1; i < png->frame_count; read_frame(png->png_ptr, png->info_ptr, png->frame_info_array + i++));

  // Generate pop
  generate_pop(png->frame_info_array, png->frame_count);

  // End read
  png_read_end(png->png_ptr, png->info_ptr);
  png_destroy_read_struct(&png->png_ptr, &png->info_ptr, NULL);

  // Close input stream
  close_patch_head_input_stream(get_env(), png->patch_head_input_stream);
  destroy_patch_head_input_stream(get_env(), &png->patch_head_input_stream);

  // Clean up
  png->partially = false;
  png->png_ptr = NULL;
  png->info_ptr = NULL;
  png->patch_head_input_stream = NULL;

  return true;
}
Ejemplo n.º 3
0
void* decode(JNIEnv* env, InputStream* stream, bool partially, int* format)
{
  unsigned char magic_numbers[2];
  PatchHeadInputStream* patch_head_input_stream;

  *format = get_format(env, stream);

  switch (*format) {
#ifdef IMAGE_SUPPORT_JPEG
    case IMAGE_FORMAT_JPEG:
      magic_numbers[0] = IMAGE_JPEG_MAGIC_NUMBER_0;
      magic_numbers[1] = IMAGE_JPEG_MAGIC_NUMBER_1;
      break;
#endif
#ifdef IMAGE_SUPPORT_PNG
    case IMAGE_FORMAT_PNG:
      magic_numbers[0] = IMAGE_PNG_MAGIC_NUMBER_0;
      magic_numbers[1] = IMAGE_PNG_MAGIC_NUMBER_1;
      break;
#endif
#ifdef IMAGE_SUPPORT_GIF
    case IMAGE_FORMAT_GIF:
      magic_numbers[0] = IMAGE_GIF_MAGIC_NUMBER_0;
      magic_numbers[1] = IMAGE_GIF_MAGIC_NUMBER_1;
      break;
#endif
    default:
      LOGE(EMSG("Can't detect format %d"), *format);
      destroy_input_stream(get_env(), &stream);
      return NULL;
  }

  patch_head_input_stream = create_patch_head_input_stream(stream, magic_numbers, 2);
  if (patch_head_input_stream == NULL){
    WTF_OM;
    destroy_input_stream(get_env(), &stream);
    return NULL;
  }

  switch (*format) {
#ifdef IMAGE_SUPPORT_JPEG
    case IMAGE_FORMAT_JPEG:
      return JPEG_decode(env, patch_head_input_stream, partially);
#endif
#ifdef IMAGE_SUPPORT_PNG
    case IMAGE_FORMAT_PNG:
      return PNG_decode(env, patch_head_input_stream, partially);
#endif
#ifdef IMAGE_SUPPORT_GIF
    case IMAGE_FORMAT_GIF:
      return GIF_decode(env, patch_head_input_stream, partially);
#endif
    default:
      LOGE(EMSG("Can't detect format %d"), *format);
      close_patch_head_input_stream(get_env(), patch_head_input_stream);
      destroy_patch_head_input_stream(get_env(), &patch_head_input_stream);
      return NULL;
  }
}
Ejemplo n.º 4
0
void* PNG_decode(JNIEnv* env, PatchHeadInputStream* patch_head_input_stream, bool partially)
{
  PNG *png = NULL;
  png_structp png_ptr = NULL;
  png_infop info_ptr = NULL;
  bool apng;
  unsigned int width;
  unsigned int height;
  int color_type;
  int bit_depth;
  bool is_opaque;
  unsigned char* buffer = NULL;
  unsigned int frame_count = 0;
  bool hide_first_frame = false;
  PNG_FRAME_INFO* frame_info_array = NULL;
  int i;

  png = (PNG *) malloc(sizeof(PNG));
  if (png == NULL) {
    WTF_OM;
    close_patch_head_input_stream(get_env(), patch_head_input_stream);
    destroy_patch_head_input_stream(get_env(), &patch_head_input_stream);
    return NULL;
  }

  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, &user_error_fn, &user_warn_fn);
  if (png_ptr == NULL) {
    free(png);
    png = NULL;
    close_patch_head_input_stream(get_env(), patch_head_input_stream);
    destroy_patch_head_input_stream(get_env(), &patch_head_input_stream);
    return NULL;
  }

  info_ptr = png_create_info_struct(png_ptr);
  if (info_ptr == NULL) {
    png_destroy_read_struct(&png_ptr, NULL, NULL);
    free(png);
    png = NULL;
    close_patch_head_input_stream(get_env(), patch_head_input_stream);
    destroy_patch_head_input_stream(get_env(), &patch_head_input_stream);
    return NULL;
  }

  if (setjmp(png_jmpbuf(png_ptr))) {
    LOGE(EMSG("Error in png decode"));
    free_frame_info_array(frame_info_array, frame_count);
    frame_info_array = NULL;
    free(buffer);
    buffer = NULL;
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    free(png);
    png = NULL;
    close_patch_head_input_stream(get_env(), patch_head_input_stream);
    destroy_patch_head_input_stream(get_env(), &patch_head_input_stream);
    return NULL;
  }

  // Set custom read function
  png_set_read_fn(png_ptr, patch_head_input_stream, &user_read_fn);

  // Get png info
  png_read_info(png_ptr, info_ptr);

  // Check apng
  if (png_get_valid(png_ptr, info_ptr, PNG_INFO_acTL)) {
    apng = true;
  } else {
    apng = false;
  }

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

  // Create buffer
  buffer = (unsigned char*) malloc(width * height * 4);
  if (buffer == NULL) {
    WTF_OM;
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    free(png);
    png = NULL;
    close_patch_head_input_stream(get_env(), patch_head_input_stream);
    destroy_patch_head_input_stream(get_env(), &patch_head_input_stream);
    return NULL;
  }

  if (apng) {
    // Get frame count
    frame_count = png_get_num_frames(png_ptr, info_ptr);
    hide_first_frame = png_get_first_frame_is_hidden(png_ptr, info_ptr);
    if (hide_first_frame) {
      frame_count--;
    }

    // Create frame info array
    frame_info_array = (PNG_FRAME_INFO*) calloc(frame_count, sizeof(PNG_FRAME_INFO));
    if (frame_info_array == NULL) {
      WTF_OM;
      free(buffer);
      buffer = NULL;
      png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
      free(png);
      png = NULL;
      close_patch_head_input_stream(get_env(), patch_head_input_stream);
      destroy_patch_head_input_stream(get_env(), &patch_head_input_stream);
      return NULL;
    }
  }

  // Configure to ARGB
  png_set_expand(png_ptr);
  if (bit_depth == 16) {
    png_set_scale_16(png_ptr);
  }
  if (color_type == PNG_COLOR_TYPE_GRAY ||
      color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
    png_set_gray_to_rgb(png_ptr);
  }
  if (!(color_type & PNG_COLOR_MASK_ALPHA)) {
    is_opaque = true;
    png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);
  } else {
    is_opaque = false;
  }

  if (apng) {
    if (hide_first_frame) {
      // Skip first frame
      read_image(png_ptr, buffer, width, height);
    }

    // Read first frame
    read_frame(png_ptr, info_ptr, frame_info_array);
    // Fix dop
    if (frame_info_array->dop == PNG_DISPOSE_OP_PREVIOUS) {
      frame_info_array->dop = PNG_DISPOSE_OP_BACKGROUND;
    }

    if (!partially || frame_count == 1) {
      // Read all frame
      for (i = 1; i < frame_count; read_frame(png_ptr, info_ptr, frame_info_array + i++));

      // Generate pop
      generate_pop(frame_info_array, frame_count);

      // End read
      png_read_end(png_ptr, info_ptr);
      png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

      // Close input stream
      close_patch_head_input_stream(env, patch_head_input_stream);
      destroy_patch_head_input_stream(env, &patch_head_input_stream);

      png->partially = false;
      png->png_ptr = NULL;
      png->info_ptr = NULL;
      png->patch_head_input_stream = NULL;
    } else {
      png->partially = true;
      png->png_ptr = png_ptr;
      png->info_ptr = info_ptr;
      png->patch_head_input_stream = patch_head_input_stream;
    }

    // Fill PNG
    png->width = width;
    png->height = height;
    png->is_opaque = is_opaque;
    png->buffer = buffer;
    png->apng = true;
    png->buffer_index = -1;
    png->frame_info_array = frame_info_array;
    png->frame_count = frame_count;
    png->backup = NULL;

    // Render first frame
    PNG_advance(png);
  } else {
    read_image(png_ptr, buffer, width, height);

    // End read
    png_read_end(png_ptr, info_ptr);
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

    // Close input stream
    close_patch_head_input_stream(env, patch_head_input_stream);
    destroy_patch_head_input_stream(env, &patch_head_input_stream);

    // Fill PNG
    png->width = width;
    png->height = height;
    png->buffer = buffer;
    png->apng = false;
    png->buffer_index = 0;
    png->frame_info_array = NULL;
    png->frame_count = 0;
    png->backup = NULL;
    png->partially = false;
    png->png_ptr = NULL;
    png->info_ptr = NULL;
    png->patch_head_input_stream = NULL;
  }

  return png;
}
Ejemplo n.º 5
0
void* JPEG_decode(JNIEnv* env, PatchHeadInputStream* patch_head_input_stream, bool partially)
{
  JPEG* jpeg = NULL;
  struct jpeg_decompress_struct cinfo;
  struct my_error_mgr jerr;
  unsigned char* buffer = NULL;
  size_t stride;
  unsigned char* line_buffer_array[3];
  int read_lines;

  jpeg = (JPEG*) malloc(sizeof(JPEG));
  if (jpeg == NULL) {
    WTF_OM;
    close_patch_head_input_stream(get_env(), patch_head_input_stream);
    destroy_patch_head_input_stream(get_env(), &patch_head_input_stream);
    return NULL;
  }

  // Init
  cinfo.err = jpeg_std_error(&jerr.pub);
  jerr.pub.error_exit = my_error_exit;
  if (setjmp(jerr.setjmp_buffer)) {
    LOGE(EMSG("%s"), emsg);
    free(jpeg);
    free(buffer);
    jpeg_destroy_decompress(&cinfo);
    close_patch_head_input_stream(get_env(), patch_head_input_stream);
    destroy_patch_head_input_stream(get_env(), &patch_head_input_stream);
    return NULL;
  }
  jpeg_create_decompress(&cinfo);
  jpeg_custom_src(&cinfo, &custom_read, patch_head_input_stream);
  jpeg_read_header(&cinfo, TRUE);

  // Start decompress
  cinfo.out_color_space = JCS_EXT_RGBA;
  jpeg_start_decompress(&cinfo);

  stride = cinfo.output_components * cinfo.output_width;
  buffer = malloc(stride * cinfo.output_height);
  if (buffer == NULL) {
    free(jpeg);
    jpeg_destroy_decompress(&cinfo);
    close_patch_head_input_stream(get_env(), patch_head_input_stream);
    destroy_patch_head_input_stream(get_env(), &patch_head_input_stream);
    return NULL;
  }

  // Copy buffer
  line_buffer_array[0] = buffer;
  line_buffer_array[1] = line_buffer_array[0] + stride;
  line_buffer_array[2] = line_buffer_array[1] + stride;
  while (cinfo.output_scanline < cinfo.output_height) {
    read_lines = jpeg_read_scanlines(&cinfo, line_buffer_array, 3);
    line_buffer_array[0] += stride * read_lines;
    line_buffer_array[1] = line_buffer_array[0] + stride;
    line_buffer_array[2] = line_buffer_array[1] + stride;
  }

  // Finish decompress
  jpeg_finish_decompress(&cinfo);
  jpeg_destroy_decompress(&cinfo);

  // Close stream
  close_patch_head_input_stream(get_env(), patch_head_input_stream);
  destroy_patch_head_input_stream(get_env(), &patch_head_input_stream);

  // Fill jpeg
  jpeg->width = cinfo.output_width;
  jpeg->height = cinfo.output_height;
  jpeg->buffer = buffer;

  return jpeg;
}