I have two images I want to put one on top of the other and make the first one transparent . I am using this code but the transparency is not working at all. The second image is totally covering the first one. I am using C# , Framework 4.5 , Visual Studio 2012
static void Main(string[] args)
{
Image imageBackground = Image.FromFile(#"e:\picstest\profile.png");
Image imageOverlay = SetImageOpacity(Image.FromFile(#"e:\picstest\flag.png"), 50);
Image img = new Bitmap(imageBackground.Width, imageBackground.Height);
using (Graphics gr = Graphics.FromImage(img))
{
gr.DrawImage(imageBackground, new Point(0, 0));
gr.DrawImage(imageOverlay, new Point(0, 0));
}
string outputFileName = #"e:\picstest\output.png";
using (MemoryStream memory = new MemoryStream())
{
using (FileStream fs = new FileStream(outputFileName, FileMode.Create, FileAccess.ReadWrite))
{
img.Save(memory, ImageFormat.Jpeg);
byte[] bytes = memory.ToArray();
fs.Write(bytes, 0, bytes.Length);
}
}
}
public static Image SetImageOpacity(Image img, float opacity)
{
Bitmap bmp = new Bitmap(img.Width, img.Height); // Determining Width and Height of Source Image
Graphics graphics = Graphics.FromImage(bmp);
ColorMatrix colormatrix = new ColorMatrix();
colormatrix.Matrix33 = opacity;
ImageAttributes imgAttribute = new ImageAttributes();
imgAttribute.SetColorMatrix(colormatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
graphics.DrawImage(img, new Rectangle(0, 0, bmp.Width, bmp.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, imgAttribute);
graphics.Dispose(); // Releasing all resource used by graphics
return bmp;
}
}
}
It was fixed by putting the opacity value as lesser than 1 , apparently more than 1 makes it not transparent.
Related
I am trying to run a compute shader and get the resulting texture using SharpDX.
From what I understood, I need to:
1. Create a texture to set as an output to the shader.
2. Set the above texture as an unordered access view so I can write to it.
3. Run the shader
4. Copy the UAV texture to a staging texture so it can be accessed by the CPU
5. Read the staging texture to a Bitmap
The problem is that whatever I do, the result is a black bitmap. I don't think the bug is in the Texture2D -> Bitmap conversion code as printing the first pixel directly from the staging texture also gives me 0.
This is my shader code:
RWTexture2D<float4> Output : register(u0);
[numthreads(32, 32, 1)]
void main(uint3 id : SV_DispatchThreadID) {
Output[id.xy] = float4(0, 1.0, 0, 1.0);
}
Using the MS DX11 docs and blogs, I pieced together this code to run the texture:
public class GPUScreenColor {
private int adapterIndex = 0;
private Adapter1 gpu;
private Device device;
private ComputeShader computeShader;
private Texture2D texture;
private Texture2D stagingTexture;
private UnorderedAccessView view;
public GPUScreenColor() {
initializeDirectX();
}
private void initializeDirectX() {
using (var factory = new Factory1()) {
gpu = factory.GetAdapter1(adapterIndex);
}
device = new Device(gpu, DeviceCreationFlags.Debug, FeatureLevel.Level_11_1);
var compilationResult = ShaderBytecode.CompileFromFile("test.hlsl", "main", "cs_5_0", ShaderFlags.Debug);
computeShader = new ComputeShader(device, compilationResult.Bytecode);
texture = new Texture2D(device, new Texture2DDescription() {
BindFlags = BindFlags.UnorderedAccess | BindFlags.ShaderResource,
Format = Format.R8G8B8A8_UNorm,
Width = 1024,
Height = 1024,
OptionFlags = ResourceOptionFlags.None,
MipLevels = 1,
ArraySize = 1,
SampleDescription = { Count = 1, Quality = 0 }
});
UnorderedAccessView view = new UnorderedAccessView(device, texture, new UnorderedAccessViewDescription() {
Format = Format.R8G8B8A8_UNorm,
Dimension = UnorderedAccessViewDimension.Texture2D,
Texture2D = { MipSlice = 0 }
});
stagingTexture = new Texture2D(device, new Texture2DDescription {
CpuAccessFlags = CpuAccessFlags.Read,
BindFlags = BindFlags.None,
Format = Format.R8G8B8A8_UNorm,
Width = 1024,
Height = 1024,
OptionFlags = ResourceOptionFlags.None,
MipLevels = 1,
ArraySize = 1,
SampleDescription = { Count = 1, Quality = 0 },
Usage = ResourceUsage.Staging
});
}
public Bitmap getBitmap() {
device.ImmediateContext.ComputeShader.Set(computeShader);
device.ImmediateContext.ComputeShader.SetUnorderedAccessView(0, view);
device.ImmediateContext.Dispatch(32, 32, 1);
device.ImmediateContext.CopyResource(texture, stagingTexture);
var mapSource = device.ImmediateContext.MapSubresource(stagingTexture, 0, MapMode.Read, MapFlags.None);
Console.WriteLine(Marshal.ReadInt32(IntPtr.Add(mapSource.DataPointer, 0)));
try {
// Copy pixels from screen capture Texture to GDI bitmap
Bitmap bitmap = new Bitmap(1024, 1024, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
BitmapData mapDest = bitmap.LockBits(new Rectangle(0, 0, 1024, 1024), ImageLockMode.ReadWrite, bitmap.PixelFormat);
try {
var sourcePtr = mapSource.DataPointer;
var destPtr = mapDest.Scan0;
for (int y = 0; y < 1024; y++) {
// Copy a single line
Utilities.CopyMemory(destPtr, sourcePtr, 1024 * 4);
// Advance pointers
sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch);
destPtr = IntPtr.Add(destPtr, mapDest.Stride);
}
return bitmap;
} finally {
bitmap.UnlockBits(mapDest);
}
} finally {
device.ImmediateContext.UnmapSubresource(stagingTexture, 0);
}
}
}
I am pretty new to shaders so it may be something obvious...
First thing, you create your UAV as a local :
UnorderedAccessView view = new UnorderedAccessView(....
So the field is then null, replacing by
view = new UnorderedAccessView(....
will solve the first issue.
Second, it's quite likely that the runtime will complain about types (debug will give you something like :
The resource return type for component 0 declared in the shader code (FLOAT) is not compatible with the resource type bound to Unordered Access View slot 0 of the Compute Shader unit (UNORM).
Some cards might do something (fix it silently), some might do nothing, some might crash :)
Problem is that RWTexture2D does not match UNORM format (as you specify flating point format here).
You need to enforce your RWTexture to be specifically of unorm format eg (yes runtime can be that picky):
RWTexture2D<unorm float4> Output : register(u0);
Then your whole setup should work (PS: I did not check the bitmap code, but I doubled checked that the shader is running without error and first pixel is matching)
After create newBitmap i m getting exception - Parameter is not valid ,
When i want to create 9000*9000 pixel image. I need to create big resolution image. I cant able to create big Image because of this error.
My RAM is 16 GB .My system is 64 bit. Sometime it occurs Out of memory also.
How to solve this issue ?
Here is my code
private Bitmap createBigImage(Bitmap layerBitmap, int newWidth, int newHeight)
{
Bitmap newBitmap = new Bitmap(newWidth, newHeight, PixelFormat.Format32bppArgb);
using (Graphics gr = Graphics.FromImage(newBitmap))
{
gr.SmoothingMode = SmoothingMode.HighQuality;
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
gr.DrawImage(layerBitmap, new Rectangle(0, 0, newWidth, newHeight));
gr.Dispose();
}
return newBitmap;
}
Bitmap newbitmap = createBigImage(bitmap, 9000, 9000);
I use GetDIBits() to retrieve the bits of bitmap and copies them into a buffer. The function doesn't fail (the result is different to NULL), but I get wrong height of bitmap and erroneous buffer.
This is a part of my code:
HDC hdcMemDC = CreateCompatibleDC(hDC); // (hDC = hDC = BeginPaint(hwnd, &ps): i get it in WM_Paint)
int l_uiWidth = 400;
int l_uiHeight = 120;
HBITMAP hbmp = CreateCompatibleBitmap(hDC, l_uiWidth, l_uiHeight);
HGDIOBJ oldhbmp = SelectObject(hdcMemDC,hbmp);
BITMAPINFO bi;
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = l_uiWidth;
bi.bmiHeader.biHeight = l_uiHeight;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 8;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = 0;
bi.bmiHeader.biXPelsPerMeter = 0;
bi.bmiHeader.biYPelsPerMeter = 0;
bi.bmiHeader.biClrUsed = 256;
bi.bmiHeader.biClrImportant = 0;
BYTE *l_ImagePDM = new BYTE[l_uiWidth * l_uiHeight];
GetDIBits(hdcMemDC,hbmp,0,l_uiHeight,l_Image,&bi,DIB_RGB_COLORS);
Please Help me!
What's wrong with my code ?
You have not drawn anything on the bitmap that you are querying the bits for. CreateCompatibleBitmap() does not make a copy of the pixels of the source HDC. It merely allocates an HBITMAP that is compatible with the specified HDC, which then allows you to select the HBITMAP into that HDC. But you still have to draw something onto the bitmap to make its content meaningful before you can then query its bits.
When you use C++ Builder you can use Graphics unit for processing graphics.
Example of copying something from window:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
// Create a bitmap
Graphics::TBitmap* bit = new Graphics::TBitmap();
bit->PixelFormat = pf24bit;
bit->HandleType = bmDIB;
bit->Width = 200;
bit->Height = 200; // or bit->SetSize(200, 200) - newer versions C++ Builder
// Copy something from this Form (from window)
bit->Canvas->CopyRect(TRect(0, 0, 200, 200), this->Canvas, TRect(0, 0, 200, 200));
// Do something with bitmap data
RGBTRIPLE* line;
for (int i = 0; i < bit->Height; i++)
{
// Get memory address from line i
line = (RGBTRIPLE*) bit->ScanLine[i];
// Change 5'th pixel
line[5].rgbtRed = 255;
}
// Get whole bitmap memory. Bitmap data are stored upside down and size of each row is rounded
// up to a multiple of 4 bytes.
unsigned char* bitmem = (unsigned char*)(bit->ScanLine[ bit->Height-1 ]);
//...
// Draw bitmap on Form
Canvas->Draw(0, 200, bit);
delete bit;
}
When you have device context you can use TCanvas like this:
void __fastcall TForm1::Button2Click(TObject *Sender)
{
// Create device context
HDC hdc = GetDC(this->Handle); // or GetWindowDC - whole window with frame
// Create canvas and associate device context
TCanvas* canv = new TCanvas();
canv->Handle = hdc;
// Create a bitmap
Graphics::TBitmap* bit = new Graphics::TBitmap();
bit->PixelFormat = pf24bit;
bit->HandleType = bmDIB;
bit->Width = this->ClientWidth;
bit->Height = this->ClientHeight; // or bit->SetSize(w, h) - newer versions C++ Builder
// Copy window content
TRect r(0, 0, this->ClientWidth, this->ClientHeight);
bit->Canvas->CopyRect(r, canv, r); // USEING TCanvas
// Release context and delete canvas
ReleaseDC(this->Handle, hdc);
delete canv;
// Do something with the bitmap
bit->SaveToFile("screenshot.bmp");
delete bit;
}
You can also use TCanvas for device context from BeginPaint:
canv->Handle = BeginPaint(hwnd, &ps);
I have some tif files with multiple pages that I would like to convert to a single long page. i.e. a file including two pages that are each 8.5x11 would be converted to a resulting file of size 8.5x22. Is there any way to remove the page breaks?
I am not asking how to convert multiple files into a single file.
I have solved this. A good chunk of the following code comes from Scott Hanselman on this page.
This C# function takes a filename for the source image and a save location for its tiff output:
public static void RemovePageBreaks(string fileInput, string fileOutput)
{
using (Image image = Image.FromFile(fileInput))
using (MemoryStream m = new MemoryStream())
{
int width = image.Width;
int height = 0;
int pageCount = image.GetFrameCount(FrameDimension.Page);
height = image.Height * pageCount;
int pasteFrom = 0;
using (Bitmap compositeImage = new Bitmap(width, height))
using (Graphics compositeGraphics = Graphics.FromImage(compositeImage))
{
compositeGraphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
for (int page = 0; page < pageCount; page++)
{
image.SelectActiveFrame(FrameDimension.Page, page);
image.Save(m, image.RawFormat);
Rectangle rect = new Rectangle(0, pasteFrom, image.Width, image.Height);
compositeGraphics.DrawImageUnscaledAndClipped(image, rect);
pasteFrom += image.Height;
}
compositeImage.Save(fileOutput, System.Drawing.Imaging.ImageFormat.Tiff);
}
}
}
I have an Image object which is a jpg picture taken by the camera and I need to create a Bitmap from it.
Is there any way to do it besides using BMPGenerator class? I'm working on a commercial project and I don't think I can use it due to the GPLv3 license.
So far this is the code I have. Can I do something with it?
FileConnection file = (FileConnection) Connector.open("file://" + imagePath, Connector.READ_WRITE);
InputStream is = file.openInputStream();
Image capturedImage = Image.createImage(is);
I tried this but I wasn't able to get the correct filepaht and the image is stuck in null
EncodedImage image = EncodedImage.getEncodedImageResource(filePath);
byte[] array = image.getData();
capturedBitmap = image.getBitmap();
You can use videoControl.getSnapshot(null) and then Bitmap myBitmap = Bitmap.createBitmapFromBytes(raw, 0, raw.length, 1) to get a bitmap from camera.
videoControl is got from player.getControl("VideoControl") and player is got from Manager.createPlayer()
By the way, what kind of Image do you have? If we are talking of EncodedImage, you can just use getBitmap() from it.
Fixed!
Well, almost.
Used the following method but the image is rotated 90 degrees.
Going to fix that with this
public Bitmap loadIconFromSDcard(String imgname){
FileConnection fcon = null;
Bitmap icon = null;
try {
fcon = (FileConnection)Connector.open(imgname, Connector.READ);
if(fcon.exists()) {
byte[] content = new byte[(int) fcon.fileSize()];
int readOffset = 0;
int readBytes = 0;
int bytesToRead = content.length - readOffset;
InputStream is = fcon.openInputStream();
while (bytesToRead > 0) {
readBytes = is.read(content, readOffset, bytesToRead);
if (readBytes < 0) {
break;
}
readOffset += readBytes;
bytesToRead -= readBytes;
}
is.close();
EncodedImage image = EncodedImage.createEncodedImage(content,0,content.length);
icon = image.getBitmap();
}
} catch (Exception e) {
}finally{
// Close the connections
try{ if(fcon != null) fcon.close(); }
catch(Exception e){}
}
return icon;
}