How to add keywords to XPKeyword Tag to jpg image file?

How to add keywords to XPKeyword Tag to jpg image file with Aspose.imaging java ? Any suggestions are appreciated. Thanks, Harry

@harry2cazz,

Since your query is related to Aspose.Imaging, so I am moving your thread to respective category where one of our colleagues from Aspose.Imaging team will assist you soon.

Hello @harry2cazz !
Yes, it is possible. What platform do you use - Java/C#/Python?

Hi @harry2cazz
Although there is no specific property in JpegExifData for XPKeyword, you might add or modify it. Please take a look at this example.


public void testAdd_XPKeywords()
{
	try (Image image = Image.load("somepicture"))
	{
		ExifData exifData = addXPKeyword(image, "Test,TiffTag;XPKeywords;JPEG", true);
		image.save("output-with_xpkeyword.jpg", new JpegOptions() {{
			setExifData(exifData);
		}});
	}

	try (JpegImage image = (JpegImage)Image.load("output-with_xpkeyword.jpg"))
	{
		XPKeywordRW reader = new XPKeywordRW(image.getExifData());

		System.out.println("Old value: " + reader.getXPKeyword());

		reader.setXpKeywordTag("newID", false); // add one more keyword
		image.setExifData(reader.addToExifData());
		image.save("output-with_added_xpkeyword.jpg");
	}
}

private ExifData addXPKeyword(Image image, String xpKeywords, boolean replaceOld) throws UnsupportedEncodingException
{
	if (!replaceOld && image instanceof JpegImage)
	{
		XPKeywordRW writer = new XPKeywordRW(((JpegImage) image).getExifData());
		writer.setXpKeywordTag(xpKeywords, false);
		return writer.addToExifData();
	}

	XPKeywordRW writer = new XPKeywordRW();
	writer.setXpKeywordTag(xpKeywords, true);
	return writer.addToExifData();
}


static class XPKeywordRW
{
	TiffDataType xpKeywordTag;
	final Charset charset;
	ExifData data;

	public XPKeywordRW()
	{
		xpKeywordTag = null;
		this.data = null;
		charset = StandardCharsets.UTF_16LE;
	}

	public XPKeywordRW(ExifData data)
	{
		xpKeywordTag = null;
		if (data != null)
		{
			for (TiffDataType property : data.getProperties())
			{
				if (property.getId() == TiffTags.XPKeywords)
				{
					xpKeywordTag = property;
					break;
				}
			}
		}
		charset = StandardCharsets.UTF_16LE;
	}

	public XPKeywordRW(TiffDataType[] properties)
	{
		xpKeywordTag = null;
		this.data = null;
		if (properties != null)
		{
			for (TiffDataType property : properties)
			{
				if (property.getId() == TiffTags.XPKeywords)
				{
					xpKeywordTag = property;
					break;
				}
			}
		}
		charset = StandardCharsets.UTF_16LE;
	}

	public String getXPKeyword()
	{
		if (xpKeywordTag == null)
		{
			return "";
		}
		String val = new String((byte[]) xpKeywordTag.getValue(), charset);
		// remove the ending zero char
		int length = val.length();
		while (length > 0 && val.charAt(length - 1) == 0)
		{
			length--;
			val = val.substring(0, length);
		}

		return val;
	}

	public void setXpKeywordTag(String value, boolean replace)
	{
		String newValue = value;
		if (!replace && xpKeywordTag != null)
		{
			String oldValue = getXPKeyword();
			if (!oldValue.isEmpty())
			{
				newValue = oldValue + ";" + value + "\u0000";
			}
		}

		if (xpKeywordTag == null)
		{
			xpKeywordTag = new TiffByteType(TiffTags.XPKeywords);
		}

		xpKeywordTag.setValue(newValue.getBytes(charset));
	}

	public ExifData addToExifData(ExifData data)
	{
		if (xpKeywordTag == null)
		{
			return data;
		}
		List<TiffDataType> properties = new ArrayList<>();
		if (data != null)
		{
			Collections.addAll(properties, data.getProperties());
			properties.removeIf(it -> it.getId() == TiffTags.XPKeywords);
		}
		properties.add(xpKeywordTag);
		return new JpegExifData(properties.toArray(new TiffDataType[0]));
	}

	public ExifData addToExifData()
	{
		if (xpKeywordTag == null)
		{
			return this.data;
		}
		List<TiffDataType> properties = new ArrayList<>();
		if (this.data != null)
		{
			Collections.addAll(properties, this.data.getProperties());
			properties.removeIf(it -> it.getId() == TiffTags.XPKeywords);
		}
		properties.add(xpKeywordTag);
		return new JpegExifData(properties.toArray(new TiffDataType[0]));
	}
}