I have a program that copies images from a webpage and saves them locally. On certain webpages the saved image is a completely black screen. First I thought it was a problem in the code that didn't take the good picture. So I started investigating. I went manually to those pages and tried to copy the image(right click, copy image) and it still returned a black image. Can someone tell me how can I bypass this from code? Here is the current code, which works fine for most of the pictures
IHTMLDocument2 doc = (IHTMLDocument2)webBrowser1.Document.DomDocument;
IHTMLControlRange imgRange = (IHTMLControlRange)((HTMLBody)doc.body).createControlRange();
foreach (IHTMLImgElement img in doc.images)
{
if (img.alt != "my image alt")
continue;
imgRange.add((IHTMLControlElement)img);
imgRange.execCommand("Copy", false, null);
using (Bitmap bmp = (Bitmap)Clipboard.GetDataObject().GetData(DataFormats.Bitmap))
{
if (bmp != null)
{
bmp.Save("testimg.jpg");
}
}
}
That image has a transparent background.
Therefore, every pixel in the image is black, except that most of them are fully transparent.
Since .jpg files do not support transparency, saving it as a .jpg results in a black image.
If you save it as a .png file (which does support transparency), it should work.
Related
I am loading a png file using stb_image_load.
The code looks something like
stbi_uc* pixels = stbi_load("textures/viking_room.png", &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
...
if (stbi_failure_reason()) std::cout << stbi_failure_reason();
if (!pixels) throw std::runtime_error("failed to load texture image!");
Now stbi_failure_reason() return no SOI but pixels is not empty and loads the texture perfectly. The first result on github about this was about malformed png headers, so I checked using pngcheck, but it says that the png file is OK.
Any idea why this might be happening? I've also had trouble loading this image However it works with other images, is there any way I can avoid this in future?
There was an issue opened 787 for this and was fixed on a newer version (2.27)
when displaying images in codename 1 form they appear blurred, where is and how can I solve the problem?
Have tried displaying them using image viewer and ImageLabel but non seems to work for me
Image image = URLImage.createToStorage(
EncodedImage.createFromImage(Utils.getTheme().getImage("default_avatar.png"), false), imageName,
imageUrl);
ImageViewer imageViewer = new ImageViewer(image);
imageViewer.getAllStyles().setBgTransparency(0);
When you download an image with URLImage it's scaled to to the size of default_avatar.png. That would mean you lost all the pixels of a larger size. You should use something like:
ConnectionRequest cr = new ConnectionRequest();
cr.downloadImageToStorage(imageName, img -> {
// callback when image downloaded
});
As stated, how should we properly save a captured signature using SignaturePad component to a SQL Server database? Well it should be easy, considering the GetImage(false) method used by the component returns a Bitmap and later on compress the Bitmap into a JPEG and into an array byte using a Stream. The byte array should then be saved directly to the SQL Server database; however, the problem with this approach is that when you retrieve the image from the database, the image is all black. It's like the strokes were never captured, funny thing though is that the background color of the SignaturePad was set to White and the stroke color is Black.
Xamarin.Android Button OnClick Event Handler
var signature = this.SignatureView.GetImage(false); // This returns the Bitmap from SignaturePad.
var imageData = this.ImageToByteArray(signature); // This converts the Bitmap to byte[].
var result = this.SaveDataAsync(imageData); // Save the byte[] to the database.
Xamarin.Android Extension Method
private byte[] ImageToByteArray(Bitmap image)
{
if (image == null) return null;
byte[] result;
using (var stream = new MemoryStream())
{
image.Compress(CompressFormat.Jpeg, 100, stream);
result = stream.ToArray();
stream.Flush();
}
return result;
}
This is the same approach we did on iOS, but doesn't work on Android. Any ideas or working solution would be very much appreciated.
Thanks!
Copied from Xamarin Forum - Components Section
Okay, I think I found a solution to this issue, which was described in this thread Signature Pad for Xamarin.Forms. I am not sure why we need to specify the colors within the GetImage() method, while the properties for the Stroke and Background colors has already been specified. Well, I guess the colors needed to draw the image is not the same with that of the properties.
I am using birt to develop some reports,I want to display some pie charts in the birt pdf report,I found the birt chart function is not very flexiable,so I want to use jfreechart to generate an image and show it in the report instead. Now I have a question: can we show image in birt with the image inputstream,so that the image do not need to be generated and store in some place?
I know I can generate the image into a jpg file and store it in some place ,then I can access it birt report via the location of this image file.But if I do as that ,each time when we view the birt report ,it will generate a new image file,I do not want to generate so much files.
Any good ideas?
There are two possible solutions.
As you said, you can save the charts as files.
I do this in a report where I generate dozens of control charts (German: "Regelkarten"). To tidy up after the report has finished, I add the generated file names to a list, then I delete the files in the list in the report's afterRender script like this.
var images = vars["images"];
for (var i=0; i<images.size(); i++) {
var fname = images.get(i);
if (new java.io.File(fname)['delete']()) {
log.debug("Temp. image file removed: " + fname);
} else {
log.error("Could not delete temp. image file " + fname);
}
}
Note: This is OK for generating PDF or Word, but probably it wouldn't work for HTML.
In my case, I did this because I could check the generated charts outside of BIRT by just commenting out the clean up routine.
The other option is to generate a byte[]. BIRT complains in the log file then (Rhino, something about unknown type mapping Java<->Javascript), but it works.
I never have used this with JFreeChart, but that's how we do it for generating DataMatrix ("2D-Barcode") with an ancient commercial Java library from a company called "ID Automation".
The image item references row["dataMatrix_AuftID"], which is defined as type: Java Object, expression: barcode.dataMatrix(row["AUFT_ID"],70,70,80,0.03)
The function barcode.dataMatrix in our Javascript wrapper library for the Java library calls the Java library. Its last few lines look like this, which should give you an idea for your case:
var image = new java.awt.image.BufferedImage(siz.width, siz.height, t);
// get graphic context of image
var imgGraphics = image.createGraphics();
// paint DataMatrix in graphics context of image
bc.paint(imgGraphics);
// get the image's bytes in PNG format
var baos = new java.io.ByteArrayOutputStream();
javax.imageio.ImageIO.write(image, "png", baos);
var bytes = baos.toByteArray();
return bytes;
As a side-note, for a proof of concept I showed that it is also possible to generate SVG in memory and use it with BIRT. Never used this in production, however.
My application should be able to copy 32-bit images (RGB + alpha channel) to the clipboard and paste these images from the clipboard. For this I plan to use CF_DIBV5 because the BITMAPV5HEADER structure has a field bV5AlphaMask.
The problem is that there doesn't seem to be a consensus as to how exactly the image data should be stored in the clipboard. While doing some tests I found out that there are several differences betweeen the applications making it next to impossible to come up with a general solution.
Here are my observations:
When I copy an alpha channel image from Word 2010 or XnView to the clipboard, it is stored without premultiplying pixel data.
When I copy an image using Firefox or Chrome, however, the pixel data seems to be premultiplied by the alpha channel.
Firefox sets bV5AlphaMask to 0xff000000 whereas most other applications do not set this at all but keep it 0. This is strange because these applications put DIBs onto the clipboard that actually contain an alpha channel in the highest 8 bits but still they set bV5AlphaMask to 0. So one has to make the assumption that if bit depth is 32 that there is an alpha channel even if bV5AlphaMask is 0.
To cut a long story short my basic question is this: Is there some official information as to how alpha channel data should be stored on the clipboard? I'm especially interested to find out whether or not the data must be premultiplied. As you can see above, Word 2010 and XnView do not premultiply, while Firefox and Chrome do. But it is of essential importance to know whether or not the color channels should be premultiplied.
Thanks a lot for shedding some light onto this!
UPDATE 2
Pasting into Paint.NET works fine now. It was caused by a bug in my code which did not set the color channels to 0 if the alpha channel was 0, i.e. the premultiplication wasn't done correctly in this case which seems to have confused Paint.NET.
Still unsolved is the problem with Internet Explorer 10. When copying a PNG with alpha channel to the clipboard, IE 10 just puts a 24-bit CF_DIBV5 on the clipboard but Paint.NET can paste this bitmap WITH alpha channel so there must be another format that IE 10 exposes to the clipboard. Maybe it exposes a PNG uses CFSTR_FILECONTENTS and CFSTR_FILEDESCRIPTOR.
UPDATE
I've now implemented it in the way described by arx below and it works pretty well. However, there are still two things that keep me puzzled:
1) Pasting alpha channel images from my app into Paint.NET doesn't preserve the alpha channel. The image appears opaque in Paint.NET. HOWEVER, pasting from Firefox and Chrome into Paint.NET works perfectly, the alpha channel is preserved! I've dumped the complete DIBV5 and it is identical to my app, but still it works with FF and Chrome but not with my app so there must be something else to it! Firefox and Chrome must be doing something else that my app doesn't do!?
2) The same is true for Internet Explorer 10. Pasting an alpha channel image from IE 10 to my app doesn't work at all... I'm getting a DIB that has a bit depth of 24, i.e. no alpha channel at all. When pasting from IE 10 to Paint.NET, however, the alpha channel is there! So there must be something more to it here as well...
I'm sure there is a right way of storing the alpha in CF_DIBV5, but it really doesn't matter. Applications already handle it inconsistently, so if you want your application to play nicely with others you can't use CF_DIBV5.
I researched copying and pasting transparent bitmaps a while ago. My aim was to successfully paste a transparent bitmap into two versions of Office and GIMP. I looked at several possible formats:
CF_BITMAP
Transparency is always ignored.
CF_DIB
Using 32bpp BI_RGB in the usual 0xAARRGGBB format. GIMP supports this but nothing else does.
CF_DIBV5
GIMP doesn't support this.
"PNG"
Paste supported: GIMP, Word 2000, Excel 2000, Excel 2007 and PowerPoint 2007.
Paste unsupported: Word 2007 and OneNote 2007.
All of these applications successfully export "PNG" if you copy a bitmap.
However, Word and OneNote 2007 will paste a PNG file copied from Explorer. So I came up with the following:
Solution for Copying
Convert your transparent bitmap to PNG format.
Advertise the following clipboard formats:
"PNG" - the raw PNG data.
CF_DIB - for applications (like paint) that don't handle transparency.
CFSTR_FILEDESCRIPTOR - make the PNG look like a file. The file descriptor should have an invented filename with a ".png" extension.
CFSTR_FILECONTENTS - the contents must be exposed as an IStream; just using an HGLOBAL doesn't seem to work. The data is identical to the "PNG" data.
Having done this I could successfully paste transparent bitmaps into GIMP, Office 2000 and Office 2007. You can also paste the PNG directly into an Explorer folder.
Update
I realised that I've only answered half the question. This is great for copying, but no use if you want to paste from an application that only copies CF_DIBV5 (like Firefox).
I'd recommend that you use "PNG" if it's available, otherwise fall back to CF_DIBV5, treating it as premultiplied. This will correctly handle Word 2010 (which exports "PNG"), Firefox and Chrome. XnView only exports non-multiplied CF_DIBV5, so this won't work correctly. I'm not sure you can do any better.
lscf - A Tool for Exploring Clipboard Formats
This is the source of a tool for displaying a list of available clipboard formats. It can also write one to a file. I called it lscf. Create a win32 console application in Visual Studio and paste this source over the main function. It has one very minor bug: it never displays the "Unknown format" error if you mistype a format name.
#include <Windows.h>
#include <stdio.h>
#include <tchar.h>
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
LPCTSTR cfNames[] = {
_T("CF_TEXT"),
_T("CF_BITMAP"),
_T("CF_METAFILEPICT"),
_T("CF_SYLK"),
_T("CF_DIF"),
_T("CF_TIFF"),
_T("CF_OEMTEXT"),
_T("CF_DIB"),
_T("CF_PALETTE"),
_T("CF_PENDATA"),
_T("CF_RIFF"),
_T("CF_WAVE"),
_T("CF_UNICODETEXT"),
_T("CF_ENHMETAFILE"),
_T("CF_HDROP"),
_T("CF_LOCALE"),
_T("CF_DIBV5")
};
int LookupFormat(LPCTSTR name)
{
for (int i = 0; i != ARRAY_SIZE(cfNames); ++i)
{
if (_tcscmp(cfNames[i], name) == 0)
return i + 1;
}
return RegisterClipboardFormat(name);
}
void PrintFormatName(int format)
{
if (!format)
return;
if ((format > 0) && (format <= ARRAY_SIZE(cfNames)))
{
_tprintf(_T("%s\n"), cfNames[format - 1]);
}
else
{
TCHAR buffer[100];
if (GetClipboardFormatName(format, buffer, ARRAY_SIZE(buffer)))
_tprintf(_T("%s\n"), buffer);
else
_tprintf(_T("#%i\n"), format);
}
}
void WriteFormats()
{
int count = 0;
int format = 0;
do
{
format = EnumClipboardFormats(format);
if (format)
{
++count;
PrintFormatName(format);
}
}
while (format != 0);
if (!count)
_tprintf(_T("Clipboard is empty!\n"));
}
void SaveFormat(int format, LPCTSTR filename)
{
HGLOBAL hData = (HGLOBAL)GetClipboardData(format);
LPVOID data = GlobalLock(hData);
HANDLE hFile = CreateFile(filename, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
DWORD bytesWritten;
WriteFile(hFile, data, GlobalSize(hData), &bytesWritten, 0);
CloseHandle(hFile);
}
GlobalUnlock(hData);
}
int _tmain(int argc, _TCHAR* argv[])
{
if (!OpenClipboard(0))
{
_tprintf(_T("Cannot open clipboard\n"));
return 1;
}
if (argc == 1)
{
WriteFormats();
}
else if (argc == 3)
{
int format = LookupFormat(argv[1]);
if (format == 0)
{
_tprintf(_T("Unknown format\n"));
return 1;
}
SaveFormat(format, argv[2]);
}
else
{
_tprintf(_T("lscf\n"));
_tprintf(_T("List available clipboard formats\n\n"));
_tprintf(_T("lscf CF_NAME filename\n"));
_tprintf(_T("Write format CF_NAME to file filename\n\n"));
}
CloseClipboard();
return 0;
}
I was stuck on this problem for a while despite the detailed main answer. It would not seem to preserve alpha (even through a clipboard viewer).
It turns out, the solution is as simple as this:
export CF_DIB (no need for V5) with 32-bit pre-multiplied alpha
and export the "PNG" format
With that, it seemed to be able to paste in all applications I tested (Paint.NET, GIMP, LibreOffice, and so forth).
Essentially, as long as alpha was pre-multiplied, alpha was preserved in CF_DIB in almost every program I used. In a rare one-off case, "PNG" was needed.
To be clear: CF_DIBV5 was not needed.