IOS 11 now uses a newer, more compressed, file compression routine as default. The HEIC photos (.heic extension) can be read in Windows 10, and other ways for earlier OS's. Without doing a conversion to Jpeg (jpg), how can Visual Basic 6.0 load them into a PictureBox or and Image control? Googled, but found no direct solution.
I know Windows Imaging Component (WIC) can read it, if you install the codec for it (HEIF Image Extensions)
I use WIC together with Direct2D, but Its possible to use WIC and GDI/GDI+ together.
can you explain a bit further? How/where do I get the codec (and is that a typo (HEIF in lieu of HEIC)?)?
I simply want to 'load' HEIC pictures into either an Image Control or PictureBox Control in VB6. Maybe if you can explain a bit better, I might be able to figure that out.
I'd guess that .heic is a contrarian's synonym for .heif but who can be sure?
As far as I can tell GDI+ has some support for perhaps some subsets of the format. It's really a container format so an individual file might have almost anything in there.
The trick created the tlb and modules for it, but theres no HEIC/HEIF CLSID for it, that "id" need to be found somewhere. But it shouldn't be impossible to get it, maybe googling from other programming languages that uses WIC.
you should check direct2d pages, its where The trick uploaded the package and go from there.
so, load it and after that render it into a picturebox should not be that hard.
and it seems that GDI can do it as well, as dilettante pointed out, using ImageFormatHEIF
but Im sure you need to install that codec first.
As far as I can tell GDI+ has some support for perhaps some subsets of the format. It's really a container format so an individual file might have almost anything in there.
Just to piggyback a bit. GDI+ may not support it anyway based on this assessment:
I have the WebP codec installed and Paint opens it just fine. ImageFormatWEBP is one of those formats dilletante linked to. But GDI+ doesn't seem to want to read WebP images, at least with the flat APIs.
I guess someone could download the codec and simply see if GDI+ will open it.
I think modern MS Paint uses WIC or WIA?
Insomnia is just a byproduct of, "It can't be done"
WIA just wraps GDI+ so I doubt it supports that family of file formats either. Even WIC probably only supports a subset, there are just too many kinds of crap one can cram into that container format.
I got nowhere with the GDI+ flat API after installing the extensions, even trying with the simplest examples I could locate. There might be new calls required or something.
The tests I have done in Windows 10 show that if Windows has installed the codec then the Windows Imaging Component can show it. Webp and Heif codecs are installed with 1909.
I have attached the WIC class I use. Also notice there is an undocumented setting value: Const WICBitmapInterpolationModeFant = 4&. The max for this is supposed to be 3 but 4 makes a marked improvement in image quality.
@Steve Grant: I could hoist your class for my AlphaBlendImage control to load .webp (and .heif) files to StdPictures and might use it for *all* other formats instead of GDI+ too.
Is this code public domain now that you posted it on the forums? I will most probably rewrite it completely but will surely use the ideas (and consts) in it.
Edit: AlphaBlendImage control has a GdipLoadPicture public function that can wrap 32-bit alpha transparent bitmaps into built-in StdPicture instances via hIcon handles.
cheers,
</wqw>
Last edited by wqweto; Dec 24th, 2019 at 05:48 AM.
As of commit ed578e9 the AlphaBlendImage control has a couple of WicLoadPicture and WicLoadPictureArray which are based on cWICImage class above and return StdPictures w/ alpha-channel support in an hIcon sub-type.
Unfortunately on my Win10 the reference autumn_1440x960.heic image bombs out with "Automation error\nThe image format is unknown" error.
YMMV as apparently Microsoft Windows [Version 10.0.17763.914] from cmd.exe is Version 1809 from winver.exe here on my machine.
Otherwise .webp images load just a ok w/ WIC.
cheers,
</wqw>
Last edited by wqweto; Dec 25th, 2019 at 08:39 AM.
As of commit ed578e9 the AlphaBlendImage control has a couple of WicLoadPicture and WicLoadPictureArray which are based on cWICImage class above and return StdPictures w/ alpha-channel support in an hIcon sub-type.
Can you help me to convert the loaded WIC image to a GDI image for further GDI+ processing?
I want to save the pic with GdipSaveImageToFile but i cant figure out how to get the GDI image handle from the loaded WIC image...
Can you help me to convert the loaded WIC image to a GDI image for further GDI+ processing?
I want to save the pic with GdipSaveImageToFile but i cant figure out how to get the GDI image handle from the loaded WIC image...
WicLoadPicture[Array] + pvLoadPicture prepare a normal GDI device-independant bitmap DIB + lpBits which is then stuffed as an icon inside an StdPicture.
In pvLoadPicture easiest would be to use the intermediate lpBits array of ARGB pixels and plug something like GdipCreateBitmapFromScan0(lWidth, lHeight, 4 * lWidth, PixelFormat32bppPARGB, lpBits, hBitmap) to create a GDI+ bitmap in hBitmap instead of StdPicture which can then be used with GdipSaveImageToFile to persist to file.
thanks for the hint with the API GdipCreateBitmapFromScan0.
i get now a bitmap handle with this API but when i use the handle with GdipSaveImageToFile the IDE crashes
maybe the created bitmap handle is not compatible with GdipSaveImageToFile?
my code:
Code:
... some WIC api stuff to load a picture
...
930 hMemDC = CreateCompatibleDC(0)
940 If hMemDC = 0 Then
950 GoTo ReleaseHandle
960 End If
970 With uHdr
980 .biSize = Len(uHdr)
990 .biPlanes = 1
1000 .biBitCount = 32
1010 .biWidth = lImageWidth
1020 .biHeight = -lImageHeight
1030 .biSizeImage = 4 * lImageWidth * lImageHeight
1040 End With
1050 hDib = CreateDIBSection(hMemDC, uHdr, DIB_RGB_COLORS, lpBits, 0, 0)
1060 If hDib = 0 Then
1070 GoTo ReleaseHandle
1080 End If
1090 lReturn = IWICBitmapSource_CopyPixels_Proxy(pScaler, ByVal 0&, lImageWidth * 4, lImageWidth * lImageHeight * 4, ByVal lpBits)
1100 If lReturn < 0 Then
1110 sError = lReturn & " (w9)"
1120 GoTo ReleaseHandle
1130 End If
1140 lReturn = GdipCreateBitmapFromScan0(lImageWidth, lImageHeight, lImageWidth * 4, PixelFormat32bppPARGB, lpBits, lBitmap)
1150 If lReturn <> 0 Then
1160 sError = GDIPLUS_Fehler(lReturn) & " (w10)"
1170 GoTo ReleaseHandle
1180 End If
2120 If GetEncoderClsid("image/png", tPicEncoder) = False Then
2130 ErrorMessage = "GetEncoderClsid: " & GDIPLUS_Fehler(retStatus)
2140 GoTo ReleaseAll
2150 End If
2160 retStatus = GdipSaveImageToFile(lBitmap, StrPtr(sTempImageFilename & ".png"), tPicEncoder, ByVal 0)
2170 If retStatus <> 0 Then
2180 ErrorMessage = "GdipSaveImageToFile: " & GDIPLUS_Fehler(retStatus)
2190 GoTo ReleaseAll
2200 End If
Btw, now seeing the final code hMemDC + hDIB seems redundant in this case -- you can allocate a 4 * lImageWidth * lImageHeight byte-array and use this as target for IWICBitmapSource_CopyPixels_Proxy and source buffer for GdipCreateBitmapFromScan0.
Check out GdipSaveImageToFile API declare too -- output filename should be ByVal As Long, structs should be As Any for ByVal 0 to work.
do you have any idea why the first 2 pixel are empty when using your buffer-method with IWICBitmapSource_CopyPixels_Proxy & GdipCreateBitmapFromScan0 ?
Code:
Dim pBuffer() As Byte
Dim bufSize As Long
bufSize = 4 * lImageWidth * lImageHeight
ReDim pBuffer(bufSize - 1)
lReturn = IWICBitmapSource_CopyPixels_Proxy(pScaler, ByVal 0&, lImageWidth * 4, bufSize, pBuffer(0))
lReturn = GdipCreateBitmapFromScan0(lImageWidth, lImageHeight, lImageWidth * 4, PixelFormat32bppPARGB, pBuffer(0), lBitmap)
It's not obvious if anything is wrong with thse two lines of code.
It looks like a whole horizontal line + 2 pixels are white. About the size of BITMAPINFO header. (Though these should have been black if header is zeroed out for some reason.)
after a lot of testing i found the reason for the missing pixels but i still dont understand why this happen
i have a WIC function to load a picture and to return a hBitmap for further processing with other GDI functions.
when i call this function i get back a GDI bitmap handle and i use this handle to save the pic in another format and convert it to a stdPicture but this leads to 2 missing pixel at the beginning of the pic.
if i do all this GDI-stuff (save/convert) inside the WIC function no pixels are missing in the converted picture.
is a returned bitmap handle from a function not the same as the handle from inside this function?
small Pseudo code example:
Code:
private function LoadWICimage(ByRef lBitmap As Long)
'some WIC stuff to load the pic
...
GdipCreateBitmapFromScan0(lImageWidth, lImageHeight, lImageWidth * 4, PixelFormat32bppPARGB, pBuffer(0), lBitmap)
end function
private function SaveImage(ByRef hBitmap as long)
dim lBitmap As Long
call LoadWICimage(lBitmap)
GetEncoderClsid("image/png", tPicEncoder)
GdipSaveImageToFile(lBitmap, StrPtr(sFilename & ".png"), tPicEncoder, ByVal 0)
GdipCreateHBITMAPFromBitmap(lBitmap, hBitmap, vbWhite) <-- creates the Bitmap with 2 missing pixel at the beginning
end function
if i put the code from the function "SaveImage" into the function "LoadWICimage" no pixel are missing...