Could someone help me to import individual jpeg images embedded in a gif image into each slide in a PowerPoint file? I use exportToPPTX.

1 visualizzazione (ultimi 30 giorni)
Hello,
Could someone help me to import individual jpeg images embedded in a gif image into each slide in a PowerPoint file? I use exportToPPTX.
Loaded gif data as in:
Gif = [dbase, 'figure.gif'];
The gif image was then separated independently as follows:
Images = imread(Gif, 'frames', 'all');
The separated images were generated to PowerPoint with the following codes, then error messages came up.
for kz = 1:Nz % Nz = number of images
exportToPPTX('addpicture', Images, 'Position', [0, 0, 3, 3]);
end
The error messages were as follows:
Error using writepng
PNG image data must be either MxN or MxNx3.
Error in imwrite
feval(fmt_s.write, data, map, filename, paramPairs{:});
Error in exportToPPTX>addPicture
imwrite(imgData,imagePath);
Error in exportToPPTX
PPTXInfo = addPicture(PPTXInfo,imgData,varargin{3:end});
Error in
exportToPPTX('addpicture', Images, 'Position', [0, 0, 3, 3]);
Could someone kindly suggest an appropriate code to add 'imwrite' to solve this situation?
Thank you very much for your help.

Risposte (2)

DGM
DGM il 2 Feb 2023
Modificato: DGM il 2 Feb 2023
As far as I know, the bug mentioned in the first link still exists, and the only solutions are those described at the end of the answer. While I don't run anything newer than R2019b, I've still browsed the contents of readgif.m in the current version, so I see no reason to think things are fixed.
Let's review. Prior to R2018b, this is how you would read a multiframe GIF:
% using basic tools (no transparent content)
fname = 'sources/globe.gif'; % this is not a standard test image
[inpict,~] = imread(fname,'frames','all'); % indexed color
S = imfinfo(fname);
[h,w,nchan,nframes,~] = size(inpict);
outpict = zeros(h,w,3,nframes,'uint8');
for f = 1:nframes
% each image frame is converted using its assigned CT
outpict(:,:,:,f) = im2uint8(ind2rgb(inpict(:,:,:,f),S(f).ColorTable));
end
If your image had transparent regions, you'd have to take extra steps if you wanted to preserve it.
% using basic tools (with transparent content)
fname = 'sources/globe.gif'; % this is not a standard test image
[inpict,~] = imread(fname,'frames','all'); % indexed color
S = imfinfo(fname);
[h,w,nchan,nframes,~] = size(inpict);
outpict = zeros(h,w,3,nframes,'uint8');
alpha = zeros(h,w,1,nframes,'uint8');
for f = 1:nframes
% each image frame is converted using its assigned CT
outpict(:,:,:,f) = im2uint8(ind2rgb(inpict(:,:,:,f),S(f).ColorTable));
% each alpha frame is generated using the relevant TC index (zero-based)
alpha(:,:,:,f) = im2uint8(inpict(:,:,:,f) ~= (S(f).TransparentColor-1));
end
MIMT gifread() handles all those cases internally and defaults to 4D RGB/RGBA output. It's a convenience, but it's still doing basically the same things, and it's still internally dependent on imread()/imfinfo() and all their private functions.
% MIMT gifread() default output is RGB (or RGBA if there is transparent content)
fname = 'sources/globe.gif';
inpict = gifread(fname); % RGB/RGBA uint8
nframes = size(inpict,4); % need this for later anyway
[outpict alpha] = splitalpha(inpict); % split alpha if present
If you're running R2018b or newer, none of the above will work as expected. The indexed image data (inpict) returned by imread() will be wrong. You will no longer be able to use the LCTs or TransparentColor indices retrieved from imfinfo() to convert the image to RGB. As mentioned in the prior thread, readgif.m (a support file used internally by imread()) destructively remaps all frames to use the calculated CT for frame 1. The internal documentation is is slightly incorrect in stating that it uses the LCT for frame1. Whether that's a LCT or the GCT depends on how the file was created. Regardless of whether it uses LCT1 or the GCT, it's the wrong CT for any other frame with a unique LCT.
The canonical usage is to simply apply the wrong map to all the frames, which obviously is a bad idea:
% THIS USUALLY GENERATES GARBAGE
fname = 'sources/globe.gif'; % this is not a standard test image
[inpict map1] = imread(fname,'frames','all'); % indexed color
[h,w,nchan,nframes,~] = size(inpict);
outpict = zeros(h,w,3,nframes,'uint8');
for f = 1:nframes
% apply map for frame1 to ALL FRAMES for no good reason
outpict(:,:,:,f) = im2uint8(ind2rgb(inpict(:,:,:,f),map1));
end
If your LCTs are significantly unique, this results in a bunch of garishly dithered garbage. If your LCTs are only weakly unique, then the damage might be subtle, but it will be there.
In the comments below, I've included a specially-constructed test GIF and script that can be used to test for the correct operation of readgif.m.
So how do you work around this problem? I proposed three ways:
  1. Edit $matlabroot/toolbox/matlab/imagesci/private/readgif.m to prevent the destructive remapping of the image data. Doing so requires write privileges to that file. Once readgif.m is fixed, then the first three examples should work correctly.
  2. Split the file externally using ImageMagick via the 'imagemagick' option in MIMT gifread(). This was a workaround for a much older bug, but it works here as well. Unfortunately, it also requires that you have ImageMagick installed and are using linux. I'm going to assume this is unlikely an option.
  3. Split the file externally using some other program. This may be done manually or possibly via system() calls. Once the file is split into single-frame images, imread() can read them without ruining them.
