In Canon SDK sample, how can I take a photo with certain resolution such as 200-300 dpi or change the resolution programmatically, and save the taken photo in another file type, here I need to save in .TIF format? I can't find any function to do it.
author of the article here.
you can change the image resolution by setting the PropID_ImageQuality with one of the ImageQuality enums. Note that not every camera supports every enum value and the actual image resolution depends on the camera and sensor. If you need a pixel-exact image you'll have to resize it yourself.
Also, the image you download from the camera is not modified by the SDK so you can only get the image format that the camera has, usually CR2 and/or Jpg.
To get a tif from a raw file you can use the SDKs image methods. To create a raw image use the EdsCreateImageRef method and to save it use the EdsSaveImage method. As a target you can use EdsTargetImageType.TIFF (or TIFF16 for 16bit per channel).
EDIT:
quick sample for saving an image to tiff (not tested):
IntPtr imgRef;
//Open image
IntPtr inStream;
EDSDK.EdsCreateFileStream("inFile.cr2", EdsFileCreateDisposition.OpenExisting, FileAccess.Read, out inStream);
EDSDK.EdsCreateImageRef(inStream, out imgRef);
EDSDK.EdsRelease(inStream);
//do whatever you like with imgRef now
//Save image
IntPtr outStream;
var settings = new EdsSaveImageSetting();
EDSDK.EdsCreateFileStream("outFile.tif", EdsFileCreateDisposition.CreateAlways, EdsFileAccess.Write, out outStream);
EDSDK.EdsSaveImage(imgRef, EdsTargetImageType.TIFF, settings, outStream);
EDSDK.EdsRelease(outStream);
To get a TIFF image, shoot in RAW format and after downloading the image use the EdsSaveImage function with the EdsTargetImageType set to kEdsTargetImageType_TIFF. The DPI resolution is not relevant directly, but you can always use tools like Exiftool to set the DPI explicitly.
Related
I've written a program that can create digital art. Images like the Mandelbrot Set and the Julia Set. But I'm looking to save these images as PNGs. At present, in Java, I'm generating the images in an application window and then taking a screen shot of the display. However, I lose the finer detail of these images. Plus, this method also reduces the physical size of the images as well. I want to potentially be able to make a big poster out of these pictures.
In C#, I'm using the following:
Bitmap myimage = new Bitmap("image.png"); and: myimage.SetPixel(x,y, Color.FromArgb(255*colors[x,y], 255*colors[x,y], 255*colors[x,y]); where colors[,] is some value between 0 and 1.
The code runs fine, minus the Bitmap declaration. My understanding is that new Bitmap(filepath); allows you to edit and manipulate the PNG image. Am I right to think that? How do I create/edit a PNG file in C#?
(edit)PS: The PNG file, "image.png", does exist in the solution folder.
Firstly you have to know the step by step process in creating the PNG file.
Setup Aspose.Imaging for .NET package from Nuget.org.
Include reference to following two namespaces: Aspose.Imaging,
Aspose.Imaging.ImageOptions.
Specify license using SetLicense method before converting.
Read BMP file into an Image object.
Set attributes for output PNG image using PngOptions class.
Save the output PNG image with the specified PNG options.
Code to create PNG image from BMP
using System;
//Use following namespaces to create PNG image
using Aspose.Imaging;
using Aspose.Imaging.ImageOptions;
namespace CreatePNGImage
{
class Program
{
static void Main(string[] args)
{
//Set license before creating PNG image from BMP
Aspose.Imaging.License AsposeImagingLicense = new Aspose.Imaging.License();
AsposeImagingLicense.SetLicense(#"c:\asposelicense\license.lic");
//load input BMP image
Image BmpToPngImage = Image.Load("InputBMPImage.bmp");
//set attributes of the output PNG file
PngOptions PNGImageOptions = new PngOptions();
PNGImageOptions.ResolutionSettings = new ResolutionSetting(300, 300);
PNGImageOptions.CompressionLevel = 6;
//save converted output PNG image
BmpToPngImage.Save("OutputPNGImage.png", PNGImageOptions);
}
}
}
Try this to create the PNG file out of c#.
I have used the sample code as found in the answer at how to create an animated gif in .net
ie
System.Windows.Media.Imaging.GifBitmapEncoder gEnc = new GifBitmapEncoder();
foreach (System.Drawing.Bitmap bmpImage in images)
{
var src = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
bmpImage.GetHbitmap(),
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
gEnc.Frames.Add(BitmapFrame.Create(src));
}
using(FileStream fs = new FileStream(path, FileMode.Create))
{
gEnc.Save(fs);
}
I would now like to set the speed of the animate gif. The help in this area is terrible. Anyone got any idea of how to do it? This must surely be possible. It seems to be such a basic function of an animated gif but they seem to have gone out of their way to make it difficult.
Thanks in advance.
I don't think you can do it with GifBitmapEncoder. Theoretically, you could use BitmapMetadata.SetQuery to set the value of /grctlext/Delay on each frame (the delay is specified in the Graphic Control Extension of each frame, as explained in the Wikipedia article). But the doc says:
Graphics Interchange Format (GIF) images do not support global
preview, global thumbnails, global metadata, frame level thumbnails,
or frame level metadata.
Which is technically incorrect, because the GIF format itself does support global and frame-level metadata; it's just the GifBitmapEncoder class that doesn't support it.
So I think your only options are to use another, more complete image manipulation library, or to do it manually. The GIF format is rather simple; it's described in details on this site, including the parts about animation and LZW compression.
Alternatively, instead of doing the whole encoding yourself, you could use GifBitmapEncoder to do the heavy lifting, and just patch the metadata in the resuting stream afterwards. The code in my XamlAnimatedGif library might help; you won't be able to use it directly, but you could reuse some parts of it, as it implements a full GIF decoder.
I have a Windows Store app written in C# that works with photos. I want to show the last photo the user selected in the app in the medium size live tile (150 x 150). I am using the code below to do it. When I run the app I don't get any errors, but I don't see the selected photo in the live tile either. I know that I am doing at least some things right. I say this because if the user hasn't selected a photo yet, then I show a test image and I do see that image in the tile. But the test image comes from the app package using the ms-appx protocol, not from the app storage area.
I found a few SO posts on the subject but they are all for Windows Phone. I looked at the KnownFolders list for Windows Store app files, but nothing seemed to map to the SharedContent folder required for files meant for live tile use in Windows Phone. What is wrong with my code?
Note, the vvm.ActiveVideomark.GetThumbnail() call simply retrieves a bitmap as a WriteableBitmap object. As you can see in the code, I am resizing the image to the size required by the Medium live tile (150 x 150). ToJpegFileAsync() is an extension method that encodes a WriteableBitmap object to jpeg bytes and then writes those bytes to a file using the given file name. Both of these calls are well-tested and are not the source of the problem as far as I know.
TileUpdateManager.CreateTileUpdaterForApplication().Clear();
TileUpdateManager.CreateTileUpdaterForApplication().EnableNotificationQueue(true);
var tileXml = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquare150x150Image);
var tileImage = tileXml.GetElementsByTagName("image")[0] as XmlElement;
// Got a current photo?
if (vvm.ActiveVideomark == null)
// No, just show the regular logo image.
tileImage.SetAttribute("src", "ms-appx:///Assets/Logo.scale-100.png");
else
{
// Resize it to the correct size.
WriteableBitmap wbm = await vvm.ActiveVideomark.GetThumbnail();
WriteableBitmap wbm2 = wbm.Resize(150, 150, WriteableBitmapExtensions.Interpolation.Bilinear);
// Write it to a file so we can pass it to the Live Tile.
string jpegFilename = "LiveTile1.jpg";
StorageFile jpegFile = await wbm2.ToJpegFileAsync(jpegFilename);
// Yes, show the selected image.
tileImage.SetAttribute("src", jpegFile.Path);
}
The src attribute must contain a URI with ms-appx:///, ms-appdata:///local, or http[s]:// schemes. The StorageFile.Path property, as you're using with jpegFile.Path, is a local filesystem pathmame like c:\users\Robert\AppData... which won't be valid. So create your tile images in local app data, and then use ms-appdata:///local/ to refer to them in tile payloads.
I am still very much learning ASP.NET using c# and Webmatrix. I have put together a photography competition site but can't quite find an ideal way of uploading images. I don't see the point of uploading images greater than 1200x900 (projectors maximum resolution) so want to make sure images are small as possible.
I am using tag and checking he image size. If it's too big I am using 'ImageResizer' to resize the image when saving. The only way I know to check the size is to convert the 'HttpPostedFileBase' file into an image using System.Drawing.Image. But when the image is 36Mpixels (it is a photography club) this is taking an age just to read the height and width properties. Can I just load the first x bytes to read the properties or do I have to read the whole image?
The second reason I am converting to an image is to extract the exif data. Again is there an easier and quicker way to read the exif data?
I hope my question makes sense this is all a bit new to me.
simplified code:
HttpPostedFileBase uploadedFile = Request.Files[0];
using (System.Drawing.Image image = System.Drawing.Image.FromStream(uploadedFile.InputStream, true, true))
{
string Exif;
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
try{
Exif = encoding.GetString(image.GetPropertyItem(36867).Value);
}
catch
{
Exif="";
}
if (image.Width <Convert.ToInt32(MaxWidth) && image.Height <Convert.ToInt32(MaxHeight))
{
// SAVE IMAGE AS IS
image.Save(fileSavePath);
// LOAD IMAGE DETAILS WITH EXIF
db.Execute("INSERT INTO CompImages (ImageTitle,CompID,GroupID,ClubID,FileName,UserID,ExifDate) VALUES(#0,#1,#2,#3,#4,#5,#6)",ImageTitle,CompID,GroupID,ClubID,fileName,WebSecurity.CurrentUserId,DateTaken);
}
else
{
// LOAD IMAGE DETAILS WITH EXIF
db.Execute("INSERT INTO CompImages (ImageTitle,CompID,GroupID,ClubID,FileName,UserID,ExifDate) VALUES(#0,#1,#2,#3,#4,#5,#6)",ImageTitle,CompID,GroupID,ClubID,fileName,WebSecurity.CurrentUserId,DateTaken);
// RESIZE IMAGE
ImageResizer.ImageJob iF = new ImageResizer.ImageJob(image, "~/UpImages/"+CompID+"/"+fileName, new ImageResizer.ResizeSettings(
"width="+MaxWidth+";height="+MaxHeight+";format=jpg;mode=max"));
iF.CreateParentDirectory = true; //Auto-create the uploads directory.
iF.Build();
}
}
The only way I know to check the size is to convert the
'HttpPostedFileBase' file into an image using System.Drawing.Image.
You could also checkout the ContentLength property directly:
int uploadedFileSize = uploadedFile.ContentLength;
The second reason I am converting to an image is to extract the exif
data. Again is there an easier and quicker way to read the exif data?
I am not aware of a built-in class in the BCL that would allow you to read EXIF information without loading the image in memory but you could use some third party library like this one: http://www.codeproject.com/Articles/36342/ExifLib-A-Fast-Exif-Data-Extractor-for-NET-2-0
I'm currently converting some legacy code to create PDF files using iTextSharp. We're creating a largish PDF file that contains a number of images, which I'm inserting like so:
Document doc = new Document(PageSize.A4, 50, 50, 25, 25);
PdfWriter writer = PdfWriter.GetInstance(doc, myStream);
writer.SetFullCompression();
doc.Open();
Image frontCover = iTextSharp.text.Image.GetInstance(#"C:\MyImage.png");
//Scale down from a 96 dpi image to standard itextsharp 72 dpi
frontCover.ScalePercent(75f);
frontCover.SetAbsolutePosition(0, 0);
doc.Add(frontCover);
doc.Close();
Inserting an image (20.8 KB png file) seems to increase the PDF file size by nearly 100 KB.
Is there a way of compressing the image before entry (bearing in mind that this needs to be of reasonable print quality), or of further compressing the entire PDF? Am I even performing any compression in the above example?
The answer appears to have been that you need to set an appropriate version of the PDF spec to target and then set the compression as follows:
PdfWriter writer = PdfWriter.GetInstance(doc, ms);
PdfContentByte contentPlacer;
writer.SetPdfVersion(PdfWriter.PDF_VERSION_1_5);
writer.CompressionLevel = PdfStream.BEST_COMPRESSION;
This has brought my file size down considerably. I also found that PNG's were giving me the best results as regards to final size of document.
I did some experiments this morning. My test image was 800x600 with a file size of 100.69K when saved as a PNG. I inserted this into a PDF (using iTextSharp and the usual GetInstance() method) and the file size increased from 301.71K to 402.63K. I then re-saved my test image as a raw bitmap with file size of 1,440,054. I inserted this into the PDF and the file size went DOWN to 389.81K. Interesting!
I did some research on the web for a possible explanation, and, based on what I found, it looks like iTextSharp does not compress images, but rather it compresses everything with some generic compression. So in other words, the BMP is not actually converted to another file type, it's just compressed very much like you would by ZIPping it. Whatever they're doing, it must be good, for it compressed better than the image with PNG compression. I assume iTextSharp woudld try to compress the PNG but would compress at 0% since it already is compressed. (This is inconsistent with the original author's observations, though... Paddy said his PDF size increased much more than the size of the PNG... not sure what to make of that. I can only go on my own experiments).
Conclusions:
1) I don't need to add some fancy library to my project to convert my (eventual dynamically-created) image to PNG; it actually does better to leave it totally uncompressed and let iTextSharp do all the compression work.
2) I also read stuff on the web about iTextSharp saving images at a certain DPI. I did NOT see this problem... I used ScalePercent() method to scale the bitmap to 1% and the file size was the same and there was no "loss" in the bitmap pixels in the bitmap... this confirms that iTextSharp is doing a simple, nice, generic lossless compression.
It seems that PDF requires the png to be transcoded to something else, jpeg, most probably.
see here: http://forums.adobe.com/message/2952201
The only thing I can think of is to convert png to smallest jpeg first, including scaling down 75%, then importing that file without scaling.
use:
var image = iTextSharp.text.Image.GetInstance(srcImage, ImageFormat.Jpeg);
image.ScaleToFit(document.PageSize.Width, document.PageSize.Height);
//image.ScalePercent(75f);
image.SetAbsolutePosition(0, 0);
document.Add(image);
document.NewPage();