예제 #1
0
int GP_ReadJP2Ex(GP_IO *io, GP_Context **rimg, GP_DataStorage *storage,
                 GP_ProgressCallback *callback)
{
	opj_dparameters_t params;
	opj_codec_t *codec;
	opj_stream_t *stream;
	opj_image_t *img;

	GP_PixelType pixel_type;
	GP_Context *res = NULL;
	unsigned int i, x, y;
	int err = 0, ret = 1;

	opj_set_default_decoder_parameters(&params);

	codec = opj_create_decompress(OPJ_CODEC_JP2);

	if (!codec) {
		GP_DEBUG(1, "opj_create_decompress failed");
		err = ENOMEM;
		goto err0;
	}

	opj_set_error_handler(codec, jp2_err_callback, NULL);
	opj_set_warning_handler(codec, jp2_warn_callback, NULL);
	opj_set_info_handler(codec, jp2_info_callback, callback);

	if (!opj_setup_decoder(codec, &params)) {
		GP_DEBUG(1, "opj_setup_decoder failed");
		err = ENOMEM;
		goto err1;
	}

	stream = opj_stream_default_create(OPJ_TRUE);

	if (!stream) {
		GP_DEBUG(1, "opj_stream_create_default_file_stream faled");
		err = ENOMEM;
		goto err1;
	}

	//TODO: Do we need seek and skip?
	opj_stream_set_read_function(stream, jp2_io_read);
	opj_stream_set_user_data(stream, io);

	if (!opj_read_header(stream, codec, &img)) {
		GP_DEBUG(1, "opj_read_header failed");
		err = EINVAL;
		goto err2;
	}

	if (storage)
		fill_metadata(img, storage);

	GP_DEBUG(1, "Have image %ux%u-%ux%u colorspace=%s numcomps=%u",
	         img->x0, img->y0, img->x1, img->y1,
	         color_space_name(img->color_space), img->numcomps);

	if (!rimg)
		return 0;

	/*
	 * Try to match the image information into pixel type.
	 *
	 * Unfortunately the images I had have color_space set
	 * to unspecified yet they were RGB888.
	 */
	for (i = 0; i < img->numcomps; i++) {
		opj_image_comp_t *comp = &img->comps[i];

		GP_DEBUG(2, "Component %u %ux%u bpp=%u",
		         i, comp->w, comp->h, comp->prec);

		if (comp->w != img->comps[0].w ||
		    comp->h != img->comps[0].h) {
			GP_DEBUG(1, "Component %u has different size", 1);
			err = ENOSYS;
			goto err3;
		}

		if (comp->prec != 8) {
			GP_DEBUG(1, "Component %u has different bpp", 1);
			err = ENOSYS;
			goto err3;
		}
	}

	switch (img->color_space) {
	case OPJ_CLRSPC_UNSPECIFIED:
		if (img->numcomps != 3) {
			GP_DEBUG(1, "Unexpected number of components");
			err = ENOSYS;
			goto err3;
		}
		pixel_type = GP_PIXEL_RGB888;
	break;
	default:
		GP_DEBUG(1, "Unsupported colorspace");
		err = ENOSYS;
		goto err3;
	}

	GP_ProgressCallbackReport(callback, 0, 100, 100);

	if (!opj_decode(codec, stream, img)) {
		GP_DEBUG(1, "opj_decode failed");
		err = EINVAL;
		goto err3;
	}

	res = GP_ContextAlloc(img->comps[0].w, img->comps[0].h, pixel_type);

	if (!res) {
		GP_DEBUG(1, "Malloc failed :(");
		err = ENOMEM;
		goto err3;
	}

	for (y = 0; y < res->h; y++) {
		for (x = 0; x < res->w; x++) {
			i = y * res->w + x;

			GP_Pixel p = img->comps[0].data[i] << 16|
			             img->comps[1].data[i] << 8 |
			             img->comps[2].data[i];

			GP_PutPixel_Raw_24BPP(res, x, y, p);
		}
	}

	GP_ProgressCallbackDone(callback);
	*rimg = res;
	ret = 0;
err3:
	opj_image_destroy(img);
err2:
	opj_stream_destroy(stream);
err1:
	opj_destroy_codec(codec);
err0:
	if (err)
		errno = err;
	return ret;
}
예제 #2
0
int GP_ReadJPGEx(GP_IO *io, GP_Context **img,
		 GP_DataStorage *storage, GP_ProgressCallback *callback)
{
	struct jpeg_decompress_struct cinfo;
	struct my_source_mgr src;
	struct my_jpg_err my_err;
	GP_Context *ret = NULL;
	uint8_t buf[1024];
	int err;

	cinfo.err = jpeg_std_error(&my_err.error_mgr);
	my_err.error_mgr.error_exit = my_error_exit;

	if (setjmp(my_err.setjmp_buf)) {
		err = EIO;
		goto err2;
	}

	jpeg_create_decompress(&cinfo);
	init_source_mgr(&src, io, buf, sizeof(buf));
	cinfo.src = (void*)&src;

	if (storage)
		save_jpg_markers(&cinfo);

	jpeg_read_header(&cinfo, TRUE);

	GP_DEBUG(1, "Have %s JPEG size %ux%u %i channels",
	            get_colorspace(cinfo.jpeg_color_space),
	            cinfo.image_width, cinfo.image_height,
		    cinfo.num_components);

	//TODO: Propagate failure?
	if (storage)
		read_jpg_metadata(&cinfo, storage);

	if (!img)
		goto exit;

	GP_Pixel pixel_type;

	switch (cinfo.out_color_space) {
	case JCS_GRAYSCALE:
		pixel_type = GP_PIXEL_G8;
	break;
	case JCS_RGB:
		pixel_type = GP_PIXEL_BGR888;
	break;
	case JCS_CMYK:
		pixel_type = GP_PIXEL_CMYK8888;
	break;
	default:
		pixel_type = GP_PIXEL_UNKNOWN;
	}

	if (pixel_type == GP_PIXEL_UNKNOWN) {
		GP_DEBUG(1, "Can't handle %s JPEG output format",
		            get_colorspace(cinfo.out_color_space));
		err = ENOSYS;
		goto err1;
	}

	ret = GP_ContextAlloc(cinfo.image_width, cinfo.image_height,
	                      pixel_type);

	if (ret == NULL) {
		GP_DEBUG(1, "Malloc failed :(");
		err = ENOMEM;
		goto err1;
	}

	jpeg_start_decompress(&cinfo);

	switch (pixel_type) {
	case GP_PIXEL_BGR888:
	case GP_PIXEL_G8:
		err = load(&cinfo, ret, callback);
	break;
	case GP_PIXEL_CMYK8888:
		err = load_cmyk(&cinfo, ret, callback);
	break;
	default:
		err = EINVAL;
	}

	if (err)
		goto err2;

	jpeg_finish_decompress(&cinfo);
exit:
	jpeg_destroy_decompress(&cinfo);

	GP_ProgressCallbackDone(callback);

	if (img)
		*img = ret;

	return 0;
err2:
	GP_ContextFree(ret);
err1:
	jpeg_destroy_decompress(&cinfo);
	errno = err;
	return 1;
}
예제 #3
0
int GP_WriteJPG(const GP_Context *src, GP_IO *io,
                GP_ProgressCallback *callback)
{
	struct jpeg_compress_struct cinfo;
	GP_PixelType out_pix;
	struct my_jpg_err my_err;
	struct my_dest_mgr dst;
	uint8_t buf[1024];
	int err;

	GP_DEBUG(1, "Writing JPG Image to I/O (%p)", io);

	out_pix = GP_LineConvertible(src->pixel_type, out_pixel_types);

	if (out_pix == GP_PIXEL_UNKNOWN) {
		GP_DEBUG(1, "Unsupported pixel type %s",
		         GP_PixelTypeName(src->pixel_type));
		errno = ENOSYS;
		return 1;
	}

	if (setjmp(my_err.setjmp_buf)) {
		errno = EIO;
		return 1;

	}

	cinfo.err = jpeg_std_error(&my_err.error_mgr);
	my_err.error_mgr.error_exit = my_error_exit;

	jpeg_create_compress(&cinfo);

	init_dest_mgr(&dst, io, buf, sizeof(buf));
	cinfo.dest = (void*)&dst;

	cinfo.image_width  = src->w;
	cinfo.image_height = src->h;

	switch (out_pix) {
	case GP_PIXEL_BGR888:
		cinfo.input_components = 3;
		cinfo.in_color_space = JCS_RGB;
	break;
	case GP_PIXEL_G8:
		cinfo.input_components = 1;
		cinfo.in_color_space = JCS_GRAYSCALE;
	break;
	default:
		GP_BUG("Don't know how to set color_space and compoments");
	}

	jpeg_set_defaults(&cinfo);

	jpeg_start_compress(&cinfo, TRUE);

	if (out_pix != src->pixel_type)
		err = save_convert(&cinfo, src, out_pix, callback);
	else
		err = save(&cinfo, src, callback);

	if (err) {
		jpeg_destroy_compress(&cinfo);
		errno = err;
		return 1;
	}

	jpeg_finish_compress(&cinfo);
	jpeg_destroy_compress(&cinfo);

	GP_ProgressCallbackDone(callback);
	return 0;
}
예제 #4
0
파일: GP_Blur.c 프로젝트: m1ch4ls/gfxprim
int GP_FilterGaussianBlur_Raw(const GP_Context *src,
                              GP_Coord x_src, GP_Coord y_src,
                              GP_Size w_src, GP_Size h_src,
			      GP_Context *dst,
                              GP_Coord x_dst, GP_Coord y_dst,
                              float sigma_x, float sigma_y,
                              GP_ProgressCallback *callback)
{
	unsigned int size_x = gaussian_kernel_size(sigma_x);
	unsigned int size_y = gaussian_kernel_size(sigma_y);

	GP_DEBUG(1, "Gaussian blur sigma_x=%2.3f sigma_y=%2.3f kernel %ix%i image %ux%u",
	            sigma_x, sigma_y, size_x, size_y, w_src, h_src);

	GP_ProgressCallback *new_callback = NULL;

	GP_ProgressCallback gaussian_callback = {
		.callback = gaussian_callback_horiz,
		.priv = callback
	};

	if (callback != NULL)
		new_callback = &gaussian_callback;

	/* compute kernel and apply in horizontal direction */
	if (sigma_x > 0) {
		float kernel_x[size_x];
		float sum = gaussian_kernel_init(sigma_x, kernel_x);

		GP_ConvolutionParams params = {
			.src = src,
			.x_src = x_src,
			.y_src = y_src,
			.w_src = w_src,
			.h_src = h_src,
			.dst = dst,
			.x_dst = x_dst,
			.y_dst = y_dst,
			.kernel = kernel_x,
			.kw = size_x,
			.kh = 1,
			.kern_div = sum,
			.callback = new_callback,
		};

		if (GP_FilterHConvolutionMP_Raw(&params))
			return 1;
	}

	if (new_callback != NULL)
		new_callback->callback = gaussian_callback_vert;

	/* compute kernel and apply in vertical direction */
	if (sigma_y > 0) {
		float kernel_y[size_y];
		float sum = gaussian_kernel_init(sigma_y, kernel_y);

		GP_ConvolutionParams params = {
			.src = src,
			.x_src = x_src,
			.y_src = y_src,
			.w_src = w_src,
			.h_src = h_src,
			.dst = dst,
			.x_dst = x_dst,
			.y_dst = y_dst,
			.kernel = kernel_y,
			.kw = 1,
			.kh = size_y,
			.kern_div = sum,
			.callback = new_callback,
		};

		if (GP_FilterVConvolutionMP_Raw(&params))
			return 1;
	}

	GP_ProgressCallbackDone(callback);
	return 0;
}