If you have write access, option 1 is probably the easiest, though I make no guarantee that it won't break the task of coalescing optimized GIFs. For now, let's assume that your GIF is simple and that nothing has changed significantly in the last few years. Open readgif.m and somewhere you'll find this conditional:
if hasLocalColorTable
% If the current frame's color table and previous's frame
% color is different then convert the current frame such
% that it can render correctly using the first color table.
% See geck g167814
current_frame = transformCurrentFrame(current_frame,current_info,map);
end
Comment out the call to transformCurrentFrame(), save the file, and restart MATLAB. At that point, you should be able to use the above examples as you see fit.
As for writing the images to a PPTX, that depends again on whether there is transparent content. If there isn't, then you should be able to pass the image data from the workspace. If there is transparent content, you may be forced to write each frame to a transparent PNG and then pass the file path to exportToPPTX() instead. I'm not exactly sure how to use it, but I don't see any other way to include transparency information.
  10 Commenti
DGM
DGM il 20 Apr 2023
What portions of the file were changed from the stock version? This is significantly different than the version that I have (the 2018 version is what's in R2019b), It looks like a lot of the stuff for handling the different disposal methods has been changed/removed, so I don't know if that's part of the 2020 version of the file, or if that's something that was done in order to fix the problem at hand.
As is, this doesn't work in R2019b, since it's referencing a bunch of private/builtin stuff that's different in R2019b.
Henry Barth
Henry Barth il 21 Apr 2023
Modificato: Henry Barth il 21 Apr 2023
It's the R2021a version with fixes. Sorry to hear that it doesn't work in R2019b.
  • Edit: Keep in mind that my function is an edit of the function
readgif
that is (at least in R2021a) the basis for imread when it comes to gifs.

Accedi per commentare.


Walter Roberson
Walter Roberson il 29 Gen 2023
Images = imread(Gif, 'frames', 'all');
.gif files are always indexed images.
In the special case that the frames were grayscale, and the gif was written out by imwrite() [and probably by some other software packages, but not all) then the colormap stored would be a linear grayscale map in which the uint8 data returned int Images would be exactly the same as the uint8 intensity level. This is not promised by GIF: it is completely valid to write out a GIF in which the indexes map to some other grayscale level entirely.
JPEG images are almost always RGB images, so if you used imwrite() with 'writemode', 'append' to store images that were originally read from JPEG files, chances are high that what got stored was RGB data. Although apparently it is possible to have different color maps for different frames in GIF files, imread() and imwrite() do not support that; when you imwrite() the first RGB image it will internally [ind, cmap] = rgb2ind(DATA, 256) to buid a colormap and every frame after that will be ind = rgb2ind(DATA, StoredCmap) -- all converted to the same colormap used on the first frame.
If you happened to read a bunch of JPEG images into a 4d array (row, column, channel, imagenumber) and you imwrite() that entire array at the same time, then imwrite() will use all of the data together to build the colormap.
What this means is that unless you have the special case that your JPEG images were grayscale JPEG (possible but highly uncommon) or else that you specifically did rgb2gray() on each of the JPEG images before doing the imwrite()... then chances are high that you need to read the colormap out of the GIF file and do color conversion, because that Image variable is going to be indices not color or intensity information.
So you would need
[Image_ind, cmap] = imread(Gif, 'frames', 'all');
Images = ind2rgb(Image_ind, cmap);
then when you go to write to powerpoint you need to write one at a time:
for kz = 1:Nz % Nz = number of images
exportToPPTX('addpicture', Images(:,:,:,k), 'Position', [0, 0, 3, 3]);
end
  3 Commenti
DGM
DGM il 1 Feb 2023
Modificato: DGM il 1 Feb 2023
Unless all the images in the GIF use the same colormap, you cannot simply read the GIF file correctly with a single call to imread(). A single call to imread() will only return the color table (CT) used by frame 1. Even if you could, (as far as I recall) ind2rgb() cannot accept 4D inputs.
If the frames within your GIF use unique local color tables (LCT), then you cannot correctly read the file with imread() in any contemporary version unless you take extra steps to do so.
So what exactly is your GIF file? If it uses unique LCT's and you're running R2018b or newer, then the only way to correctly read the file requires workarounds. If your GIF uses a common CT for all frames, then you'll have to convert the indexed results to RGB one frame at a time.
The following FEX tools simplify GIF reading/writing, but they'll still require extra effort to fix the problems with newer versions.
Matt
Matt il 1 Feb 2023
Thank you DGM for your helpful advice.
My GIF file uses unique LCT and my MATLAB is version R2022b. If you can kindly suggest appropriate script I could try, I'd be very grateful. (Sorry I'm still a beginner for coding.)
Thanks for your help!

Accedi per commentare.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by