Discussion:
GDIP+ - Loading a BMP image and saving as JPG : Adding metadata fails
(too old to reply)
R.Wieser
2018-12-23 08:43:05 UTC
Permalink
Hello all,

I'm loading a BMP image (using GdipLoadImageFromFile), and trying to add
some metadata (using GdipSetPropertyItem), before saving tit as a JPG. The
problem is that adding a property consistently fails.

After a bit of testing I found out that loading a JPG instead causes the
property adding to succceed (turns up in the GdipGetAllPropertyItems
result).

It is as if the adding of the property is first checked against the
*current* image type (bitmaps do not seem to support metadata), and doesn't
at all consider the possibility that the result wil be saved as a fully
other one. :-(

Does this really mean I first need to first save the BMP as a JPG and than
reload the JPG before I can add properties to it ? That sounds a bit
brain-dead to me.

Is there maybe some setting I need to apply ?

Regards,
Rudy Wieser
David Lowndes
2018-12-24 01:16:47 UTC
Permalink
Post by R.Wieser
I'm loading a BMP image (using GdipLoadImageFromFile), and trying to add
some metadata (using GdipSetPropertyItem), before saving tit as a JPG. The
problem is that adding a property consistently fails.
I assume the call to GdipSetPropertyItem returns a failure code?
Post by R.Wieser
After a bit of testing I found out that loading a JPG instead causes the
property adding to succceed (turns up in the GdipGetAllPropertyItems
result).
I take it the JPG doesn't originally have the property you're setting - the same as the BMP doesn't?
Post by R.Wieser
It is as if the adding of the property is first checked against the
*current* image type (bitmaps do not seem to support metadata), and doesn't
at all consider the possibility that the result wil be saved as a fully
other one. :-(
I'd guess that if it behaved as you hope, it would mean that the save operation would need to fail if the final format didn't
support the metadata - which may be inflexible behaviour if for example the metadata wasn't crucial. I'm only guessing though!

Merry Christmas
Dave
R.Wieser
2018-12-24 07:05:54 UTC
Permalink
David,
Post by David Lowndes
I assume the call to GdipSetPropertyItem returns a failure code?
Shucks. I should have mentioned it. Its code 0x14, "PropertyNotSupported"
Post by David Lowndes
I take it the JPG doesn't originally have the property you're setting -
the same as the BMP doesn't?
I do not quite understand. In my program there is no JPG image/data to
apply a property to. It only appears (on the drive) when I call
'GdipSaveImageToFile' (using the JPG encoder).

But if you are thinking of a problem with the replacing of
properties/metadata, the documention to the GdipSetPropertyItem function
says it will replace if it already exists.
Post by David Lowndes
I'd guess that if it behaved as you hope, it would mean that the save
operation
would need to fail if the final format didn't support the metadata - which
may
be inflexible behaviour if for example the metadata wasn't crucial. I'm
only
guessing though!
It doesn't need to fail, it could return a warning message. Or, as I
realize now, absolutily nothing: When I tried it the other way around
(JPG -> BMP) the metadata from the JPG was silently dropped (something I
didn't quite expect, but could see some wisdom in).

And now I think of it, that is what GdipSetPropertyItem could have done.
Not fail, but just showing that that property is incompatible with the
current image format (but store for usage anyway).


Related question:
To forgo a "write BMP to disk as JPG" - "reload JPG from disk" - "apply
metadata" - "write to disk again" dance, are you maybe aware of an in-memory
way of converting an image ?

Regards,
Rudy Wieser
David Lowndes
2018-12-24 10:18:45 UTC
Permalink
Post by R.Wieser
Post by David Lowndes
I assume the call to GdipSetPropertyItem returns a failure code?
Shucks. I should have mentioned it. Its code 0x14, "PropertyNotSupported"
OK, that sounds reasonable.
Post by R.Wieser
Post by David Lowndes
I take it the JPG doesn't originally have the property you're setting -
the same as the BMP doesn't?
I do not quite understand. In my program there is no JPG image/data to
apply a property to. It only appears (on the drive) when I call
'GdipSaveImageToFile' (using the JPG encoder).
You originally mentioned:

"After a bit of testing I found out that loading a JPG instead causes the
property adding to succeed (turns up in the GdipGetAllPropertyItems
result)."

So, my query applied to that statement.
Post by R.Wieser
But if you are thinking of a problem with the replacing of
properties/metadata, the documention to the GdipSetPropertyItem function
says it will replace if it already exists.
OK, so your code doesn't need to do anything different regardless of whether the property already exists or not?

However, the underlying implementation may do something different, so I suspect it's still worthwhile knowing if there's any
difference if an original JPG has the property or not.
Post by R.Wieser
And now I think of it, that is what GdipSetPropertyItem could have done.
Not fail, but just showing that that property is incompatible with the
current image format (but store for usage anyway).
Isn't that essentially what it has done by returning code 0x14, "PropertyNotSupported" ?
Post by R.Wieser
To forgo a "write BMP to disk as JPG" - "reload JPG from disk" - "apply
metadata" - "write to disk again" dance, are you maybe aware of an in-memory
way of converting an image ?
I'm not aware of anything using GDI+. There may be ways of doing it using lower level features, or 3'rd party libraries, but it's
not an area I'm familiar with.

Merry Christmas
Dave
R.Wieser
2018-12-24 11:18:04 UTC
Permalink
David,
Post by David Lowndes
OK, so your code doesn't need to do anything different regardless
of whether the property already exists or not?
If I may believe the documentation I don't need to. But in case of the BMP
image I knew no metadata was present (I checked), and regardless of that
created a known-not-to-exist, and repeatable entry ("-dummy-",
PropertyTagExifUserComment, PropertyTagTypeASCII).
Post by David Lowndes
I suspect it's still worthwhile knowing if there's any
difference if an original JPG has the property or not.
I just checked: In both cases (non-existing vs existing) the item was added
(in the latter case creating/showing a duplicate entry I mean).
Post by David Lowndes
Isn't that essentially what it has done by returning code
0x14, "PropertyNotSupported" ?
Not quite. Currently it refuses to store the property. My suggestion is
that its hould store the property regardless, but just discard it when the
image is saved (converted) to an image type that does not support them.
Like it already does when saving a JPG containing metadata to a BMP.
Post by David Lowndes
I'm not aware of anything using GDI+.
I've been googeling for a while, but alas, could not find anything either.
Post by David Lowndes
There may be ways of doing it using lower level features
Well, there is a small other problem involved: It appears that the encoding
of the involved images is such that, for example, FreeImage cannot handle
them. Even windows own "picture and fax viewer" barfs on them. IE is the
only program I can view them in, and GDI+ currently seems to be the only DLL
which allows loading of them.

Sadly enough my attempt to draw those onto a newly created "canvas" using
'GdipDrawImageRectI' (and save that) returns an error (works for "normal"
images though).
Post by David Lowndes
Merry Christmas
A merry chrismas and a happy newyear to you too. :-)

Regards,
Rudy Wieser
JJ
2018-12-24 10:35:17 UTC
Permalink
Post by R.Wieser
To forgo a "write BMP to disk as JPG" - "reload JPG from disk" - "apply
metadata" - "write to disk again" dance, are you maybe aware of an in-memory
way of converting an image ?
GdipSaveImageToStream() then GdipLoadImageToStream().
R.Wieser
2018-12-24 11:48:07 UTC
Permalink
JJ,
Post by JJ
GdipSaveImageToStream() then GdipLoadImageToStream().
Shucks. I had thought of that too, but thought I saw in some example code
that I needed to specify a "filename"(?) nonetheless. Looking at
description of the functions just now I do not see any such thing. Time to
re-examine them I guess.
Post by JJ
Well... GDI+ Image class is a generic wrapper for various image
formats. But apparently, it's not generic enough.
Worse, it at such a basic, obvious place (1). Than again, I currently do
not know enough about the DLL to be certain that it *really* isn't possible
....

(1) The same problem would most likely appear when for example using
'GdipCreateBitmapFromScan0'.
Post by JJ
Unfortunately, yes. GDI+ is not perfect. But you can save it into
a memory stream.
Yep, I have to revisit it.
Post by JJ
I don't think so. But if it does, what should that setting for?
I was thinking of either an "ignore current image format" override setting,
a "pre-encode" (/trans-encode) method, or a "ToFileEx" method which accepts
a property-list argument (like it currently already does for encoder
settings).

Hmm... Make me wonder if I can patch that GDI+ DLL to skip, for that one
function, the current image format check ...

Regards,
Rudy Wieser

JJ
2018-12-24 10:56:53 UTC
Permalink
Post by R.Wieser
It is as if the adding of the property is first checked against the
*current* image type (bitmaps do not seem to support metadata), and doesn't
at all consider the possibility that the result wil be saved as a fully
other one. :-(
Well... GDI+ Image class is a generic wrapper for various image formats.
But apparently, it's not generic enough.
Post by R.Wieser
Does this really mean I first need to first save the BMP as a JPG and than
reload the JPG before I can add properties to it ? That sounds a bit
brain-dead to me.
Unfortunately, yes. GDI+ is not perfect. But you can save it into a memory
stream.
Post by R.Wieser
Is there maybe some setting I need to apply ?
I don't think so. But if it does, what should that setting for?
Loading...