In my application the user can create multiple objects (so called drawings) each of which has a SurfaceInkCanvas, very similar with the Photopad (the Photo Paint app)in the SDKSamples(provided by MS Surface SP1 SDK).
What would be the best way to save the content of the inkCanvas(the drawing object) given the fact that there may be tens or even hundreds of them created.
After some research, one option popped-out: converting it to an image, jpg or png, but this method doesn't seem that scalable IMO.
Would it be possible to store the points in a database(preferably sqlite)?
The goal is to be able to restore the drawings(contents of the inkCanvas) for further editing upon loading.
Saving to an image isn't really viable for what it sounds like you want to do because restoring vector lines from a bitmap is much harder and potentially lossy than the vector to bitmap conversion, in addition to not being very efficient from a data density perspective.
You could write some code to save and restore the collection of lines that's stored in the Strokes property. This would allow you to reduce the size of your data down to a minimum and easily store in a database. Each Stroke has some data about what the line looks like and a set of points that make up the line. It's fairly simple to extract and restore that data to another InkCanvas when reloading.
You might also be able to use XamlWriter/XamlReader to just serialize the entire InkCanvas to xml but you would need to be able to put the new deserialized instance into your UI and make sure there aren't any naming or resource complications in your XAML that tend to cause errors with this method.
there's already a format that microsoft uses to save the strokes in, which is ISF - standing for Ink Serialized format that saves the Strokes collection in an .isf file.
However in this example each drawing is saved in a separate (but small-size) .isf file that can be easily loaded back for further editing or even converting (exporting) it to bitmap.
So a good method would be to save each drawing in files(even though this is a bit more expensive, time-wise, than simply storing it in a sqlite db)and save the path of each along with an id in the database to identify each session.
Any suggestion for further optimising this method from a scalability point of view?
Related
I have been searching for help with this for a long time. If it's been answered here already, I cannot find it. I'm using C# on a Windows Form.
I'm trying to create a simple program that allows me to open a PDF, flatten any layers within it, and then, for each click of the mouse, draw a circle.
Centered within each circle I need to have a number, beginning with "1", and chronologically increasing to infinity (could be 1, could be 15000).
Finally, I need to be able to save, and print the final result.
There are other things I need to add, but if someone can get me started with this, I should be able to figure out the rest on my own.
I've been able to import the .pdf. However, any tut I've found for creating a transparent layer on which to draw, never allows me to see the pdf behind. Do I even need this transparent layer, or can I draw directly on the pdf? My second biggest issue figuring out is how to create the circle, with the chronologically increasing number anywhere I choose to click my mouse.
Thanks in advance for any help.
Please see the image below for what it should look like.
You can do that with Atalasoft's DotImage/DotPdf/DotAnnotate packages (disclaimer: I used to work on these products up until 3 years ago). There are a number of ways to do this. If you don't care the markup being an annotation, you can make an annotation with a custom appearance and add each one to the document.
If you care that the numbers get added to the document, you can use DotPdf directly to append content to the content stream of any page.
How to do this on your own. Good luck (seriously - this is not an easy problem to solve).
Here's what you need to be able to do first (at a minimum) for putting new content into an existing page:
First, let's talk about the PDF rendering model:
PDF uses a little non-Turing complete RPN language to place content on the page. A given page has one or more streams of code which gets executed in order to render a page. If you want add content on top, you need to render it last (there are other more complicated ways to do this, but this is good enough). That means you either append to the existing content stream (wouldn't recommend), or you take advantage of the fact that a PDF page can have any number of content streams on it. You make a new stream and add in the code to render the content that you want.
I'll warn you ahead of time that rendering text is non-trivial, especially if you have to embed fonts or use unicode encoding. I'll also warn you that there is no "circle" primitive in PDF. You have to approximate it with Bezier curves.
I'm studious in my laziness, so I created abstractions to make it easier to correctly create content streams. For example, I make a class called a drawing surface and I could tell it "set the drawing style to this" "place a 'shape' here" "draw text here" and so on. When it was told to render, it would generate the PDF rendering program that matched. On top of this, I had another abstraction that consisted of a drawing list of higher level objects and the drawing list, when rendered would write to the drawing surface which would in turn write PDF.
Append changes (generations) to a PDF
Create Content streams
Append a replacement page object for an existing page with the Contents changed from a Stream to an array (or if it's an array already, append to it) and with new resources added to the Resource dictionary
Here's what you need to be able to do first (at a minimum) for putting annotations on an existing page:
Append changes (generations) to a PDF
Append a replacement page object for an existing page with the Annots added with new annotations (or modified by inserting/appending new annotations)
Create appearance streams
Create annotations with using the custom appearance streams
As far as how to do the UI, that's oddly straight forward as long as you have a PDF renderer. Render a page into an image and make a control that gives you a mouse click onto the page. Then build a transformation matrix that goes from image coordinates to PDF page coordinates and push the mouse coordinates through that matrix. The result will be the origin of your mark up on the page (be aware that some pages are rotated and you will need to adjust your transformation matrix to match).
Now, to be clear, when I wrote this library for Atalasoft, I already had several years of PDF experience (I worked on Acrobat v 1 - 4). While I wasn't working on the library full time, it was written over the span of 10 years. The code to append to an existing PDF took several months of time to get right. Eventually, I shed that code because of complications in appending anything but simple changes (like annotations) and wrote code that could rewrite an entire PDF with updates to existing content (page reordering, annotations, bookmarks, new content on a page, edited images, etc), while simultaneously shedding anything that is no longer needed. This is akin to adding in and clipping out sections of a directed graph with cycles and being able to ensure that you have a correct graph on the other end.
The hard part wasn't working within the specification - that's fairly straightforward for me. The problem was dealing with cockamamie PDF generated by other tools that had all kinds of bizarro spec violations and handling that correctly.
Now, I'm not saying don't do this. I'm all for people learning new things and learning about PDF. There's a lot there to learn and a lot of interesting ideas, but you need to be aware that simple sounding problems in PDF space aren't trivial unless you have a great deal of infrastructure in place. For example, "how many pages are in a PDF?" requires a PDF scanner and code to execute or parse PDF content so you can read in the cross reference table (which may be a compressed cross reference stream), the document dictionary (which may include encryption), and finally the page tree: all which can be easily derailed by non-compliant PDF.
If you're trying to balance time and cost, remember that your time is far from free and maybe a library to do the heavy lifting is not a bad thing. iTextPdf is open source and can do all of the things you need to do, but it will cost you in time to learn the library, but that's a huge savings over having to write PDF tools on your own. Atalasoft's code is not free, but was written to have a much shallower learning curve than most libraries.
Basically, I have a bunch of images that I can combine into a single image(an atlas) or use individually. For testing/designing purposes, I would like to keep all the images separate but for release they should all be combine into the atlas(for non-embeddable compilers) or embedded.
e.g., suppose I have 100 sprites. I can create a single atlas for them, use them all individually unembedded, or embed the atlas, or embed all the image.
I'd like to start out with the individual+unembedded case for development then move to the embedded atlas case or embedded individual case(but I think this is probably not as good as the embedded atlas).
Is there an easy way to set this up in C# so the transition will be minimal?
The problem with the embedded atlas is that I would have to convert loading images(simple Image.FromFile into extracting images from the atlas).
Just curious what would be a good approach to remove the need for rewriting a lot of code in the future when the switch is made.
I could have something like Image.FromAtlas that essentially figures out the details(uses FromFile if we are in "development mode" or extracts the image from the atlas if in production... I think the embedded case would be rather trivial to implement).
What do you think? Thanks.
Through prior research, I've found that is isn't too hard to set the MetaData properties on an image. For example, I can read a JPEG image into a Bitmap object and change its "Original Taken" date through the image's SetPropertyItem method (I've already researched the format and enumeration for doing this, too).
However, although the actual MetaData part seems easy, I am faced with a couple of irritating implementation issues:
1) When I call Save() on the bitmap, it doesn't seem that the image's original encoding settings are used. As a result, the compression level changes (presumably to some default value); I can see the file size shrink considerably after my Save() call. I know that you can customize the encoding settings for an image within the call to Save(), but honestly, I only want to change the picture's metadata; isn't there any easy way to just save the image using its original encoding settings? Even if I could directly reference the image's existing encoding settings in the Save() call, that would help.
2) Apparently, the original file is locked when you read it into a Bitmap object. As a result, I can't save the image under its original file name without a lot of messing around: currently, I'm drawing the image I read from file onto an offscreen bitmap, disposing of the original image, and then saving the offscreen bitmap. Again, this seems like an awful lot of extra work when all I want to do is update the metadata in an image file.
Any suggestions you can offer would be most appreciated... the amount of work I'm having to do just to update a JPEG file's meta data (most of which has nothing to do with the actual metadata change) leads me to wonder if I'm missing some easier or better ways of doing this.
What you want to do is edit the EXIF data. What you are doing now is recompressing the image, and this will cause quality loss, as you have noticed.
See this code sample for editing EXIF: http://www.dreamincode.net/code/snippet3144.htm
I have a winforms image list which contains say like 200 images 256x256.
I use the method Images.FromFile to load the images and then add them to the image list.
According to ANTS .NET profiler, half of the program's time is spent in Images.FromFile. Is there a better way to load an image to add to an image list?
Another thing that might be optimized is, the images that are loaded are larger than 256x256. So is there a way to load them by resizing them first or something? I just want to uniform scale them if they their height is larger than 256 pixels.
Any idea to optimize this?
EDIT: They are JPEGs.
You don't say how much bigger than 256x256 the images actually are - modern digital cameras images are much bigger than this.
Disk I/O can be very slow, and I would suggest you first get a rough idea how many megabytes of data you're actually reading.
Then you can decide if there's a subtle 'Image.FromFile' problem or a simple 'this is how slow my computer/drives/anti-virus scanner/network actually is' problem.
A simple test of the basic file I/O performance would be do to File.ReadAllBytes() for each image instead of Image.FromFile() - that will tell you what proportion of the time was spent with the disk and what with the image handling - I suspect you'll find it's largely disk, at which point your only chance to speed it up might be one of the techniques for getting JFIF thumbnails out of files. Or perhaps one can imagine clever stuff with partial reads of progressive JPEGs, though I don't know if anyone does that, nor if your files are progressive (they're probably not).
I don't really know how fast you need these to load, but if the problem is that an interactive application is hanging while you load the files, then think of ways to make that better for the user - perhaps use a BackgroundWorker to load them asynchronously, perhaps sort the images by ascending file-size and load the small ones first for a better subjective performance.
If you are trying to make thumbnails then try this code here it will let you extract thumbnails without completely loading the image.
You can use FreeImage.NET which is great for loading images on background.
The Image.FromFile contains hidden Mutex which locks your app if you are try to load large images even on background thread.
As for the JPEGs, the FreeImage library uses OpenJPEG library which can load JPEG images in smaller scale more quickly. It can also utilize embedded thumbnails.
The WPF classes also allow loading images in smaller resolution, but this cannot be used if you are restricted to WinForms.
If you want speed then prescale your images, don't do it in runtime.
You didn't mention want type of images you loading (jpeg, png, gif, bmp) of course that bmp is the fastest one since it has not (or almost no) compression.
Are your images 256 colors (8 bit w/ palette), bmp, gif and png support that format that can load pretty fast.
It sounds like you need some sort of image thumbnails? Don't forget that jpeg images already contains thumbnails inside, so you can extract only this small image and you do not need to scale. Such images however smaller than 256x256.
Another option is to move loading logic into separate thread, it will not be faster, but from users perspective it can look as significant speedup.
I have a winforms image list
I would avoid using ImageList in this scenario. Internally, it is an old Windows common control intended for working with GUI icons, usually 32x32 pixels or less.
Another thing that might be optimized is, the images that are loaded are larger than 256x256.
Be aware that GDI+ is not optimized for working with very large bitmaps of the kind that you would normally edit using photo software. Photo editing software packages generally have sophisticated algorithms that divide the image into smaller parts, swap parts to and from disk as needed to efficiently utilize memory, and so on.
Resizing an image is CPU intensive, especially when using a good quality interpolation algorithm. Take a cue from how Windows Explorer does this -- it saves the thumbnails to a file on disk for future access, and it does the processing in the background to avoid monopolizing the system.
This might be too late but using ImageLocation property will do two things
speed up image loading
work around the bug (Image file is locked when you set the PictureBox Image property to a file)
pictureBox1.ImageLocation = "image.jpg";
pictureBox1 .SizeMode = PictureBoxSizeMode.StretchImage;
Got a question. I have images hosted on my server. I already know of the method when an image is uploaded to resize it and save, but I have another thought in mind.
I was wondering if there is a way to resize when the image is requested from the user. Not when it was uploaded by the user.
So for example a user goes to upload an image and I DO NOT RESIZE it and save another copy of the resized image. Instead, when the image is requested by the user via an ASP.NET img control/tag it would resize the image on the fly to display it and display it via the img tag/control.
Why would I want to do this?
To save on disk space. Most servers have a disk space limit, but not a server processing limit. So I would like to save on disk space and use the processing space instead.
EDIT: As a startup website its currently better that I save disk than saving processing time. I don't have much money for large amount of space at this moment. Hopefully it will change when the site launches.
Any ideas? Thanks guys and girls.
I assume you can 'control' the urls to the resized images, so for example the full-sized image might be referenced as <img src="uploads/myphoto.jpg"/> the thumbnail could be to an ASPX or ASHX like <img src="uploads/myphoto.jpg.ashx"/>?
This article on CodeProject - Dynamic Image Resize seems to have exactly the source code you are looking for (and although it's in VB, it shouldn't be hard to port if you're a C# person). Hope that helps.
Finally, I'd encourage you consider the various forms of caching (both using Http-Headers, to ensure the images are cached at the client or proxy whenever possible; and using built-in ASP.NET features to avoid unnecessary processing of the same images over-and-over).
Although you'll be saving disk-quota, you're effectively slowing down every other page/request... just a thought.
Dynamic image resizing has numerous advantages, the least of which is reduced disk space usage. However, it does need to be combined with a form of persistent caching, such as either Amazon CloudFront or a disk cache.
Dynamic image resizing gives you great agility on your web site, whereas pre-generating image variants locks you in, preventing the eventual changes you will have to make. When combined with caching, there is no run-time performance difference between the two.
The ImageResizer library offers disk caching, CloudFront caching, and correct memory and cache management. It's been constantly improved and maintained since 2007, and is quite bulletproof. It's running a few social networking sites as well, some having over a million images.
It's a time-tested, traffic-tested, and unit-tested library :) It's also extremely simple to use - you just add ?width=x&height=y to the query string. Functionality can be added via 20+ plugins, so you won't be weighed down by unused code and features.
The article mentioned by CraigD is inherently limited in its performance by the fact that it uses an HttpHandler instead of using an HttpModule - an HttpHandler cannot pass a request back to IIS native code for execution after the resized image is written to disk. It also doesn't adjust jpeg encoding properly or play well with the ASP.NET cache or URL authorization system. Although, I do have to admit - compared to most of the sample code I've seen, it violates far fewer of the image resizing pitfalls I've compiled.
I strongly suggest using the ImageResizer library. It's good code, I wrote it :) If you do end up using sample code or writing your own, please avoid these pitfalls!
You can create an implementation of IHttpHandler to respond to image requests, in that handler you can have code that loads the image from disk and transforms to it a size that is needed. You need to return the proper mime type with the response, and use the WriteBytes method (or something like it, I forgot the name). Also, you may look into content expiration headers, so that the image may not have to be loaded every time by the same client, but is instead cached.
You claim unlimited processing but limited disk space. Most of the time, even if they don't enforce a processing limit, as you have more customers, hits to your site, processing will be a worse bottleneck than storage space, and it will cost more to add more processing. Furthermore,
If you have large images, resized and compressed versions will occupy %10 of the space of the originals, even if you store a display and thumbnail version.
Else, just serve them and display them resized by browser, it will be faster.
It is not really actual resize of image, it is rather resize when you display an image, but i used with success just simple
<img src="myimage" height="height you want to give" width="width you want
to give" alt="" />
It is working every time.