Ejemplo n.º 1
0
static RSFilterResponse *
get_image(RSFilter *filter, const RSFilterRequest *request)
{
	RSDcp *dcp = RS_DCP(filter);
	RSDcpClass *klass = RS_DCP_GET_CLASS(dcp);
	GdkRectangle *roi;
	RSFilterResponse *previous_response;
	RSFilterResponse *response;
	RS_IMAGE16 *input;
	RS_IMAGE16 *output;
	RS_IMAGE16 *tmp;

	gint j;

	RSFilterRequest *request_clone = rs_filter_request_clone(request);

	if (!dcp->use_profile)
	{
		gfloat premul[4] = {dcp->pre_mul.x, dcp->pre_mul.y, dcp->pre_mul.z, 1.0};
		rs_filter_param_set_float4(RS_FILTER_PARAM(request_clone), "premul", premul);
	}

	rs_filter_param_set_object(RS_FILTER_PARAM(request_clone), "colorspace", klass->prophoto);
	previous_response = rs_filter_get_image(filter->previous, request_clone);
	g_object_unref(request_clone);

	if (!RS_IS_FILTER(filter->previous))
		return previous_response;

	input = rs_filter_response_get_image(previous_response);
	if (!input) return previous_response;
	response = rs_filter_response_clone(previous_response);

	/* We always deliver in ProPhoto */
	rs_filter_param_set_object(RS_FILTER_PARAM(response), "colorspace", klass->prophoto);
	g_object_unref(previous_response);

	if ((roi = rs_filter_request_get_roi(request)))
	{
		/* Align so we start at even pixel counts */
		roi->width += (roi->x&1);
		roi->x -= (roi->x&1);
		roi->width = MIN(input->w - roi->x, roi->width);
		output = rs_image16_copy(input, FALSE);
		tmp = rs_image16_new_subframe(output, roi);
		bit_blt((char*)GET_PIXEL(tmp,0,0), tmp->rowstride * 2, 
			(const char*)GET_PIXEL(input,roi->x,roi->y), input->rowstride * 2, tmp->w * tmp->pixelsize * 2, tmp->h);
	}
	else
	{
		output = rs_image16_copy(input, TRUE);
		tmp = g_object_ref(output);
	}
	g_object_unref(input);
	rs_filter_response_set_image(response, output);
	g_object_unref(output);

	g_static_rec_mutex_lock(&dcp_mutex);
	init_exposure(dcp);

	guint i, y_offset, y_per_thread, threaded_h;
	guint threads = rs_get_number_of_processor_cores();
	if (tmp->h * tmp->w < 200*200)
		threads = 1;

	ThreadInfo *t = g_new(ThreadInfo, threads);

	threaded_h = tmp->h;
	y_per_thread = (threaded_h + threads-1)/threads;
	y_offset = 0;

	for (i = 0; i < threads; i++)
	{
		t[i].tmp = tmp;
		t[i].start_y = y_offset;
		t[i].start_x = 0;
		t[i].dcp = dcp;
		y_offset += y_per_thread;
		y_offset = MIN(tmp->h, y_offset);
		t[i].end_y = y_offset;
		for(j = 0; j < 256; j++)
			t[i].curve_input_values[j] = 0;
		t[i].single_thread = (threads == 1);
		if (threads == 1)
			start_single_dcp_thread(&t[0]);
		else	
			t[i].threadid = g_thread_create(start_single_dcp_thread, &t[i], TRUE, NULL);
	}

	/* Wait for threads to finish */
	for(i = 0; threads > 1 && i < threads; i++)
		g_thread_join(t[i].threadid);

	/* Settings can change now */
	g_static_rec_mutex_unlock(&dcp_mutex);

	/* If we must deliver histogram data, do it now */
	if (dcp->read_out_curve)
	{
		gint *values = g_malloc0(256*sizeof(gint));
		for(i = 0; i < threads; i++)
			for(j = 0; j < 256; j++)
				values[j] += t[i].curve_input_values[j];
		rs_curve_set_histogram_data(RS_CURVE_WIDGET(dcp->read_out_curve), values);
		g_free(values);
	}
	g_free(t);
	g_object_unref(tmp);

	return response;
}
Ejemplo n.º 2
0
/**
 * Open an image using libpng
 * @param filename The filename to open
 * @return The newly created RS_IMAGE16 or NULL on error
 */
static RSFilterResponse*
load_png(const gchar *filename)
{
  gfloat gamma_guess = 2.2f;
  RSColorSpace *input_space = exiv2_get_colorspace(filename, &gamma_guess);

  int width, height, rowbytes;
  png_byte color_type;
  png_byte bit_depth;

  png_structp png_ptr;
  png_infop info_ptr;
  png_bytep * row_pointers;

  unsigned char header[8];    // 8 is the maximum size that can be checked

  /* open file and test for it being a png */
  FILE *fp = fopen(filename, "rb");
  if (!fp)
    return NULL;

  if (!fread(header, 1, 8, fp))
    return NULL;

  if (png_sig_cmp(header, 0, 8))
    return NULL;

  /* initialize stuff */
  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

  if (!png_ptr)
    return NULL;

  info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr)
    return NULL;

  if (setjmp(png_jmpbuf(png_ptr)))
    return NULL;

  png_init_io(png_ptr, fp);
  png_set_sig_bytes(png_ptr, 8);

  png_read_info(png_ptr, info_ptr);

  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);

#ifdef DEBUG
  printf("width: %u\n", (guint32) width);
  printf("height: %u\n", (guint32) height);
  printf("bit_depth: %d\n", bit_depth);
  printf("color_type: %d\n", color_type);
#endif

  /* currently we only support 16BIT RGBA */
  if (color_type != PNG_COLOR_TYPE_RGB_ALPHA || bit_depth != 16)
    return NULL;

  png_read_update_info(png_ptr, info_ptr);

  /* read file */
  if (setjmp(png_jmpbuf(png_ptr)))
    return NULL;

  row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);

  if (bit_depth == 16)
    rowbytes = width*8;
  else
    rowbytes = width*4;

  gint y,x;
  gint dest = 0;

  for (y=0; y<height; y++)
    row_pointers[y] = (png_byte*) malloc(rowbytes);

  png_read_image(png_ptr, row_pointers);

  RS_IMAGE16 *image = rs_image16_new(width, height, 3, 4);

  for (y=0; y<height; y++) {
    png_byte* row = row_pointers[y];
    for (x=0; x<width; x++) {
      png_byte* ptr = &(row[x*8]);
      image->pixels[dest++] = CLAMP((ptr[0]<<8)|ptr[1], 0, 65535);
      image->pixels[dest++] = CLAMP((ptr[2]<<8)|ptr[3], 0, 65535);
      image->pixels[dest++] = CLAMP((ptr[4]<<8)|ptr[5], 0, 65335);
      dest++;
    }
  }

  RSFilterResponse* response = rs_filter_response_new();
  if (image)
    {
      rs_filter_response_set_image(response, image);
      rs_filter_response_set_width(response, image->w);
      rs_filter_response_set_height(response, image->h);
      g_object_unref(image);
      rs_filter_param_set_object(RS_FILTER_PARAM(response), "embedded-colorspace", input_space);
      rs_filter_param_set_boolean(RS_FILTER_PARAM(response), "is-premultiplied", TRUE);
    }
  return response;

  return NULL;
}