Exemplo n.º 1
0
bool _openslide_jpeg_read_dimensions(const char *filename,
                                     int64_t offset,
                                     int32_t *w, int32_t *h,
                                     GError **err) {
  FILE *f = _openslide_fopen(filename, "rb", err);
  if (f == NULL) {
    return false;
  }
  if (offset && fseeko(f, offset, SEEK_SET) == -1) {
    _openslide_io_error(err, "Cannot seek to offset");
    fclose(f);
    return false;
  }

  bool success = jpeg_get_dimensions(f, NULL, 0, w, h, err);

  fclose(f);
  return success;
}
Exemplo n.º 2
0
bool _openslide_jpeg_read(const char *filename,
                          int64_t offset,
                          uint32_t *dest,
                          int32_t w, int32_t h,
                          GError **err) {
  //g_debug("read JPEG: %s %" G_GINT64_FORMAT, filename, offset);

  FILE *f = _openslide_fopen(filename, "rb", err);
  if (f == NULL) {
    return false;
  }
  if (offset && fseeko(f, offset, SEEK_SET) == -1) {
    _openslide_io_error(err, "Cannot seek to offset");
    fclose(f);
    return false;
  }

  bool success = jpeg_decode(f, NULL, 0, dest, false, w, h, err);

  fclose(f);
  return success;
}
Exemplo n.º 3
0
bool _openslide_gdkpixbuf_read(const char *format,
                               const char *filename,
                               int64_t offset,
                               int64_t length,
                               uint32_t *dest,
                               int32_t w, int32_t h,
                               GError **err) {
  GdkPixbufLoader *loader = NULL;
  uint8_t *buf = g_slice_alloc(BUFSIZE);
  bool success = false;
  struct load_state state = {
    .w = w,
    .h = h,
  };

  // open and seek
  FILE *f = _openslide_fopen(filename, "rb", err);
  if (!f) {
    goto DONE;
  }
  if (fseeko(f, offset, SEEK_SET)) {
    _openslide_io_error(err, "Couldn't fseek %s", filename);
    goto DONE;
  }

  // create loader
  loader = gdk_pixbuf_loader_new_with_type(format, err);
  if (!loader) {
    goto DONE;
  }
  g_signal_connect(loader, "area-prepared", G_CALLBACK(area_prepared), &state);

  // read data
  while (length) {
    size_t count = fread(buf, 1, MIN(length, BUFSIZE), f);
    if (!count) {
      g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_FAILED,
                  "Short read loading pixbuf from %s", filename);
      goto DONE;
    }
    if (!gdk_pixbuf_loader_write(loader, buf, count, err)) {
      g_prefix_error(err, "gdk-pixbuf error: ");
      goto DONE;
    }
    if (state.err) {
      goto DONE;
    }
    length -= count;
  }

  // finish load
  if (!gdk_pixbuf_loader_close(loader, err)) {
    g_prefix_error(err, "gdk-pixbuf error: ");
    goto DONE;
  }
  if (state.err) {
    goto DONE;
  }
  g_assert(state.pixbuf);

  // copy pixels
  uint8_t *pixels = gdk_pixbuf_get_pixels(state.pixbuf);
  int rowstride = gdk_pixbuf_get_rowstride(state.pixbuf);
  for (int32_t y = 0; y < h; y++) {
    for (int32_t x = 0; x < w; x++) {
      dest[y * w + x] = 0xFF000000 |                              // A
                        pixels[y * rowstride + x * 3 + 0] << 16 | // R
                        pixels[y * rowstride + x * 3 + 1] << 8 |  // G
                        pixels[y * rowstride + x * 3 + 2];        // B
    }
  }

  success = true;

