func NewImageTile(filename string, r image.Rectangle, width, height int) (err error, tile *ImageTile) { l_stream := C.opj_stream_create_default_file_stream_v3(C.CString(filename), 1) if l_stream == nil { return errors.New("failed to create stream"), nil } l_codec := C.opj_create_decompress(C.OPJ_CODEC_JP2) var parameters C.opj_dparameters_t C.opj_set_default_decoder_parameters(¶meters) level := desired_progression_level(r, width, height) log.Println("desired level:", level) //(parameters).cp_reduce = C.OPJ_UINT32(level) C.set_handlers(l_codec) if err == nil && C.opj_setup_decoder(l_codec, ¶meters) == C.OPJ_FALSE { err = errors.New("failed to setup decoder") } if err == nil && C.opj_set_decoded_resolution_factor(l_codec, C.OPJ_UINT32(level)) == C.OPJ_FALSE { err = errors.New("failed to set decode resolution factor") } var img *C.opj_image_t if err == nil && C.opj_read_header(l_stream, l_codec, &img) == C.OPJ_FALSE { err = errors.New("failed to read the header") } if err == nil { log.Println("num comps:", img.numcomps) log.Println("x0:", img.x0, "x1:", img.x1, "y0:", img.y0, "y1:", img.y1) } if err == nil && C.opj_set_decode_area(l_codec, img, C.OPJ_INT32(r.Min.X), C.OPJ_INT32(r.Min.Y), C.OPJ_INT32(r.Max.X), C.OPJ_INT32(r.Max.Y)) == C.OPJ_FALSE { err = errors.New("failed to set the decoded area") } if err == nil && C.opj_decode(l_codec, l_stream, img) == C.OPJ_FALSE { err = errors.New("failed to decode image") } if err == nil && C.opj_end_decompress(l_codec, l_stream) == C.OPJ_FALSE { err = errors.New("failed to decode image") } C.opj_stream_destroy_v3(l_stream) if l_codec != nil { C.opj_destroy_codec(l_codec) } if err == nil { var comps []C.opj_image_comp_t compsSlice := (*reflect.SliceHeader)((unsafe.Pointer(&comps))) compsSlice.Cap = int(img.numcomps) compsSlice.Len = int(img.numcomps) compsSlice.Data = uintptr(unsafe.Pointer(img.comps)) bounds := image.Rect(0, 0, int(comps[0].w), int(comps[0].h)) var data []int32 dataSlice := (*reflect.SliceHeader)((unsafe.Pointer(&data))) dataSlice.Cap = bounds.Dx() * bounds.Dy() dataSlice.Len = bounds.Dx() * bounds.Dy() dataSlice.Data = uintptr(unsafe.Pointer(comps[0].data)) tile = &ImageTile{data, bounds, bounds.Dx(), img} runtime.SetFinalizer(tile, func(it *ImageTile) { C.opj_image_destroy(it.img) }) } else { C.opj_image_destroy(img) } return }
func (i *JP2Image) cleanupImage() { if i.image != nil { C.opj_image_destroy(i.image) i.image = nil } }