예제 #1
0
void psd_layer_type_tool_free(psd_uint info_data)
{
    psd_layer_type_tool * data;
    psd_int i;

    data = (psd_layer_type_tool *)info_data;
    for(i = 0; i < data->faces_count; i ++)
        psd_free(data->face[i].vector);
    psd_free(data->face);
    psd_free(data->style);
    psd_free(data->line);
    psd_free(data);
}
예제 #2
0
파일: levels.c 프로젝트: IreNox/tiki3
void psd_layer_levels_free(psd_uint info_data)
{
	psd_layer_levels * data;

	data = (psd_layer_levels *)info_data;
	psd_freeif(data->extra_record);
	psd_free(data);
}
예제 #3
0
파일: psd.c 프로젝트: jfiguinha/Regards
psd_status psd_image_free(psd_context * context)
{
	if(context == NULL)
		return psd_status_invalid_context;
	
	psd_color_mode_data_free(context);
	psd_image_resource_free(context);
	psd_layer_and_mask_free(context);
	psd_image_data_free(context);
	
	psd_image_blend_free(context);
	psd_stream_free(context);
	
	psd_free(context);

	return psd_status_done;
}
예제 #4
0
파일: psd.c 프로젝트: Sumxx/XUI
static psd_status psd_image_load_tag(psd_context ** dst_context, psd_char * file_name, psd_load_tag load_tag)
{
	psd_context * context;
	psd_status status;

	if(dst_context == NULL)
		return psd_status_invalid_context;
	if(file_name == NULL)
		return psd_status_invalid_file;

	context = (psd_context *)psd_malloc(sizeof(psd_context));
	if(context == NULL)
		return psd_status_malloc_failed;
	memset(context, 0, sizeof(psd_context));

	context->ops_ = &psd_std_fileops;
	context->file_name = file_name;
	context->file = psd_fopen(file_name);
	if (context->file == NULL)
	{
		psd_free(context);
		return psd_status_invalid_file;
	}
	
	context->state = PSD_FILE_HEADER;
	context->stream.file_length = psd_fsize(context->file);
	context->load_tag = load_tag;
	status = psd_main_loop(context);
	
	if(status != psd_status_done)
	{
		psd_image_free(context);
		context = NULL;
	}
	else
	{
		psd_stream_free(context);
	}
	
	*dst_context = context;

	return status;
}
예제 #5
0
파일: test.c 프로젝트: Sumxx/XUI
int main (int argc, char **argv)
{
	psd_context * context = NULL;
	psd_status status;
	
	if(argc <= 1)
		return -1;

	// parse the psd file to psd_context
	status = psd_image_load(&context, argv[1]);

	// use it...
	//
	
	// free if it's done
	psd_image_free(context);
	psd_free(context);

	return (status == psd_status_done ? 0 : -1);
}
예제 #6
0
psd_status psd_layer_effects_blend_drop_shadow(psd_context * context, psd_layer_record * layer, psd_layer_effects * data)
{
	psd_layer_effects_drop_shadow * drop_shadow = &data->drop_shadow;
	psd_int width, height;
	psd_int angle;
	psd_int distance_x, distance_y;
	psd_bitmap src_bmp, dst_bmp, knock_bmp;
	psd_layer_mask_info layer_mask_info;
	psd_int spread_size, blur_size;
	
	if(drop_shadow->use_global_light == psd_true)
		angle = context->global_angle;
	else
		angle = drop_shadow->angle;
	distance_x = -(psd_int)(drop_shadow->distance * cos(PSD_PI * angle / 180) + 0.5);
	distance_y = (psd_int)(drop_shadow->distance * sin(PSD_PI * angle / 180) + 0.5);
	
	data->left[psd_layer_effects_type_drop_shadow] = -drop_shadow->size + distance_x;
	data->top[psd_layer_effects_type_drop_shadow] = -drop_shadow->size + distance_y;
	width = layer->width + drop_shadow->size * 2;
	height = layer->height + drop_shadow->size * 2;
	data->right[psd_layer_effects_type_drop_shadow] = data->left[psd_layer_effects_type_drop_shadow] + width;
	data->bottom[psd_layer_effects_type_drop_shadow] = data->top[psd_layer_effects_type_drop_shadow] + height;
	data->blend_mode[psd_layer_effects_type_drop_shadow] = drop_shadow->blend_mode;
	data->opacity[psd_layer_effects_type_drop_shadow] = drop_shadow->opacity;

	if(data->image_data[psd_layer_effects_type_drop_shadow] != NULL)
	{
		if(data->width[psd_layer_effects_type_drop_shadow] != width ||
			data->height[psd_layer_effects_type_drop_shadow] != height)
		{
			psd_free(data->image_data[psd_layer_effects_type_drop_shadow]);
			data->image_data[psd_layer_effects_type_drop_shadow] = (psd_argb_color *)psd_malloc(width * height * 4);
			if(data->image_data[psd_layer_effects_type_drop_shadow] == NULL)
				return psd_status_malloc_failed;
		}
	}
	else
	{
		data->image_data[psd_layer_effects_type_drop_shadow] = (psd_argb_color *)psd_malloc(width * height * 4);
		if(data->image_data[psd_layer_effects_type_drop_shadow] == NULL)
			return psd_status_malloc_failed;
	}
	data->width[psd_layer_effects_type_drop_shadow] = width;
	data->height[psd_layer_effects_type_drop_shadow] = height;
	psd_color_memset(data->image_data[psd_layer_effects_type_drop_shadow], drop_shadow->color, width * height);

	src_bmp.width = layer->width;
	src_bmp.height = layer->height;
	src_bmp.image_data = layer->image_data;
	dst_bmp.width = width;
	dst_bmp.height = height;
	dst_bmp.image_data = data->image_data[psd_layer_effects_type_drop_shadow];

	if(drop_shadow->size == 0)
	{
		psd_fill_bitmap(&dst_bmp, drop_shadow->color);
		psd_bitmap_copy_alpha_channel(&dst_bmp, &src_bmp);
	}
	else
	{
		psd_inflate_bitmap(&dst_bmp, &src_bmp, drop_shadow->size, drop_shadow->size);
		psd_fill_bitmap_without_alpha_channel(&dst_bmp, drop_shadow->color);
	}

	memcpy(&layer_mask_info, &layer->layer_mask_info, sizeof(psd_layer_mask_info));
	if(layer_mask_info.disabled == psd_false && (layer_mask_info.default_color != 255 || layer_mask_info.mask_data != NULL))
	{
		layer_mask_info.left -= layer->left - drop_shadow->size;
		layer_mask_info.top -= layer->top - drop_shadow->size;
		layer_mask_info.right -= layer->left - drop_shadow->size;
		layer_mask_info.bottom -= layer->top - drop_shadow->size;
		psd_bitmap_blend_mask(&dst_bmp, &layer_mask_info);
	}

	if(drop_shadow->knocks_out == psd_true)
	{
		psd_create_bitmap(&knock_bmp, width, height);
		psd_copy_bitmap(&knock_bmp, &dst_bmp);
		psd_offset_bitmap(&knock_bmp, distance_x, distance_y, psd_color_clear);
	}
	
	spread_size = (drop_shadow->spread * drop_shadow->size + 50) / 100;
	blur_size = drop_shadow->size - spread_size;
	if(spread_size != 0)
	{
		psd_bitmap_gaussian_blur_alpha_channel(&dst_bmp, spread_size);
		psd_bitmap_find_edge(&dst_bmp, psd_true);
	}
	if(blur_size != 0)
	{
		psd_bitmap_gaussian_blur_alpha_channel(&dst_bmp, blur_size);
	}

	psd_bitmap_contour_alpha_channel(&dst_bmp, drop_shadow->contour_lookup_table, 
		drop_shadow->anti_aliased, psd_true);

	if(drop_shadow->noise > 0)
	{
		psd_effects_add_noise(&dst_bmp, drop_shadow->noise, 
			data->left[psd_layer_effects_type_drop_shadow] + layer->left,
			data->top[psd_layer_effects_type_drop_shadow] + layer->top, context);
	}

	if(drop_shadow->knocks_out == psd_true)
	{
		psd_bitmap_knock_out(&dst_bmp, &knock_bmp);
		psd_free_bitmap(&knock_bmp);
	}
	
	data->valid[psd_layer_effects_type_drop_shadow] = psd_false;
	
	return psd_status_done;
}
예제 #7
0
void psd_freeif(void * block)
{
	if (block != NULL)
		psd_free(block);
}
예제 #8
0
void psd_bitmap_gaussian_blur_alpha_channel(psd_bitmap * bitmap, psd_double radius)
{
	psd_int     width, height;
	psd_int    *buf, *bb;
	psd_int     pixels;
	psd_int     total = 1, total2;
	psd_int     i, row, col;
	psd_int     start, end;
	psd_int    *curve;
	psd_int    *sum = NULL;
	psd_int     val;
	psd_int     length;
	psd_int     initial_p, initial_m;
	psd_double  std_dev;
	psd_color_component * src, * sp;
	psd_argb_color * src_data, * dst_data;

	if(radius <= 0.0)
		return;

	width  = bitmap->width;
	height = bitmap->height;

	if(width < 1 || height < 1)
		return;

	buf = (psd_int *)psd_malloc(PSD_MAX(width, height) * 2 * sizeof(psd_int));
	src = (psd_color_component *)psd_malloc(PSD_MAX(width, height));

	/*  First the vertical pass  */
	radius = fabs(radius) * 1.4;
	std_dev = sqrt(-(radius * radius) / (2 * log(1.0 / 255.0)));

	curve = psd_make_curve (std_dev, &length);
	sum = (psd_int *)psd_malloc((2 * length + 1) * sizeof(psd_int));

	sum[0] = 0;
	for(i = 1; i <= length*2; i++)
		sum[i] = curve[i-length-1] + sum[i-1];
	sum += length;

	total = sum[length] - sum[-length];
	total2 = total / 2;

	/*  First, the vertical pass  */
	for(col = 0; col < width; col++)
	{
		for(row = 0, src_data = bitmap->image_data + width + col; row < height - 1; row ++, src_data += width)
			src[row] = PSD_GET_ALPHA_COMPONENT(*src_data);
		src[height - 1] = 0;

		sp = src;

		initial_p = *sp;
		initial_m = *(sp + height - 1);

		/*  Determine a run-length encoded version of the row  */
		psd_run_length_encode(sp, buf, height);

		for(row = 0, dst_data = bitmap->image_data + col; row < height; row ++, dst_data += width)
		{
			start = (row < length) ? -row : -length;
			end = (height <= (row + length) ? (height - row - 1) : length);

			val = 0;
			i = start;
			bb = buf + (row + i) * 2;

			if(start != -length)
				val += initial_p * (sum[start] - sum[-length]);

			while(i < end)
			{
				pixels = bb[0];
				i += pixels;

				if(i > end)
					i = end;

				val += bb[1] * (sum[i] - sum[start]);
				bb += (pixels * 2);
				start = i;
			}

			if(end != length)
				val += initial_m * (sum[length] - sum[end]);

			*dst_data = (*dst_data & 0x00FFFFFF) | ((val + total2) / total << 24);
		}
	}

	/*  Now the horizontal pass  */
	for(row = 0; row < height; row++)
	{
		for(col = 0, src_data = bitmap->image_data + row * width + 1; col < width - 1; col ++, src_data ++)
			src[col] = PSD_GET_ALPHA_COMPONENT(*src_data);
		src[width - 1] = 0;

		sp = src;

		initial_p = *sp;
		initial_m = *(sp + width - 1);

		/*  Determine a run-length encoded version of the row  */
		psd_run_length_encode(sp, buf, width);

		for(col = 0, dst_data = bitmap->image_data + row * width; col < width; col ++, dst_data ++)
		{
			start = (col < length) ? -col : -length;
			end = (width <= (col + length)) ? (width - col - 1) : length;

			val = 0;
			i = start;
			bb = buf + (col + i) * 2;

			if(start != -length)
				val += initial_p * (sum[start] - sum[-length]);

			while(i < end)
			{
				pixels = bb[0];
				i += pixels;

				if(i > end)
					i = end;

				val += bb[1] * (sum[i] - sum[start]);
				bb += (pixels * 2);
				start = i;
			}

			if(end != length)
				val += initial_m * (sum[length] - sum[end]);

			*dst_data = (*dst_data & 0x00FFFFFF) | ((val + total2) / total << 24);
		}
	}

	/*  free buffers  */
	psd_free(curve - length);
	psd_free(sum - length);
	psd_free(buf);
	psd_free(src);
}
예제 #9
0
파일: stroke.c 프로젝트: 5daysfish/psdump
psd_status psd_layer_effects_blend_stroke(psd_context * context, psd_layer_record * layer, psd_layer_effects * data)
{
	psd_layer_effects_stroke * stroke = &data->stroke;
	psd_int i, width, height, center_x, center_y, radius_x, radius_y, radius_corner;
	psd_int corner_angle, angle;
	psd_int sign_x = 1, sign_y = 1;
	psd_bitmap layer_bmp, src_bmp, dst_bmp;
	psd_layer_mask_info layer_mask_info;

	width = layer->width + stroke->size * 2;
	height = layer->height + stroke->size * 2;
	data->left[psd_layer_effects_type_stroke] = -stroke->size;
	data->top[psd_layer_effects_type_stroke] = -stroke->size;
	data->right[psd_layer_effects_type_stroke] = layer->width + stroke->size;
	data->bottom[psd_layer_effects_type_stroke] = layer->height + stroke->size;
	data->blend_mode[psd_layer_effects_type_stroke] = stroke->blend_mode;
	data->opacity[psd_layer_effects_type_stroke] = stroke->opacity;

	if(data->image_data[psd_layer_effects_type_stroke] != NULL)
	{
		if(data->width[psd_layer_effects_type_stroke] != width ||
			data->height[psd_layer_effects_type_stroke] != height)
		{
			psd_free(data->image_data[psd_layer_effects_type_stroke]);
			data->image_data[psd_layer_effects_type_stroke] = (psd_argb_color *)psd_malloc(width * height * 4);
			if(data->image_data[psd_layer_effects_type_stroke] == NULL)
				return psd_status_malloc_failed;
		}
	}
	else
	{
		data->image_data[psd_layer_effects_type_stroke] = (psd_argb_color *)psd_malloc(width * height * 4);
		if(data->image_data[psd_layer_effects_type_stroke] == NULL)
			return psd_status_malloc_failed;
	}
	data->width[psd_layer_effects_type_stroke] = width;
	data->height[psd_layer_effects_type_stroke] = height;

	layer_bmp.width = layer->width;
	layer_bmp.height = layer->height;
	layer_bmp.image_data = layer->image_data;
	psd_create_bitmap(&src_bmp, width, height);
	psd_inflate_bitmap(&src_bmp, &layer_bmp, stroke->size, stroke->size);
	dst_bmp.width = width;
	dst_bmp.height = height;
	dst_bmp.image_data = data->image_data[psd_layer_effects_type_stroke];

	psd_fill_bitmap(&dst_bmp, psd_color_clear);
	switch(stroke->position)
	{
		case psd_stroke_outside:
			psd_draw_stroke(&dst_bmp, &src_bmp, stroke->size * 2);
			psd_bitmap_find_edge(&src_bmp, psd_true);
			psd_bitmap_knock_out(&dst_bmp, &src_bmp);
			break;
		case psd_stroke_inside:
			psd_draw_stroke(&dst_bmp, &src_bmp, stroke->size * 2);
			psd_bitmap_find_edge(&src_bmp, psd_true);
			psd_bitmap_reverse_alpha_channel(&src_bmp);
			psd_bitmap_knock_out(&dst_bmp, &src_bmp);
			break;
		case psd_stroke_center:
			psd_draw_stroke(&dst_bmp, &src_bmp, stroke->size);
			break;
		default:
			psd_assert(0);
			break;
	}

	psd_inflate_bitmap(&src_bmp, &layer_bmp, stroke->size, stroke->size);
	memcpy(&layer_mask_info, &layer->layer_mask_info, sizeof(psd_layer_mask_info));
	if(layer_mask_info.disabled == psd_false && (layer_mask_info.default_color != 255 || layer_mask_info.mask_data != NULL))
	{
		layer_mask_info.left -= layer->left - stroke->size;
		layer_mask_info.top -= layer->top - stroke->size;
		layer_mask_info.right -= layer->left - stroke->size;
		layer_mask_info.bottom -= layer->top - stroke->size;
		psd_bitmap_blend_mask(&src_bmp, &layer_mask_info);
	}
	psd_bitmap_reverse_mixed_alpha_channel(&src_bmp);
	psd_bitmap_blend_alpha_channel(&dst_bmp, &src_bmp);

	switch(stroke->fill_type)
	{
		case psd_fill_solid_color:
			psd_fill_bitmap_without_alpha_channel(&dst_bmp, stroke->fill_color);
			break;
			
		case psd_fill_gradient:
			if(stroke->gradient_align == psd_false)
			{
				center_x = context->width / 2 + stroke->gradient_horz_offset * context->width / 100;
				center_y = context->height / 2 + stroke->gradient_vert_offset * context->height / 100;
				center_x -= layer->left;
				center_y -= layer->top;
				corner_angle = (psd_int)(atan((psd_float)context->height / context->width) * 180 / PSD_PI + 0.5);
				angle = stroke->gradient_angle;
				width = (context->width * stroke->gradient_scale + 100) / 200;
				height = (context->height * stroke->gradient_scale + 100) / 200;
			}
			else
			{
				center_x = width / 2 + stroke->gradient_horz_offset * layer->width / 100;
				center_y = height / 2 + stroke->gradient_vert_offset * layer->height / 100;
				switch(stroke->position)
				{
					case psd_stroke_outside:
						width = layer->width + stroke->size * 2;
						height = layer->height + stroke->size * 2;
						break;
					case psd_stroke_inside:
						width = layer->width;
						height = layer->height;
						break;
					case psd_stroke_center:
						width = layer->width + stroke->size;
						height = layer->height + stroke->size;
						break;
				}
				center_x += stroke->gradient_horz_offset * width / 100;
				center_y += stroke->gradient_vert_offset * height / 100;
				corner_angle = (psd_int)(atan((psd_float)height / width) * 180 / PSD_PI + 0.5);
				angle = stroke->gradient_angle;
				width = (width * stroke->gradient_scale + 100) / 200;
				height = (height * stroke->gradient_scale + 100) / 200;
			}
			if(angle < 0)
				angle += 360;
			if(angle >= 90 && angle < 180)
			{
				angle = 180 - angle;
				sign_x = -1;
			}
			else if(angle >= 180 && angle < 270)
			{
				angle = angle - 180;
				sign_x = -1;
				sign_y = -1;
			}
			else if(angle >= 270 && angle <= 360)
			{
				angle = 360 - angle;
				sign_y = -1;
			}
			if(angle <= corner_angle)
			{
				radius_x = width;
				radius_y = (psd_int)(radius_x * PSD_TAN(angle) + 0.5);
			}
			else
			{
				radius_y = height;
				radius_x = (psd_int)(radius_y / PSD_TAN(angle) + 0.5);
			}
			radius_corner = (psd_int)(psd_carm_sqrt((psd_float)(radius_x * radius_x + radius_y * radius_y)) + 0.5);

			switch(stroke->gradient_style)
			{
				case psd_gradient_style_linear:
					psd_gradient_fill_linear(&src_bmp, &stroke->gradient_color, stroke->gradient_reverse, 
						center_x - sign_x * radius_x, center_y + sign_y * radius_y, 
						center_x + sign_x * radius_x, center_y - sign_y * radius_y);
					break;
				case psd_gradient_style_radial:
					psd_gradient_fill_radial(&src_bmp, &stroke->gradient_color, stroke->gradient_reverse, 
						center_x, center_y, radius_corner);
					break;
				case psd_gradient_style_angle:
					psd_gradient_fill_angle(&src_bmp, &stroke->gradient_color, stroke->gradient_reverse, 
						center_x, center_y, stroke->gradient_angle);
					break;
				case psd_gradient_style_reflected:
					psd_gradient_fill_reflected(&src_bmp, &stroke->gradient_color, stroke->gradient_reverse, 
						center_x - sign_x * radius_x, center_y + sign_y * radius_y, 
						center_x + sign_x * radius_x, center_y - sign_y * radius_y);
					break;
				case psd_gradient_style_diamond:
					psd_gradient_fill_diamond(&src_bmp, &stroke->gradient_color, stroke->gradient_reverse, 
						center_x, center_y, radius_corner, stroke->gradient_angle);
					break;
				default:
					psd_assert(0);
					break;
			}

			psd_bitmap_copy_without_alpha_channel(&dst_bmp, &src_bmp);
			break;
			
		case psd_fill_pattern:
			for(i = 0; i < context->pattern_count; i ++)
			{
				if(strcmp(context->patterns[i].unique_id, stroke->pattern_info.identifier) == 0)
				{
					psd_pattern_fill(&src_bmp, &context->patterns[i], stroke->pattern_scale, 
						stroke->pattern_horz_phase + stroke->size, 
						stroke->pattern_vert_phase + stroke->size);
					break;
				}
			}
			
			psd_bitmap_copy_without_alpha_channel(&dst_bmp, &src_bmp);
			break;
			
		default:
			psd_assert(0);
			break;
	}

	psd_free_bitmap(&src_bmp);

	data->valid[psd_layer_effects_type_stroke] = psd_false;
	
	return psd_status_done;
}
예제 #10
0
파일: inner_glow.c 프로젝트: IreNox/tiki3
psd_status psd_layer_effects_blend_inner_glow(psd_context * context, psd_layer_record * layer, psd_layer_effects * data)
{
	psd_layer_effects_inner_glow * inner_glow = &data->inner_glow;
	psd_int width, height;
	psd_bitmap src_bmp, dst_bmp, knock_bmp;
	psd_layer_mask_info layer_mask_info;
	psd_int choke_size, blur_size;
	psd_argb_color gradient_table[256];
	
	data->left[psd_layer_effects_type_inner_glow] = -inner_glow->size;
	data->top[psd_layer_effects_type_inner_glow] = -inner_glow->size;
	width = layer->width + inner_glow->size * 2;
	height = layer->height + inner_glow->size * 2;
	data->right[psd_layer_effects_type_inner_glow] = data->left[psd_layer_effects_type_inner_glow] + width;
	data->bottom[psd_layer_effects_type_inner_glow] = data->top[psd_layer_effects_type_inner_glow] + height;
	data->blend_mode[psd_layer_effects_type_inner_glow] = inner_glow->blend_mode;
	data->opacity[psd_layer_effects_type_inner_glow] = inner_glow->opacity;

	if(data->image_data[psd_layer_effects_type_inner_glow] != NULL)
	{
		if(data->width[psd_layer_effects_type_inner_glow] != width ||
			data->height[psd_layer_effects_type_inner_glow] != height)
		{
			psd_free(data->image_data[psd_layer_effects_type_inner_glow]);
			data->image_data[psd_layer_effects_type_inner_glow] = (psd_argb_color *)psd_malloc(width * height * 4);
			if(data->image_data[psd_layer_effects_type_inner_glow] == NULL)
				return psd_status_malloc_failed;
		}
	}
	else
	{
		data->image_data[psd_layer_effects_type_inner_glow] = (psd_argb_color *)psd_malloc(width * height * 4);
		if(data->image_data[psd_layer_effects_type_inner_glow] == NULL)
			return psd_status_malloc_failed;
	}
	data->width[psd_layer_effects_type_inner_glow] = width;
	data->height[psd_layer_effects_type_inner_glow] = height;
	psd_color_memset(data->image_data[psd_layer_effects_type_inner_glow], inner_glow->color, width * height);

	src_bmp.width = layer->width;
	src_bmp.height = layer->height;
	src_bmp.image_data = layer->image_data;
	dst_bmp.width = width;
	dst_bmp.height = height;
	dst_bmp.image_data = data->image_data[psd_layer_effects_type_inner_glow];

	if(inner_glow->size == 0)
	{
		psd_fill_bitmap(&dst_bmp, inner_glow->color);
		psd_bitmap_copy_alpha_channel(&dst_bmp, &src_bmp);
	}
	else
	{
		psd_inflate_bitmap(&dst_bmp, &src_bmp, inner_glow->size, inner_glow->size);
		psd_fill_bitmap_without_alpha_channel(&dst_bmp, inner_glow->color);
	}

	memcpy(&layer_mask_info, &layer->layer_mask_info, sizeof(psd_layer_mask_info));
	if(layer_mask_info.disabled == psd_false && (layer_mask_info.default_color != 255 || layer_mask_info.mask_data != NULL))
	{
		layer_mask_info.left -= layer->left - inner_glow->size;
		layer_mask_info.top -= layer->top - inner_glow->size;
		layer_mask_info.right -= layer->left - inner_glow->size;
		layer_mask_info.bottom -= layer->top - inner_glow->size;
		psd_bitmap_blend_mask(&dst_bmp, &layer_mask_info);
	}

	psd_bitmap_reverse_alpha_channel(&dst_bmp);

	psd_create_bitmap(&knock_bmp, width, height);
	psd_copy_bitmap(&knock_bmp, &dst_bmp);

	if(inner_glow->technique == psd_technique_precise)
		psd_bitmap_find_edge(&dst_bmp, psd_false);
	
	choke_size = (inner_glow->choke * inner_glow->size + 50) / 100;
	blur_size = inner_glow->size - choke_size;
	if(choke_size != 0)
	{
		psd_bitmap_gaussian_blur_alpha_channel(&dst_bmp, choke_size);
		psd_bitmap_find_edge(&dst_bmp, psd_false);
	}
	if(blur_size != 0)
	{
		psd_bitmap_gaussian_blur_alpha_channel(&dst_bmp, blur_size);
	}

	psd_bitmap_ajust_range(&dst_bmp, inner_glow->range);

	if(inner_glow->source == psd_glow_center)
		psd_bitmap_reverse_alpha_channel(&dst_bmp);

	psd_bitmap_contour_alpha_channel(&dst_bmp, inner_glow->contour_lookup_table, 
		inner_glow->anti_aliased, psd_false);

	if(inner_glow->noise > 0)
	{
		psd_effects_add_noise(&dst_bmp, inner_glow->noise, 
			data->left[psd_layer_effects_type_inner_glow] + layer->left,
			data->top[psd_layer_effects_type_inner_glow] + layer->top, context);
	}

	if(inner_glow->fill_type == psd_fill_gradient)
	{
		psd_gradient_color_get_table(&inner_glow->gradient_color, gradient_table, 256, psd_false);
		psd_effects_apply_gradient(&dst_bmp, gradient_table, psd_false, inner_glow->jitter, 
			data->left[psd_layer_effects_type_inner_glow] + layer->left,
			data->top[psd_layer_effects_type_inner_glow] + layer->top, context);
	}

	psd_bitmap_knock_out(&dst_bmp, &knock_bmp);
	psd_free_bitmap(&knock_bmp);
	
	data->valid[psd_layer_effects_type_inner_glow] = psd_false;
	
	return psd_status_done;
}
예제 #11
0
psd_status psd_get_image_resource(psd_context * context)
{
	psd_int length, i, size;
	psd_ushort ID;
	psd_uint tag;
	psd_uchar sizeofname;
	psd_int sizeofdata, prev_stream_pos;
	psd_uchar * buffer;
	//psd_status status;

	// Length of image resource section
	length = psd_stream_get_int(context);
	if(length <= 0)
		return psd_status_done;

	// default
	context->global_angle = 30;
	context->global_altitude = 30;

	while(length > 0)
	{
		// Signature: '8BIM'
		tag = psd_stream_get_int(context);
		if(tag == '8BIM')
		{
			length -= 4;
			// Unique identifier for the resource
			ID = psd_stream_get_short(context);
			length -= 2;
			// Name: Pascal string, padded to make the size even (a null name consists of two bytes of 0)
			sizeofname = psd_stream_get_char(context);
			if((sizeofname & 0x01) == 0)
				sizeofname ++;
			psd_stream_get_null(context, sizeofname);
			length -= sizeofname + 1;
			// Actual size of resource data that follows
			sizeofdata = psd_stream_get_int(context);
			length -= 4;
			// resource data must be even
			if(sizeofdata & 0x01)
				sizeofdata ++;
			length -= sizeofdata;

			switch(context->load_tag)
			{
				case psd_load_tag_thumbnail:
					if(ID != 1033 && ID != 1036)
					{
						psd_stream_get_null(context, sizeofdata);
						continue;
					}
					break;
				case psd_load_tag_merged:
					// alpha channels information
					if(ID != 1006 && ID != 1045 && ID != 1053)
					{
						psd_stream_get_null(context, sizeofdata);
						continue;
					}
					break;
				case psd_load_tag_exif:
					if(ID != 1058 && ID != 1059)
					{
						psd_stream_get_null(context, sizeofdata);
						continue;
					}
					break;
			}

			prev_stream_pos = context->stream.current_pos;

			if(sizeofdata > 0)
			{
				switch(ID)
				{
					// ResolutionInfo structure
					case 1005:
						// Horizontal resolution in pixels per inch.
						context->resolution_info.hres = psd_stream_get_int(context) / 65536.0f;
						// 1=display horitzontal resolution in pixels per inch; 2=display horitzontal resolution in pixels per cm.
						context->resolution_info.hres_unit = psd_stream_get_short(context);
						// Display width as 1=inches; 2=cm; 3=points; 4=picas; 5=columns.
						context->resolution_info.width_unit = psd_stream_get_short(context);
						// Vertial resolution in pixels per inch.
						context->resolution_info.vres = psd_stream_get_int(context) / 65536.0f;
						// 1=display vertical resolution in pixels per inch; 2=display vertical resolution in pixels per cm.
						context->resolution_info.vres_unit = psd_stream_get_short(context);
						// Display height as 1=inches; 2=cm; 3=points; 4=picas; 5=columns.
						context->resolution_info.height_unit = psd_stream_get_short(context);
						context->fill_resolution_info = psd_true;
						break;

					// Names of the alpha channels as a series of Pascal strings.
					case 1006:
						buffer = (psd_uchar *)psd_malloc(sizeofdata);
						if(buffer == NULL)
							return psd_status_malloc_failed;
						psd_stream_get(context, buffer, sizeofdata);
						if(context->alpha_channels == 0)
						{
							size = 0;
							// maybe odd
							while(size + 1 < sizeofdata)
							{
								size += *(buffer + size) + 1;
								context->alpha_channels ++;
							}
							context->color_channels = context->channels - context->alpha_channels;
							context->alpha_channel_info = (psd_alpha_channel_info *)psd_malloc(context->alpha_channels * sizeof(psd_alpha_channel_info));
							if(context->alpha_channel_info == NULL)
							{
								psd_free(buffer);
								return psd_status_malloc_failed;
							}
							memset(context->alpha_channel_info, 0, context->alpha_channels * sizeof(psd_alpha_channel_info));
						}

						size = 0;
						for(i = 0; i < context->alpha_channels; i ++)
						{
							memcpy(context->alpha_channel_info[i].name, buffer + size + 1, *(buffer + size));
							size += *(buffer + size) + 1;
						}
						psd_free(buffer);
						context->fill_alpha_channel_info = psd_true;
						break;

					// DisplayInfo structure
					case 1007:
						context->display_info.color = psd_stream_get_space_color(context);
						// 0..100
						context->display_info.opacity = psd_stream_get_short(context);
						psd_assert(context->display_info.opacity >= 0 && context->display_info.opacity <= 100);
						// selected = 0, protected = 1
						context->display_info.kind = psd_stream_get_char(context);
						// maybe be 2 when color mode is multichannel
						//psd_assert(context->display_info.kind == 0 || context->display_info.kind == 1);
						// padding
						psd_stream_get_char(context);
						context->fill_display_info = psd_true;
						break;

					// The caption as a Pascal string.
					case 1008:
						size = psd_stream_get_char(context);
						psd_stream_get(context, context->caption, size);
						break;

					// Layer state information
					// 2 bytes containing the index of target layer (0 = bottom layer).
					case 1024:
						context->target_layer_index = psd_stream_get_short(context);
						break;

					// Layers group information
					// 2 bytes per layer containing a group ID for the dragging groups. Layers in
					// a group have the same group ID.
					case 1026:
						context->layer_group_count = sizeofdata / 2;
						context->layer_group_id = (psd_ushort *)psd_malloc(context->layer_group_count * 2);
						if(context->layer_group_id == NULL)
							return psd_status_malloc_failed;
						for(i = 0; i < context->layer_group_count; i ++)
							context->layer_group_id[i] = psd_stream_get_short(context);
						context->fill_layer_group = psd_true;
						break;

					// (Photoshop 4.0) Thumbnail resource for Photoshop 4.0 only
					case 1033:
					// (Photoshop 5.0) Thumbnail resource (supersedes resource 1033)
					case 1036:
						if(context->load_tag == psd_load_tag_layer)
						{
							psd_stream_get_null(context, sizeofdata);
							continue;
						}

						// 1 = kJpegRGB . Also supports kRawRGB (0).
						context->thumbnail_resource.format = psd_stream_get_int(context);
						psd_assert(context->thumbnail_resource.format == 0 || context->thumbnail_resource.format == 1);
						// Width of thumbnail in pixels.
						context->thumbnail_resource.width = psd_stream_get_int(context);
						// Height of thumbnail in pixels.
						context->thumbnail_resource.height = psd_stream_get_int(context);
						// Padded row bytes = (width * bits per pixel + 31) / 32 * 4.
						context->thumbnail_resource.width_bytes = psd_stream_get_int(context);
						// Total size = widthbytes * height * planes
						context->thumbnail_resource.total_size = psd_stream_get_int(context);
						// Used for consistency check.
						context->thumbnail_resource.size_after_compression = psd_stream_get_int(context);
						context->thumbnail_resource.bits_per_pixel = psd_stream_get_short(context);
						// Bits per pixel. = 24
						psd_assert(context->thumbnail_resource.bits_per_pixel == 24);
						context->thumbnail_resource.number_of_planes = psd_stream_get_short(context);
						// Number of planes. = 1
						psd_assert(context->thumbnail_resource.number_of_planes == 1);
#ifdef PSD_INCLUDE_LIBJPEG
						if(context->thumbnail_resource.format == 0)
						{
							status = psd_thumbnail_decode_raw(&context->thumbnail_resource.thumbnail_data, 
								context->thumbnail_resource.size_after_compression, context);
						}
						else
						{
							status = psd_thumbnail_decode_jpeg(&context->thumbnail_resource.thumbnail_data, 
								context->thumbnail_resource.size_after_compression, context);
						}
						if(status != psd_status_done)
							return status;
#else
						context->thumbnail_resource.jfif_data = (psd_uchar *)psd_malloc(sizeofdata - 28);
						if(context->thumbnail_resource.jfif_data == NULL)
							return psd_status_malloc_failed;
						psd_stream_get(context, context->thumbnail_resource.jfif_data, sizeofdata - 28);
#endif
						context->fill_thumbnail_resource = psd_true;
						break;

					// (Photoshop 4.0) Copyright flag
					// Boolean indicating whether image is copyrighted. Can be set via
					// Property suite or by user in File Info...
					case 1034:
						context->copyright_flag = (psd_bool)psd_stream_get_short(context);
						psd_assert(context->copyright_flag == 0 || context->copyright_flag == 1);
						break;

					// (Photoshop 5.0) Global Angle
					// 4 bytes that contain an integer between 0 and 359, which is the global
					// lighting angle for effects layer. If not present, assumed to be 30.
					case 1037:
						context->global_angle = psd_stream_get_int(context);
						break;

					// (Photoshop 5.0) Effects visible
					// 1-byte global flag to show/hide all the effects layer. Only present when
					// they are hidden.
					case 1042:
						context->effects_visible = (psd_bool)psd_stream_get_short(context);
						psd_assert(context->effects_visible == 0 || context->effects_visible == 1);
						break;

					// (Photoshop 5.0) Unicode Alpha Names
					// Unicode string (4 bytes length followed by string).
					case 1045:
						buffer = (psd_uchar *)psd_malloc(sizeofdata);
						if(buffer == NULL)
							return psd_status_malloc_failed;
						psd_stream_get(context, buffer, sizeofdata);
						if(context->alpha_channels == 0)
						{
							size = 0;
							while(size < sizeofdata)
							{
								size += PSD_CHAR_TO_INT(buffer + size) * 2 + 4;
								context->alpha_channels ++;
							}
							context->color_channels = context->channels - context->alpha_channels;
							context->alpha_channel_info = (psd_alpha_channel_info *)psd_malloc(context->alpha_channels * sizeof(psd_alpha_channel_info));
							if(context->alpha_channel_info == NULL)
							{
								psd_free(buffer);
								return psd_status_malloc_failed;
							}
							memset(context->alpha_channel_info, 0, context->alpha_channels * sizeof(psd_alpha_channel_info));
						}

						size = 0;
						for(i = 0; i < context->alpha_channels; i ++)
						{
							context->alpha_channel_info[i].unicode_name_length = PSD_CHAR_TO_INT(buffer + size);
							context->alpha_channel_info[i].unicode_name = (psd_ushort *)psd_malloc(2 * context->alpha_channel_info[i].unicode_name_length);
							if(context->alpha_channel_info[i].unicode_name == NULL)
							{
								psd_free(buffer);
								return psd_status_malloc_failed;
							}
							memcpy(context->alpha_channel_info[i].unicode_name, buffer + size + 4, 2 * context->alpha_channel_info[i].unicode_name_length);
							size += 2 * context->alpha_channel_info[i].unicode_name_length + 4;
						}
						psd_free(buffer);
						context->fill_alpha_channel_info = psd_true;
						break;

					// (Photoshop 6.0) Indexed Color Table Count
					// 2 bytes for the number of colors in table that are actually defined
					case 1046:
						context->indexed_color_table_count = psd_stream_get_short(context);
						break;

					// (Photoshop 6.0) Transparency Index.
					// 2 bytes for the index of transparent color, if any.
					case 1047:
						context->transparency_index = psd_stream_get_short(context);
						break;

					// (Photoshop 6.0) Global Altitude
					// 4 byte entry for altitude
					case 1049:
						context->global_altitude = psd_stream_get_int(context);
						break;

					// (Photoshop 6.0) Alpha Identifiers
					// 4 bytes of length, followed by 4 bytes each for every alpha identifier.
					case 1053:
						if(context->alpha_channels == 0)
						{
							context->alpha_channels = sizeofdata / 4;
							context->color_channels = context->channels - context->alpha_channels;
							context->alpha_channel_info = (psd_alpha_channel_info *)psd_malloc(context->alpha_channels * sizeof(psd_alpha_channel_info));
							if(context->alpha_channel_info == NULL)
								return psd_status_malloc_failed;
							memset(context->alpha_channel_info, 0, context->alpha_channels * sizeof(psd_alpha_channel_info));
						}

						for(i = 0; i < context->alpha_channels; i ++)
						{
							context->alpha_channel_info[i].identifier = psd_stream_get_int(context);
						}
						context->fill_alpha_channel_info = psd_true;
						break;

					// (Photoshop 6.0) Version Info
					// 4 bytes version, 1 byte hasRealMergedData, Unicode string: writer
					// name, Unicode string: reader name, 4 bytes file version.
					case 1057:
						context->version_info.version = psd_stream_get_int(context);
						context->version_info.has_real_merged_data = psd_stream_get_bool(context);
						context->version_info.writer_name_length = psd_stream_get_int(context);
						context->version_info.writer_name = (psd_ushort *)psd_malloc(2 * context->version_info.writer_name_length);
						if(context->version_info.writer_name == NULL)
							return psd_status_malloc_failed;
						psd_stream_get(context, (psd_uchar *)context->version_info.writer_name, 2 * context->version_info.writer_name_length);
						context->version_info.reader_name_length = psd_stream_get_int(context);
						context->version_info.reader_name = (psd_ushort *)psd_malloc(2 * context->version_info.reader_name_length);
						if(context->version_info.reader_name == NULL)
							return psd_status_malloc_failed;
						psd_stream_get(context, (psd_uchar *)context->version_info.reader_name, 2 * context->version_info.reader_name_length);
						context->version_info.file_version = psd_stream_get_int(context);
						context->fill_version_info = psd_true;
						break;

// if you don't need the following image resource,
// you can undef this macro in psd_config.h to reduce the parsing time
/////////////////////////////////////////////////////////////////////////////////////////////
#ifdef PSD_GET_ALL_IMAGE_RESOURCE

					// Border information
					case 1009:
						// a fixed number (2 bytes real, 2 bytes fraction) for the border width
						context->border_info.border_width = psd_fixed_16_16_tofloat((psd_fixed_16_16)psd_stream_get_int(context));
						// 2 bytes for border units (1 = inches, 2 = cm, 3 = points, 4 = picas, 5 = columns).
						context->border_info.border_units = (psd_units)psd_stream_get_short(context);
						psd_assert(context->border_info.border_units >= psd_units_inches && 
							context->border_info.border_units <= psd_units_columns);
						context->fill_border_info = psd_true;
						break;

					// Print flags
					// A series of one-byte boolean values (see Page Setup dialog): labels, crop
					// marks, color bars, registration marks, negative, flip, interpolate, caption,
					// print flags.
					case 1011:
						context->print_flags.labels = psd_stream_get_bool(context);
						context->print_flags.crop_marks = psd_stream_get_bool(context);
						context->print_flags.color_bars = psd_stream_get_bool(context);
						context->print_flags.registration_marks = psd_stream_get_bool(context);
						context->print_flags.negative = psd_stream_get_bool(context);
						context->print_flags.flip = psd_stream_get_bool(context);
						context->print_flags.interpolate = psd_stream_get_bool(context);
						context->print_flags.caption = psd_stream_get_bool(context);
						context->print_flags.print_flags = psd_stream_get_bool(context);
						context->fill_print_flags = psd_true;
						break;

					// (Photoshop 4.0) Grid and guides information
					case 1032:
						// Version ( = 1)
						psd_assert(psd_stream_get_int(context) == 1);
						// Future implementation of document-specific grids (4 bytes horizontal, 4 bytes vertical).
						context->grid_guides.horz_grid = psd_stream_get_int(context);
						context->grid_guides.vert_grid = psd_stream_get_int(context);
						// Number of guide resource blocks (can be 0).
						context->grid_guides.guide_count = psd_stream_get_int(context);
						if(context->grid_guides.guide_count > 0)
						{
							//Location of guide in document coordinates. Since the guide is either vertical or horizontal, this only has to be one component of the coordinate.
							context->grid_guides.guide_coordinate = (psd_int *)psd_malloc(context->grid_guides.guide_count * 4);
							// Direction of guide. VHSelect is a system type of psd_uchar where 0 = vertical, 1 = horizontal.
							context->grid_guides.guide_direction = (psd_uchar *)psd_malloc(context->grid_guides.guide_count);
							if(context->grid_guides.guide_coordinate == NULL ||
								context->grid_guides.guide_direction == NULL)
							{
								psd_free(context->grid_guides.guide_coordinate);
								context->grid_guides.guide_coordinate = NULL;
								psd_free(context->grid_guides.guide_direction);
								context->grid_guides.guide_direction = NULL;
								return psd_status_malloc_failed;
							}
							for(i = 0; i < context->grid_guides.guide_count; i ++)
							{
								context->grid_guides.guide_coordinate[i] = psd_stream_get_int(context);
								context->grid_guides.guide_direction[i] = psd_stream_get_char(context);
							}
						}
						context->fill_grid_and_guides_info = psd_true;
						break;

					// (Photoshop 5.0) Color samplers resource
					case 1038:
						// Version ( = 1)
						psd_assert(psd_stream_get_int(context) == 1);
						// Number of color samplers to follow.
						context->color_samplers.number_of_color_samplers = psd_stream_get_int(context);
						if (context->color_samplers.number_of_color_samplers > 0)
						{
							context->color_samplers.resource = (psd_color_samplers_resource *)
								psd_malloc(sizeof(psd_color_samplers_resource) * context->color_samplers.number_of_color_samplers);
							if (context->color_samplers.resource == NULL)
								return psd_status_malloc_failed;
							for (i = 0; i < context->color_samplers.number_of_color_samplers; i ++)
							{
								// The vertical and horizontal position of the point (4 bytes each).
								context->color_samplers.resource[i].vertical_position = psd_stream_get_int(context);
								context->color_samplers.resource[i].horizontal_position = psd_stream_get_int(context);
								// Color Space
								context->color_samplers.resource[i].color_space = psd_stream_get_short(context);
							}
						}
						context->fill_color_samplers = psd_true;
						break;
						
					// (Photoshop 6.0) Slices
					case 1050:
						// Version ( = 6)
						psd_assert(psd_stream_get_int(context) == 6);
						// Bounding rectangle for all of the slices: top, left, bottom, right of all the slices
						context->slices_resource.bounding_top = psd_stream_get_int(context);
						context->slices_resource.bounding_left = psd_stream_get_int(context);
						context->slices_resource.bounding_bottom = psd_stream_get_int(context);
						context->slices_resource.bounding_right = psd_stream_get_int(context);
						// Name of group of slices: Unicode string
						size = psd_stream_get_int(context) * 2;
						psd_stream_get_null(context, size);
						// Number of slices to follow
						context->slices_resource.number_of_slices = psd_stream_get_int(context);
						context->slices_resource.slices_resource_block = (psd_slices_resource_block *)psd_malloc(context->slices_resource.number_of_slices * sizeof(psd_slices_resource_block));
						if(context->slices_resource.slices_resource_block == NULL)
							return psd_status_malloc_failed;
						memset(context->slices_resource.slices_resource_block, 0, context->slices_resource.number_of_slices * sizeof(psd_slices_resource_block));
						for(i = 0; i < context->slices_resource.number_of_slices; i ++)
						{
							context->slices_resource.slices_resource_block[i].id = psd_stream_get_int(context);
							context->slices_resource.slices_resource_block[i].group_id = psd_stream_get_int(context);
							context->slices_resource.slices_resource_block[i].origin = psd_stream_get_int(context);
							// NOTE: Only present if Origin = 1
							if(context->slices_resource.slices_resource_block[i].origin == 1)
								context->slices_resource.slices_resource_block[i].associated_layer_id = psd_stream_get_int(context);
							// Name: Unicode string
							size = psd_stream_get_int(context) * 2;
							psd_stream_get_null(context, size);
							context->slices_resource.slices_resource_block[i].type = psd_stream_get_int(context);
							context->slices_resource.slices_resource_block[i].left = psd_stream_get_int(context);
							context->slices_resource.slices_resource_block[i].top = psd_stream_get_int(context);
							context->slices_resource.slices_resource_block[i].right = psd_stream_get_int(context);
							context->slices_resource.slices_resource_block[i].bottom = psd_stream_get_int(context);
							// URL: Unicode string
							size = psd_stream_get_int(context) * 2;
							psd_stream_get_null(context, size);
							// Target: Unicode string
							size = psd_stream_get_int(context) * 2;
							psd_stream_get_null(context, size);
							// Message: Unicode string
							size = psd_stream_get_int(context) * 2;
							psd_stream_get_null(context, size);
							// Alt Tag: Unicode string
							size = psd_stream_get_int(context) * 2;
							psd_stream_get_null(context, size);
							context->slices_resource.slices_resource_block[i].cell_text_is_html = psd_stream_get_char(context);
							// Cell text: Unicode string
							size = psd_stream_get_int(context) * 2;
							psd_stream_get_null(context, size);
							context->slices_resource.slices_resource_block[i].horizontal_alignment = psd_stream_get_int(context);
							context->slices_resource.slices_resource_block[i].veritcal_alignment = psd_stream_get_int(context);
							context->slices_resource.slices_resource_block[i].color = psd_argb_to_color(psd_stream_get_char(context), 
								psd_stream_get_char(context), psd_stream_get_char(context), psd_stream_get_char(context));
						}
						context->fill_slices_resource = psd_true;
						break;

					// (Photoshop 6.0) URL List
					case 1054:
						// 4 byte count of URLs
						context->url_list.number_of_urls = psd_stream_get_int(context);
						if (context->url_list.number_of_urls > 0)
						{
							context->url_list.items = (psd_url_list_item *)psd_malloc(sizeof(psd_url_list_item) *
								context->url_list.number_of_urls);
							if (context->url_list.items == NULL)
								return psd_status_malloc_failed;
							memset(context->url_list.items, 0, sizeof(psd_url_list_item) * context->url_list.number_of_urls);
						}
						for (i = 0; i < context->url_list.number_of_urls; i ++)
						{
							// followed by 4 byte long
							context->url_list.items[i].tag = psd_stream_get_int(context);
							// 4 byte ID
							context->url_list.items[i].ID = psd_stream_get_int(context);
							// Unicode string for each count.
							context->url_list.items[i].name_length = psd_stream_get_int(context);
							context->url_list.items[i].name = (psd_ushort *)psd_malloc(2 * context->url_list.items[i].name_length);
							if (context->url_list.items[i].name == NULL)
								return psd_status_malloc_failed;
							psd_stream_get(context, (psd_uchar *)context->url_list.items[i].name, 
								2 * context->url_list.items[i].name_length);
						}
						context->fill_url_list = psd_true;
						break;

					// (Photoshop 7.0) EXIF data 1
					case 1058:
					// (Photoshop 7.0) EXIF data 3
					// http://www.pima.net/standards/it10/PIMA15740/exif.htm
					case 1059:
						// avoid to get the exif data for twice
						psd_assert(context->fill_exif_data == psd_false);
#	ifdef PSD_INCLUDDE_LIBEXIF
						buffer = (psd_uchar *)psd_malloc(sizeofdata + sizeof(ExifHeader));
						if (buffer == NULL)
							return psd_status_malloc_failed;
						psd_stream_get(context, buffer + sizeof(ExifHeader), sizeofdata);
						memcpy(buffer, ExifHeader, sizeof(ExifHeader));
						context->exif_data = (psd_uchar *)exif_data_new_from_data(buffer, sizeofdata + sizeof(ExifHeader));
						psd_free(buffer);
						context->fill_exif_data = psd_true;
#	else // ifdef PSD_INCLUDDE_LIBEXIF
						context->exif_data = (psd_uchar *)psd_malloc(sizeofdata);
						if (context->exif_data == NULL)
							return psd_status_malloc_failed;
						psd_stream_get(context, context->exif_data, sizeofdata);
						context->exif_data_length = sizeofdata;
						context->fill_exif_data = psd_true;
#	endif // ifdef PSD_INCLUDDE_LIBEXIF
						break;
						
					// (Photoshop 7.0) XMP metadata
					// File info as XML description
					// http://Partners.adobe.com/asn/developer/xmp/main.html
					case 1060:
#	ifdef PSD_INCLUDE_LIBXML
						buffer = (psd_uchar *)psd_malloc(sizeofdata);
						if (buffer == NULL)
							return psd_status_malloc_failed;
						psd_stream_get(context, buffer, sizeofdata);
						context->XMP_metadata = (psd_uchar *)xmlParseMemory(buffer, sizeofdata);
						psd_free(buffer);
						context->fill_XMP_metadata = psd_true;
#	else // ifdef PSD_INCLUDE_LIBXML
						context->XMP_metadata = (psd_uchar *)psd_malloc(sizeofdata);
						if (context->XMP_metadata == NULL)
							return psd_status_malloc_failed;
						psd_stream_get(context, context->XMP_metadata, sizeofdata);
						context->XMP_metadata_length = sizeofdata;
						context->fill_XMP_metadata = psd_true;
#	endif // ifdef PSD_INCLUDE_LIBXML
						break;

					// (Photoshop 7.0) Print scale
					case 1062:
						// 2 bytes style (0 = centered, 1 = size to fit, 2 = user defined).
						context->print_scale.style = psd_stream_get_short(context);
						psd_assert(context->print_scale.style >= psd_print_centered &&
							context->print_scale.style <= psd_print_user_defined);
						// 4 bytes x location (floating point).
						context->print_scale.x_location = psd_stream_get_float(context);
						// 4 bytes y location (floating point).
						context->print_scale.y_location = psd_stream_get_float(context);
						// 4 bytes scale (floating point)
						context->print_scale.scale = psd_stream_get_float(context);
						context->fill_print_scale = psd_true;
						break;

					// (Photoshop CS) Pixel Aspect Ratio
					case 1064:
						// 4 bytes (version = 1)
						psd_assert(psd_stream_get_int(context) == 1);
						// 8 bytes double, x / y of a pixel
						context->pixel_aspect_ratio = psd_stream_get_double(context);
						break;

					// Print flags information
					case 10000:
						// 2 bytes version ( = 1)
						psd_assert(psd_stream_get_short(context) == 1);
						// 1 byte center crop marks
						context->print_flags_info.center_crop = psd_stream_get_bool(context);
						// 1 byte ( = 0)
						psd_assert(psd_stream_get_char(context) == 0);
						// 4 bytes bleed width value
						context->print_flags_info.value = psd_stream_get_int(context);
						// 2 bytes bleed width scale
						context->print_flags_info.scale = psd_stream_get_short(context);
						context->fill_print_flags_info = psd_true;
						break;
						
#endif // ifdef PSD_GET_ALL_IMAGE_RESOURCE
/////////////////////////////////////////////////////////////////////////////////////////////

					default:
#ifdef PSD_GET_PATH_RESOURCE
						// Photoshop stores its paths as resources of type 8BIM, with IDs in the range 2000
						// through 2998.
						if(ID >= 2000 && ID <= 2998)
						{
							psd_get_path(context, sizeofdata);
						}
						// If the file contains a resource of type 8BIM with an ID of 2999, then this resource
						// contains a Pascal¨Cstyle string containing the name of the clipping path to use with this
						// image when saving it as an EPS file???
						else if(ID == 2999)
						{
							// we don't find any files includes the name of the clipping path.
							psd_assert(0);
						}
						else
#endif // ifdef PSD_GET_PATH_RESOURCE
						{
							psd_stream_get_null(context, sizeofdata);
						}
						break;
				}
				
				// Filler
				psd_stream_get_null(context, prev_stream_pos + sizeofdata - context->stream.current_pos);
			}
		}
		else
		{
			return psd_status_resource_signature_error;
		}
	}

	return psd_status_done;
}