DONE:
  // clean up
  if (loader) {
    gdk_pixbuf_loader_close(loader, NULL);
    g_object_unref(loader);
  }
  if (f) {
    fclose(f);
  }
  g_slice_free1(BUFSIZE, buf);

  // now that the loader is closed, we know state.err won't be set
  // behind our back
  if (state.err) {
    // signal handler validation errors override GdkPixbuf errors
    g_clear_error(err);
    g_propagate_error(err, state.err);
    // signal handler errors should have been noticed before falling through
    g_assert(!success);
  }
  return success;
}
static bool hamamatsu_ndpi_part2(openslide_t *osr,
				int num_jpegs, char *image_filenames,
				int num_jpeg_cols,
				GKeyFile *key_file,
				GError **err) {
  bool success = false;

  // initialize individual jpeg structs
  struct _openslide_jpeg_file **jpegs = g_new0(struct _openslide_jpeg_file *,
					       num_jpegs);
  for (int i = 0; i < num_jpegs; i++) {
    jpegs[i] = g_slice_new0(struct _openslide_jpeg_file);
  }

  // init levels: base image + map
  int32_t level_count = 2;
  struct _openslide_jpeg_level **levels =
    g_new0(struct _openslide_jpeg_level *, level_count);
  for (int32_t i = 0; i < level_count; i++) {
    levels[i] = g_slice_new0(struct _openslide_jpeg_level);
    levels[i]->tiles = _openslide_jpeg_create_tiles_table();
  }

  // process jpegs
  int32_t jpeg0_tw = 0;
  int32_t jpeg0_th = 0;
  int32_t jpeg0_ta = 0;
  int32_t jpeg0_td = 0;

  for (int i = 0; i < num_jpegs; i++) {
    struct _openslide_jpeg_file *jp = jpegs[i];

    //jp->start_in_file = 0;
    jp->filename = g_strdup(image_filenames);

    FILE *f;
    if ((f = _openslide_fopen(jp->filename, "rb", err)) == NULL) {
      g_prefix_error(err, "Can't open JPEG %d: ", i);
      goto DONE;
    }

    // set start and end of jpeg file
    // from key_file
    jp->start_in_file = g_key_file_get_integer(key_file, GROUP_VMS,
                        g_strdup_printf("hamamatsu.JpegStartOffset[%i]",i), err);
    int jpeg_size = g_key_file_get_integer(key_file, GROUP_VMS,
                        g_strdup_printf("hamamatsu.JpegSize[%i]",i), err);

    if (fseeko(f, jp->start_in_file, SEEK_SET) != 0) {
      _openslide_io_error(err, "Cannot seek to offset");
      goto DONE;
    }

    // comment?
    char *comment = NULL;
    char **comment_ptr = NULL;
    if (i == 0 && osr) {
      comment_ptr = &comment;
    }

    if (!verify_jpeg(f, &jp->w, &jp->h, &jp->tw, &jp->th, comment_ptr, err)) {
      g_prefix_error(err, "Can't verify JPEG %d: ", i);
      fclose(f);
      goto DONE;
    }

    if (comment) {
      g_hash_table_insert(osr->properties,
			  g_strdup(OPENSLIDE_PROPERTY_NAME_COMMENT),
			  comment);
    }

    //seek to end of jpeg offset
    fseeko(f, jpeg_size, SEEK_CUR);
    jp->end_in_file = ftello(f);
    if (jp->end_in_file == -1) {
      g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA,
                  "Can't read file size for JPEG %d", i);
      fclose(f);
      goto DONE;
    }

    // file is done now
    fclose(f);

    int32_t num_tiles_across = jp->w / jp->tw;
    int32_t num_tiles_down = jp->h / jp->th;

    //my sample NDPI file dont have map file.
    //if I dont modified this code, I get error
    //The overwriting error message was: Tile size not consistent
    //so, I am remove "else if" code

    // because map file is last, ensure that all tw and th are the
    // same for 0 through num_jpegs-2
    //    g_debug("tile size: %d %d", tw, th);
    //if (i == 0) {
      jpeg0_tw = jp->tw;
      jpeg0_th = jp->th;
      jpeg0_ta = num_tiles_across;
      jpeg0_td = num_tiles_down;
    /*} else if (i != (num_jpegs - 1)) {
      // not map file (still within level 0)
      g_assert(jpeg0_tw != 0 && jpeg0_th != 0);
      if (jpeg0_tw != jp->tw || jpeg0_th != jp->th) {
        g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA,
                    "Tile size not consistent");
        goto DONE;
      }
    }*/

    //NDPI file dont have optimisation file input, so remove this code
    /*
    // use the optimisation file, if present
    int32_t mcu_starts_count = (jp->w / jp->tw) * (jp->h / jp->th); // number of tiles
    int64_t *mcu_starts = NULL;
    if (optimisation_file) {
      mcu_starts = extract_one_optimisation(optimisation_file,
					    num_tiles_down,
					    num_tiles_across,
					    mcu_starts_count);
    }
    if (mcu_starts) {
      jp->mcu_starts = mcu_starts;
    } else if (optimisation_file != NULL) {
      // the optimisation file is useless, ignore it
      optimisation_file = NULL;
    }
    */

    // accumulate into some of the fields of the levels
    int32_t level;
    if (i != num_jpegs - 1) {
      // base (level 0)
      level = 0;
    } else {
      // map (level 1)
      level = 1;
    }

    struct _openslide_jpeg_level *l = levels[level];
    int32_t file_x = 0;
    int32_t file_y = 0;
    if (level == 0) {
      file_x = i % num_jpeg_cols;
      file_y = i / num_jpeg_cols;
    }
    if (file_y == 0) {
      l->level_w += jp->w;
      l->tiles_across += num_tiles_across;
    }
    if (file_x == 0) {
      l->level_h += jp->h;
      l->tiles_down += num_tiles_down;
    }

    // set some values (don't accumulate)
    l->raw_tile_width = jp->tw;
    l->raw_tile_height = jp->th;
    l->tile_advance_x = jp->tw;   // no overlaps or funny business
    l->tile_advance_y = jp->th;
  }

  // at this point, jpeg0_ta and jpeg0_td are set to values from 0,0 in level 0

  for (int i = 0; i < num_jpegs; i++) {
    struct _openslide_jpeg_file *jp = jpegs[i];

    int32_t level;
    int32_t file_x;
    int32_t file_y;
    if (i != num_jpegs - 1) {
      // base (level 0)
      level = 0;
      file_x = i % num_jpeg_cols;
      file_y = i / num_jpeg_cols;
    } else {
      // map (level 1)
      level = 1;
      file_x = 0;
      file_y = 0;
    }

    //g_debug("processing file %d %d %d", file_x, file_y, level);

    int32_t num_tiles_across = jp->w / jp->tw;

    struct _openslide_jpeg_level *l = levels[level];

    int32_t tile_count = (jp->w / jp->tw) * (jp->h / jp->th); // number of tiles

    // add all the tiles
    for (int local_tileno = 0; local_tileno < tile_count; local_tileno++) {
      struct _openslide_jpeg_tile *t = g_slice_new0(struct _openslide_jpeg_tile);

      int32_t local_tile_x = local_tileno % num_tiles_across;
      int32_t local_tile_y = local_tileno / num_tiles_across;

      t->fileno = i;
      t->tileno = local_tileno;
      t->w = jp->tw;
      t->h = jp->th;
      // no dest or src offsets

      // compute key for hashtable (y * w + x)
      int64_t x = file_x * jpeg0_ta + local_tile_x;
      int64_t y = file_y * jpeg0_td + local_tile_y;

      int64_t *key = g_slice_new(int64_t);
      *key = (y * l->tiles_across) + x;

      //g_debug("inserting tile: fileno %d tileno %d, %gx%g, file: %d %d, local: %d %d, global: %" G_GINT64_FORMAT " %" G_GINT64_FORMAT ", l->tiles_across: %d, key: %" G_GINT64_FORMAT, t->fileno, t->tileno, t->w, t->h, file_x, file_y, local_tile_x, local_tile_y, x, y, l->tiles_across, *key);
      g_assert(!g_hash_table_lookup(l->tiles, key));
      g_hash_table_insert(l->tiles, key, t);
    }
  }

  success = true;

 DONE:
  if (success) {
    _openslide_add_jpeg_ops(osr, num_jpegs, jpegs, level_count, levels);
  } else {
    // destroy
    for (int i = 0; i < num_jpegs; i++) {
      g_free(jpegs[i]->filename);
      g_free(jpegs[i]->mcu_starts);
      g_slice_free(struct _openslide_jpeg_file, jpegs[i]);
    }
    g_free(jpegs);

    for (int32_t i = 0; i < level_count; i++) {
      g_hash_table_unref(levels[i]->tiles);
      g_slice_free(struct _openslide_jpeg_level, levels[i]);
    }
    g_free(levels);
  }

  return success;
}