=======================
=======================
=======================
주의
Image::FromFile(파일경로이름)
Bitmap::FromFile(파일경로이름)
이 함수를 쓸대 파일경로이름 문자열을 (WCHAR*)L"파일경로이름" 이렇게 처리해주어야
파일을 제대로 찾는다
Visual Studio 2017 버전을 쓰는데 "L" 자를 뺴먹어서 파일을 찾지를 못해 애먹은적이 있다.
=======================
=======================
=======================
출처:
일반적으로 배우는 Win32API에서 이미지 출력은 BMP파일을 리소스에 등록하여 LoadImage함수로 핸들을 받아와 Bitblt 하는 방법을 사용한다. 비트맵에 배경값을 지우는 transparentblt함수등이 있지만 PNG파일은 사용할 수 없다..
GDI+를 사용하면 다음과 같은 포맷을 기본적으로 사용가능하다
BMP
GIF
JPEG
PNG
TIFF
사용하는 방법도 크게 어렵지 않다.
// 헤더 추가
#include <gdiplus.h>
using namespace Gdiplus;
// 링커 추가
#pragma comment(lib, "Gdiplus.lib")
// 초기화
ULONG_PTR gdiplusToken; // 마지막에 GdiplusShutdown에서 사용하므로 저장필수.
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
//이미지 불러오기
Image* image = Image::FromFile(L"image..png"); // 같은 폴더내에 image.png 파일을 불러옴.
//그리기
Graphics g( [hdc] ); // Bitblt에서 사용하던 그 hdc를 넣으면 됨.
g.DrawImage(image, [x], [y]); // x, y좌표 외에도 width ,height를 받는 등의 오버로딩된 함수가 많다.
//해제
delete image;
GdiplusShutdown(gdiplusToken);
이미지를 불러오는 과정에서 FromFile은 외부경로를 통해 읽어오므로 이미지파일이 같은 폴더안에 있어야 한다.
(즉 .exe파일과 .png파일이 같은 폴더에 있어야함. 또한 프로그램 실행중 .png파일의 수정 불가능.)
리소스를 통해 불러오는 방법은 다음 포스팅에 이어서...
=======================
=======================
=======================
출처: https://msdn.microsoft.com/ko-kr/library/4sahykhd(v=vs.110).aspx
Image::FromFile 메서드 (String^, Boolean)
게시 날짜: 2016년 11월
만듭니다는 Image 지정된 된 파일에서 사용 하 여 색 관리 정보 파일에 포함 된 해당 합니다.
어셈블리: System.Drawing(System.Drawing.dll에 있음)
매개 변수
- filename
- Type: System::String^
작성 하려는 파일의 이름을 포함 하는 문자열은 Image합니다.
- useEmbeddedColorManagement
- Type: System::Boolean
로 설정 true 이미지 파일에 포함 된 색 관리 정보를 사용 하 여 그렇지 false합니다.
Exception | Condition |
---|---|
OutOfMemoryException |
파일에 올바른 이미지 형식이 없는지 않습니다.
또는 GDI+ 파일의 픽셀 형식을 지원 하지 않습니다. |
FileNotFoundException |
지정한 파일이 존재 하지 않습니다.
|
ArgumentException |
filename 한 Uri합니다.
|
관리 GDI + 기본 제공 인코더 및 디코더는 다음 파일 형식을 지 원하는 있습니다.
- BMP
- GIF
- JPEG
- PNG
- TIFF
파일에 올바른 이미지 형식이 없는 경우 또는 경우 GDI+ 픽셀 형식을 지원 하지 않는 파일의이 메서드에서 throw는 OutOfMemoryException 예외입니다.
파일 될 때까지 잠긴 상태로 유지는 Image 삭제 됩니다.
useEmbeddedColorManagement 매개 변수를 지정 하는지 여부를 새 Image 이미지 파일에 포함 된 색 관리 정보에 따라 색 보정을 적용 합니다.포함 된 정보는 International Color Consortium (ICC) 프로필, 감마 값 및 chromaticity 정보에 포함할 수 있습니다.
참고 |
---|
Image 클래스 비트맵에 알파 투명도 지원 하지 않습니다. 알파 투명도 사용 하려면 PNG 이미지 픽셀당 32 비트를 사용 합니다. |
다음 코드 예제를 사용 하 여 새 비트맵을 구하는 방법의 FromFile 메서드. 에 대해서도 설명는 TextureBrush합니다.
이 예제는 Windows Forms에서 사용할 수 있습니다. 이라는 단추가 포함 된 폼을 만들 Button2합니다. 코드를 폼에 붙여넣고 연결의 Button2_Click 메서드는 단추의 Click 이벤트입니다.
private: void Button2_Click( System::Object^ /*sender*/, System::EventArgs^ /*e*/ ) { try { Bitmap^ image1 = dynamic_cast<Bitmap^>(Image::FromFile( "C:\\Documents and Settings\\" "All Users\\Documents\\My Music\\music.bmp", true )); TextureBrush^ texture = gcnew TextureBrush( image1 ); texture->WrapMode = System::Drawing::Drawing2D::WrapMode::Tile; Graphics^ formGraphics = this->CreateGraphics(); formGraphics->FillEllipse( texture, RectangleF(90.0F,110.0F,100,100) ); delete formGraphics; } catch ( System::IO::FileNotFoundException^ ) { MessageBox::Show( "There was an error opening the bitmap." "Please check the path." ); } }
=======================
=======================
=======================
출처: http://stackoverflow.com/questions/182988/how-to-draw-argb-bitmap-using-gdi
add a comment
|
6
|
I've got working sample:
// 1. Get info using bitmap handle: image size, bits BITMAP bmpInfo; // 2. Create & draw new GDI+ bitmap using bits with pixel format PixelFormat32bppARGB Gdiplus::Graphics graphics(dcMemory); |
||
0
|
.NET offers the static
Image.FromHbitmap method. You can then use this image and invoke DrawImage on the target Graphics object. |
||||||||
|
0
|
Ah... but .Net doesn't use HBITMAP and GDI+ is a C++ library atop the basic Windows GDI, so I'm assuming you're using non-.Net C++.
GDI+ has a Bitmap class, which has a FromHBITMAP() method. Once you have the GDI+ Bitmap instance, you can use it with the GDI+ library. Of course, if you can write your program in C# using .Net it will be a lot easier. |
||
0
|
I had similar issues getting my transparent channel to work. In my case, I knew what the background color should be used for the transparent area (it was solid). I used the Bitmap.GetHBITMAP(..) method and passed in the background color to be used for the transparent area. This was a much easier solution that other attempts I was trying using LockBits and re-creating the Bitmap with PixelFormat32bppARGB, as well as cloning. In my case, the Bitmap was ignoring the alpha channel since it was created from Bitmap.FromStream.
I also had some very strange problems with the background area of my image being changed slightly. For example, instead of pure white, it was off white like 0xfff7f7. This was the case whether I was using JPG (with blended colors) or with PNG and transparent colors. See my question and solution at GDI+ DrawImage of a JPG with white background is not white |
=======================
=======================
=======================
출처: http://stackoverflow.com/questions/335273/how-to-create-a-gdiplusbitmap-from-an-hbitmap-retaining-the-alpha-channel-inf
When I create a new Gdiplus::Bitmap using the Bitmap::FromHBITMAP function, the resulting Bitmap is opaque - none of the partial transparency from the original HBITMAP is preserved.
Is there a way to create a Gdiplus::Bitmap from an HBITMAP which brings across the alpha channel data?
|
Do you know for sure that the HBITMAP has an alpha channel to start with? For instance, did you create it as a DIB with BI_RGB and 32bpp or some other way? – Johann Gerell Dec 3 '08 at 10:33
|
||
|
Yes, it does have transparency. It draws nicely using the ::AlphaBlend() function. – mackenir Dec 3 '08 at 13:44
|
||
|
(I created it in C# using new Bitmap(string filename) and the calling GetHBitmap() on the .NET bitmap object)– mackenir Dec 3 '08 at 13:46
|
---------------------------------------------------------
8
|
I think working code is more useful than instructions, so:
|
||||||||
|
----------------------------------------------------
It turns out that GDI+ never brings across the alpha channel when creating a Bitmap from an HBITMAP.
The answer is to:
- Use GetObject passing in a BITMAP and the HBITMAP, to get the width and height (and if the input bitmap is a DIB, the pixel data) of the input HBITMAP.
- Create a Bitmap of the correct size with 32 bit PARGB pixel format.
- Use LockBits to get hold of the pixelData memory of your new Bitmap.
- If you got the pixels from GetObject, copy the ARGB values across using memcpy.
- Call UnlockBits on the new Bitmap.
In my case, the format of the input HBITMAP is correct for doing a straight memcpy from input bitmap pixel data to the new Bitmap pixel data.
If you didnt get the input pixel data from GetObject, use GetDIBits to get a copy in the correct format.
=======================
=======================
=======================
출처: http://stackoverflow.com/questions/37901425/get-32-bit-rgba-image-from-windows-clipboard
I want my app (which works with RGBA8888 images) to be able to paste images from the Windows clipboard. So it should be able to read images off the clipboard that come from any common raster image apps like Gimp, Photoshop, MSPaint, etc.
From reading up on the clipboard functions, it seems I should be able to call GetClipboardData(CF_DIBV5) to get access to pretty much any bitmap type that's on the Clipboard since Windows automatically converts between that and CF_BITMAP and CF_DIB. But from reading up on the DIB format, I see that there is an immense number of possible combinations of bit depth, RGB order, optional compression, etc. It seems like what I'm doing would be a common task, but I don't see any conversion functions in the Windows API (unless I'm poor at searching), and this seems like something that would take a week to write to support all possible formats. So I'm wondering if I've overlooked something obvious. Or if there is some kind of assumption I can make to simplify this...like if all the popular image apps happen to copy images to the clipboard in uncompressed/unindexed formats.UPDATE: Here's what I have so far: HGLOBAL clipboard = GetClipboardData(CF_DIBV5); exists = clipboard != NULL; int dataLength = GlobalSize(clipboard); exists = dataLength != 0; if (exists) { LPTSTR lockedClipboard = GlobalLock(clipboard); exists = lockedClipboard != NULL; if (exists) { BITMAPV5HEADER *header = (BITMAPV5HEADER*)lockedClipboard; LONG width = header->bV5Width; LONG height = header->bV5Height; BYTE *bits = header + sizeof(header) + header->bV5ClrUsed * sizeof(RGBQUAD); //Now what? Need function to convert the bits to something uncompressed. GlobalUnlock(clipboard); } } UPDATE 2: To clarify, I need literally uncompressed 32 bit image data (RRGGBBAA) which I can manipulate however I like in a cross-platform app. I have no need to use Windows APIs to draw this image to screen. I am aware of a 3rd party library called stdb_image.h that can load .bmps, .jpgs, and .pngs into the type of data I need. So if there's a way I can turn the clipboard data into bitmap or png file data without losing alpha, then I'll be in good shape. |
||||||||||||||
|
1
|
The basic strategy I've found is to check if there's a raw PNG on the clipboard and use that first if available. That's the easiest. Some apps, such as GIMP, copy images as PNG to the clipboard.
Then check for CF_DIBV5 . The location of the actual bits depends on whether the "compression" is BI_BITFIELDS :int offset = bitmapV5Header->bV5Size + bitmapV5Header->bV5ClrUsed * (bitmapV5Header->bV5BitCount > 24 ? sizeof(RGBQUAD) : sizeof(RGBTRIPLE)); if (compression == BI_BITFIELDS) offset += 12; //bit masks follow the header BYTE *bits = (BYTE*)bitmapV5Header + offset; If the header says compression is BI_BITFIELDS , then the data is already as I needed it.If the header says compression is BI_RGB and the bit count is 24 or 32, then I can unpack the bytes. 24 bytes means row size might not land on a DWORD boundary, so you have to watch for that.Finally, lower bit counts than 24 likely mean indexed color, which I don't have working yet. |
||
0
+50
|
Here is example of usage for
CF_DIBV5 and CF_DIB . It's best to use CF_DIB as backup option. Note, this code won't work for palette based images (if it is not guaranteed 32bit then see the method further down)You can use SetDIBitsToDevice to draw directly on HDC , or use SetDIBits GDI functions don't support alpha transparency (except for a couple of functions like TransparentBlt ), in general you have to use libraries such as GDI+ for that.void foo(HDC hdc) { if (!OpenClipboard(NULL)) return; HANDLE handle = GetClipboardData(CF_DIBV5); if (handle) { BITMAPV5HEADER* header = (BITMAPV5HEADER*)GlobalLock(handle); if (header) { BITMAPINFO bmpinfo; memcpy(&bmpinfo.bmiHeader, header, sizeof(BITMAPINFOHEADER)); bmpinfo.bmiHeader.biSize = sizeof(BITMAPINFO); //(use `header` to access other BITMAPV5HEADER information) int w = bmpinfo.bmiHeader.biWidth; int h = bmpinfo.bmiHeader.biHeight; const char* bits = (char*)(header) + header->bV5Size; //draw using SetDIBitsToDevice SetDIBitsToDevice(hdc,0,0,w,h,0,0,0,h,bits,&bmpinfo,DIB_RGB_COLORS); } } else { handle = GetClipboardData(CF_DIB); if (handle) { BITMAPINFO* bmpinfo = (BITMAPINFO*)GlobalLock(handle); if (bmpinfo) { int w = bmpinfo->bmiHeader.biWidth; int h = bmpinfo->bmiHeader.biHeight; const char* bits = (char*)(bmpinfo)+bmpinfo->bmiHeader.biSize; SetDIBitsToDevice(hdc, 0, 0, w, h, 0, 0, 0, h, bits, bmpinfo, 0); } } } CloseClipboard(); } If the original image is palette based, you would have to convert to 32bit. Alternatively you could add BITMAPFILEHEADER to the data (assuming the source is bitmap) then pass to the other library.This is an example using CreateDIBitmap and GetDIBits to make sure the pixels are in 32bit:HANDLE handle = GetClipboardData(CF_DIB); if (handle) { BITMAPINFO* bmpinfo = (BITMAPINFO*)GlobalLock(handle); if (bmpinfo) { int offset = (bmpinfo->bmiHeader.biBitCount > 8) ? 0 : sizeof(RGBQUAD) * (1 << bmpinfo->bmiHeader.biBitCount); const char* bits = (const char*)(bmpinfo)+bmpinfo->bmiHeader.biSize + offset; HBITMAP hbitmap = CreateDIBitmap(hdc, &bmpinfo->bmiHeader, CBM_INIT, bits, bmpinfo, DIB_RGB_COLORS); //convert to 32 bits format (if it's not already 32bit) BITMAP bm; GetObject(hbitmap, sizeof(bm), &bm); int w = bm.bmWidth; int h = bm.bmHeight; char *bits32 = new char[w*h*4]; BITMAPINFOHEADER bmpInfoHeader = { sizeof(BITMAPINFOHEADER), w, h, 1, 32 }; HDC hdc = GetDC(0); GetDIBits(hdc, hbitmap, 0, h, bits32, (BITMAPINFO*)&bmpInfoHeader, DIB_RGB_COLORS); ReleaseDC(0, hdc); //use bits32 for whatever purpose... //cleanup delete[]bits32; } } |
||||||||||||||||||||
|
=======================
=======================
=======================
출처: https://support.microsoft.com/ko-kr/help/309482/image-file-is-locked-when-you-set-the-picturebox-image-property-to-a-file
PRB: PictureBox Image 속성을 파일로 설정하면 이미지 파일이 잠긴다
현상
해결 방법
Dim fs As System.IO.FileStream
' Specify a valid picture file path on your computer.
fs = New System.IO.FileStream("C:\WINNT\Web\Wallpaper\Fly Away.jpg",
IO.FileMode.Open, IO.FileAccess.Read)
PictureBox1.Image = System.Drawing.Image.FromStream(fs)
fs.Close()
현재 상태
추가 정보
디자인 타임
디자인 타임에 PictureBox 컨트롤의 Image 속성을 설정하면 Visual Studio .NET IDE가 그림 파일을 잠급니다. Image 속성을 재설정하거나 PictureBox 컨트롤을 삭제해도 그림 파일은 잠긴 상태로 있습니다. 그림 파일을 잠금 해제하는 유일한 방법은 Visual Studio .NET IDE를 닫는 것입니다.문제를 재현하는 방법
- Visual Studio .NET에서 새 Visual Basic Windows 응용 프로그램 프로젝트를 만듭니다. 기본적으로 Form1이 만들어집니다.
- Form1에 PictureBox 컨트롤을 추가하고 Image 속성을 그림 파일로 설정합니다.
- Windows 탐색기에서, PictureBox 컨트롤에서 Image 속성으로 사용한 그림 파일의 이름을 바꾸어 봅니다. 공유 위반 오류 메시지가 나타납니다.
- 속성 창에서 Image 속성을 마우스 오른쪽 단추로 누른 다음 다시 설정을 누릅니다. 그림 파일의 이름을 바꾸어 봅니다. 공유 위반 오류 메시지가 나타납니다.
- Form1에서 PictureBox 컨트롤을 삭제한 다음 Windows 탐색기에서 그림 파일의 이름을 바꾸어 봅니다. 공유 위반 오류 메시지가 나타납니다.
런타임
Image.FromFile 메서드를 사용하여 PictureBox 컨트롤의 그림을 로드하면 응용 프로그램을 시작할 때 그림 파일이 잠깁니다. 응용 프로그램이 실행되는 동안에도 그림 파일이 잠긴 상태로 있습니다. 런타임에 Image 속성을 Nothing으로 설정해도 그림 파일이 잠깁니다.문제를 재현하는 방법
- Visual Studio .NET에서 새 Visual Basic Windows 응용 프로그램 프로젝트를 만듭니다. 기본적으로 Form1이 만들어집니다.
- PictureBox 컨트롤 하나와 Button 컨트롤 하나를 Form1에 추가합니다.
- Button 컨트롤에 대한 Click 이벤트에서 다음 코드를 붙여넣습니다.
' Specify a valid picture file path on your machine below PictureBox1.Image = Image.FromFile("C:\WINNT\Web\Wallpaper\Fly Away.jpg")
- F5 키를 눌러 응용 프로그램을 실행한 다음 Button 컨트롤을 눌러 PictureBox 컨트롤의 그림을 로드합니다.
- 응용 프로그램이 실행되는 동안 Windows 탐색기를 사용하여 그림 파일의 이름을 바꾸어 봅니다. 공유 위반 오류 메시지가 나타나고 파일의 이름을 바꿀 수가 없습니다.
=======================
=======================
=======================
'프로그래밍 관련 > MFC' 카테고리의 다른 글
C, C++ MFC 컨트롤, 프레임 디자인 하기 관련 (0) | 2017.05.31 |
---|---|
GDI+ 설정방법, 이미지출력, 투명화, 더블버퍼링, 이미지회전, jpg생성, 글자 출력, GDI와 데이터형 변환 관련 (0) | 2017.03.21 |
[MFC] 마우스 커서 숨기기, 보이게 하기 관련 (0) | 2016.12.01 |
[MFC] UI, 이미지로드 변경수정시 Invalidate(); 하였을때 더블버퍼링으로 부드럽게,GDI+ 더블 버퍼링 관련 (0) | 2016.12.01 |
[MFC] GDI+를 이용한 이미지처리 (Gray, 투명, 회전), 선그리기 관련 (0) | 2016.11.30 |