CachedPage::UnitPtr DiHdfRasterPager::fetchUnit(DataRequest *pOriginalRequest) { VERIFYRV(pOriginalRequest != NULL, CachedPage::UnitPtr()); unsigned int frame = pOriginalRequest->getStartBand().getOnDiskNumber(); if (mHdf.toFrame(frame) == FAIL) { return CachedPage::UnitPtr(); } const RasterDataDescriptor *pDesc = static_cast<const RasterDataDescriptor*>(getRasterElement()->getDataDescriptor()); unsigned int bpp = pDesc->getBytesPerElement(); size_t bufsize = pOriginalRequest->getConcurrentRows() * pDesc->getColumnCount() * bpp; char* pBuffer = new char[bufsize]; int32 pStart[] = {pDesc->getActiveColumn(0).getOnDiskNumber(), pOriginalRequest->getStartRow().getOnDiskNumber()}; int32 pCount[] = {pDesc->getColumnCount(), pOriginalRequest->getConcurrentRows()}; int32 pStride[] = {1, 1}; if (GRreadimage(mHdf.riid(), pStart, pStride, pCount, pBuffer) == FAIL) { delete pBuffer; return CachedPage::UnitPtr(); } return CachedPage::UnitPtr(new CachedPage::CacheUnit( pBuffer, pOriginalRequest->getStartRow(), pOriginalRequest->getConcurrentRows(), bufsize, pOriginalRequest->getStartBand())); }
static int read_partial_array(const coda_cursor *cursor, long offset, long length, void *dst) { int32 start[MAX_HDF4_VAR_DIMS]; int32 stride[MAX_HDF4_VAR_DIMS]; int32 edge[MAX_HDF4_VAR_DIMS]; long i; switch (((coda_hdf4_type *)cursor->stack[cursor->n - 1].type)->tag) { case tag_hdf4_basic_type_array: coda_set_error(CODA_ERROR_INVALID_ARGUMENT, "partial array reading is not supported for HDF4 attributes"); return -1; case tag_hdf4_GRImage: { coda_hdf4_GRImage *type; type = (coda_hdf4_GRImage *)cursor->stack[cursor->n - 1].type; stride[0] = 1; stride[1] = 1; if (length < type->dim_sizes[1]) { start[0] = offset / type->dim_sizes[1]; start[1] = offset % type->dim_sizes[1]; edge[0] = 1; edge[1] = length; if (start[1] + edge[1] > type->dim_sizes[1]) { coda_set_error(CODA_ERROR_INVALID_ARGUMENT, "partial array reading for HDF4 GRImage requires " "offset (%ld) and length (%ld) to represent a hyperslab (range [%ld,%ld] " "exceeds length of dimension #1 (%ld)))", offset, length, (long)start[1], (long)start[1] + edge[1] - 1, type->dim_sizes[1]); return -1; } } else { if (length % type->dim_sizes[1] != 0) { coda_set_error(CODA_ERROR_INVALID_ARGUMENT, "partial array reading for HDF4 GRImage requires " "length (%ld) to be a multiple of the subdimension size (%ld)", length, type->dim_sizes[1]); return -1; } if (offset % type->dim_sizes[1] != 0) { coda_set_error(CODA_ERROR_INVALID_ARGUMENT, "partial array reading for HDF4 GRImage requires " " offset (%ld) to be a multiple of the subdimension size (%ld)", offset, type->dim_sizes[1]); return -1; } start[0] = offset / type->dim_sizes[1]; start[1] = 0; edge[0] = length / type->dim_sizes[1]; edge[1] = type->dim_sizes[1]; if (start[0] + edge[0] > type->dim_sizes[0]) { coda_set_error(CODA_ERROR_INVALID_ARGUMENT, "partial array reading for HDF4 GRImage requires " "offset (%ld) and length (%ld) to represent a hyperslab (range [%ld,%ld] " "exceeds length of dimension #0 (%ld)))", offset, length, (long)start[0], (long)start[0] + edge[0] - 1, type->dim_sizes[0]); return -1; } } if (GRreadimage(type->ri_id, start, stride, edge, dst) != 0) { coda_set_error(CODA_ERROR_HDF4, NULL); return -1; } } break; case tag_hdf4_SDS: { coda_hdf4_SDS *type; long block_size = 1; type = (coda_hdf4_SDS *)cursor->stack[cursor->n - 1].type; /* determine hyperslab start/edge */ if (type->rank == 0) { coda_set_error(CODA_ERROR_INVALID_ARGUMENT, "partial array reading not allowed for zero " "dimensional HDF4 SDS"); return -1; } for (i = type->rank - 1; i >= 0; i--) { if (length <= block_size * type->dimsizes[i]) { if (length % block_size != 0) { coda_set_error(CODA_ERROR_INVALID_ARGUMENT, "partial array reading for HDF4 SDS requires " "length (%ld) to be a multiple of the subdimension size (%ld)", length, block_size); return -1; } start[i] = (offset / block_size) % type->dimsizes[i]; edge[i] = length / block_size; break; } start[i] = 0; edge[i] = type->dimsizes[i]; block_size *= type->dimsizes[i]; } if (offset % block_size != 0) { coda_set_error(CODA_ERROR_INVALID_ARGUMENT, "partial array reading for HDF4 SDS requires offset " "(%ld) to be a multiple of the subdimension size (%ld)", offset, block_size); return -1; } if (start[i] + edge[i] > type->dimsizes[i]) { coda_set_error(CODA_ERROR_INVALID_ARGUMENT, "partial array reading for HDF4 SDS requires offset " "(%ld) and length (%ld) to represent a hyperslab (range [%ld,%ld] exceeds length " "of dimension #%d (%ld)))", offset, length, (long)start[i], (long)start[i] + edge[i] - 1, i, type->dimsizes[i]); return -1; } while (i > 0) { block_size *= type->dimsizes[i]; i--; start[i] = (offset / block_size) % type->dimsizes[i]; edge[i] = 1; } if (SDreaddata(type->sds_id, start, NULL, edge, dst) != 0) { coda_set_error(CODA_ERROR_HDF4, NULL); return -1; } } break; case tag_hdf4_Vdata_field: coda_set_error(CODA_ERROR_INVALID_ARGUMENT, "partial array reading is not supported for HDF4 Vdata"); return -1; default: assert(0); exit(1); } return 0; }
static int read_basic_type(const coda_cursor *cursor, void *dst) { int32 start[MAX_HDF4_VAR_DIMS]; int32 stride[MAX_HDF4_VAR_DIMS]; int32 edge[MAX_HDF4_VAR_DIMS]; long index; long i; index = cursor->stack[cursor->n - 1].index; assert(cursor->n > 1); switch (((coda_hdf4_type *)cursor->stack[cursor->n - 2].type)->tag) { case tag_hdf4_basic_type_array: { coda_cursor array_cursor; char *buffer; int native_type_size; long num_elements; /* we first read the whole array and then return only the requested element */ array_cursor = *cursor; array_cursor.n--; if (coda_cursor_get_num_elements(&array_cursor, &num_elements) != 0) { return -1; } assert(index < num_elements); native_type_size = get_native_type_size(((coda_hdf4_type *)cursor->stack[cursor->n - 1].type)->definition->read_type); buffer = malloc(num_elements * native_type_size); if (buffer == NULL) { coda_set_error(CODA_ERROR_OUT_OF_MEMORY, "out of memory (could not allocate %lu bytes) (%s:%u)", (long)(num_elements * native_type_size), __FILE__, __LINE__); return -1; } if (read_attribute(&array_cursor, buffer, -1) != 0) { free(buffer); return -1; } memcpy(dst, &buffer[index * native_type_size], native_type_size); free(buffer); } break; case tag_hdf4_attributes: case tag_hdf4_file_attributes: if (read_attribute(cursor, dst, -1) != 0) { return -1; } break; case tag_hdf4_GRImage: { coda_hdf4_GRImage *type; stride[0] = 1; stride[1] = 1; edge[0] = 1; edge[1] = 1; type = (coda_hdf4_GRImage *)cursor->stack[cursor->n - 2].type; if (type->ncomp != 1) { uint8 *buffer; int component_size; int component_index; component_size = get_native_type_size(type->basic_type->definition->read_type); /* HDF4 does not allow reading a single component of a GRImage, so we have to first read all * components and then return only the data item that was requested */ buffer = malloc(component_size * type->ncomp); if (buffer == NULL) { coda_set_error(CODA_ERROR_OUT_OF_MEMORY, "out of memory (could not allocate %lu bytes) (%s:%u)", (long)(component_size * type->ncomp), __FILE__, __LINE__); return -1; } component_index = index % type->ncomp; index /= type->ncomp; /* For GRImage data the first dimension is the fastest running */ start[0] = index % type->dim_sizes[0]; start[1] = index / type->dim_sizes[0]; if (GRreadimage(type->ri_id, start, stride, edge, buffer) != 0) { coda_set_error(CODA_ERROR_HDF4, NULL); free(buffer); return -1; } memcpy(dst, &buffer[component_index * component_size], component_size); free(buffer); } else { /* For GRImage data the first dimension is the fastest running */ start[0] = index % type->dim_sizes[0]; start[1] = index / type->dim_sizes[0]; if (GRreadimage(type->ri_id, start, stride, edge, dst) != 0) { coda_set_error(CODA_ERROR_HDF4, NULL); return -1; } } } break; case tag_hdf4_SDS: { coda_hdf4_SDS *type; type = (coda_hdf4_SDS *)cursor->stack[cursor->n - 2].type; if (type->rank == 0) { start[0] = 0; edge[1] = 1; } else { for (i = type->rank - 1; i >= 0; i--) { start[i] = index % type->dimsizes[i]; index /= type->dimsizes[i]; edge[i] = 1; } } if (SDreaddata(type->sds_id, start, NULL, edge, dst) != 0) { coda_set_error(CODA_ERROR_HDF4, NULL); return -1; } } break; case tag_hdf4_Vdata_field: { coda_hdf4_Vdata *type; coda_hdf4_Vdata_field *field_type; int record_pos; int order_pos; assert(cursor->n > 2); type = (coda_hdf4_Vdata *)cursor->stack[cursor->n - 3].type; field_type = (coda_hdf4_Vdata_field *)cursor->stack[cursor->n - 2].type; order_pos = index % field_type->order; record_pos = index / field_type->order; if (VSseek(type->vdata_id, record_pos) < 0) { coda_set_error(CODA_ERROR_HDF4, NULL); return -1; } if (VSsetfields(type->vdata_id, field_type->field_name) != 0) { coda_set_error(CODA_ERROR_HDF4, NULL); return -1; } if (field_type->order > 1) { /* HDF4 does not allow reading part of a vdata field, so we have to first read the full field and * then return only the data item that was requested */ uint8 *buffer; int element_size; int size; size = VSsizeof(type->vdata_id, field_type->field_name); if (size < 0) { coda_set_error(CODA_ERROR_HDF4, NULL); return -1; } buffer = malloc(size); if (buffer == NULL) { coda_set_error(CODA_ERROR_OUT_OF_MEMORY, "out of memory (could not allocate %lu bytes) (%s:%u)", (long)size, __FILE__, __LINE__); return -1; } if (VSread(type->vdata_id, buffer, 1, FULL_INTERLACE) < 0) { coda_set_error(CODA_ERROR_HDF4, NULL); free(buffer); return -1; } /* the size of a field element is the field size divided by the order of the field */ element_size = size / field_type->order; memcpy(dst, &buffer[order_pos * element_size], element_size); free(buffer); } else { if (VSread(type->vdata_id, (uint8 *)dst, 1, FULL_INTERLACE) < 0) { coda_set_error(CODA_ERROR_HDF4, NULL); return -1; } } } break; default: assert(0); exit(1); } return 0; }
static int read_array(const coda_cursor *cursor, void *dst) { int32 start[MAX_HDF4_VAR_DIMS]; int32 stride[MAX_HDF4_VAR_DIMS]; int32 edge[MAX_HDF4_VAR_DIMS]; long num_elements; long i; if (coda_hdf4_cursor_get_num_elements(cursor, &num_elements) != 0) { return -1; } if (num_elements <= 0) { /* no data to be read */ return 0; } switch (((coda_hdf4_type *)cursor->stack[cursor->n - 1].type)->tag) { case tag_hdf4_basic_type_array: if (read_attribute(cursor, dst, -1) != 0) { return -1; } break; case tag_hdf4_GRImage: { coda_hdf4_GRImage *type; type = (coda_hdf4_GRImage *)cursor->stack[cursor->n - 1].type; start[0] = 0; start[1] = 0; stride[0] = 1; stride[1] = 1; edge[0] = type->dim_sizes[0]; edge[1] = type->dim_sizes[1]; if (GRreadimage(type->ri_id, start, stride, edge, dst) != 0) { coda_set_error(CODA_ERROR_HDF4, NULL); return -1; } } break; case tag_hdf4_SDS: { coda_hdf4_SDS *type; type = (coda_hdf4_SDS *)cursor->stack[cursor->n - 1].type; if (type->rank == 0) { start[0] = 0; edge[0] = 1; } else { for (i = 0; i < type->rank; i++) { start[i] = 0; edge[i] = type->dimsizes[i]; } } if (SDreaddata(type->sds_id, start, NULL, edge, dst) != 0) { coda_set_error(CODA_ERROR_HDF4, NULL); return -1; } } break; case tag_hdf4_Vdata_field: { coda_hdf4_Vdata *type; coda_hdf4_Vdata_field *field_type; assert(cursor->n > 1); type = (coda_hdf4_Vdata *)cursor->stack[cursor->n - 2].type; field_type = (coda_hdf4_Vdata_field *)cursor->stack[cursor->n - 1].type; if (VSseek(type->vdata_id, 0) < 0) { coda_set_error(CODA_ERROR_HDF4, NULL); return -1; } if (VSsetfields(type->vdata_id, field_type->field_name) != 0) { coda_set_error(CODA_ERROR_HDF4, NULL); return -1; } if (VSread(type->vdata_id, (uint8 *)dst, field_type->num_records, FULL_INTERLACE) < 0) { coda_set_error(CODA_ERROR_HDF4, NULL); return -1; } } break; default: assert(0); exit(1); } return 0; }