Loading images (graphics) with VisualWorks very slow - smalltalk

I am trying to load image files like jpeg into vw as part of an application. This seems to take very long and sometimes even crashes vw. The image has roughly 3.5MB and is a simple jpeg picture. This is what causes the problem:
ImageReader fromFile:'pic.jpg'.
This operation takes about 5-10 seconds to complete. It happens in both 32 and 64 bit projects alike.
Any ideas or suggestions as to how I can solve this problem? Same thing in pharo seems to work okay.
Thanks!

ImageReader will automatically choose the correct subclass, like JPEGImageReader. Picking the subclass is not the slow part; decoding the JPG data is.
A jpeg file, unlike PNG doesn't use zip compression but instead uses discrete-cosine-transforms (see https://en.wikipedia.org/wiki/JPG#JPEG_compression). This compression requires a lot of number crunching, which is slower in VisualWorks than it would be in C. The PNG reader on the other hand uses Zlib to have the number-crunching part done in C, which is why it is so much faster.
You could use Cairo or GDI or whatever other C-API you have at hand to speed this up.

Try calling the JPEGImageReader directly:
JPEGImageReader fromFile:'pic.jpg'
If that's fast, then the slowdown is in finding the proper image reader to use for the file. What ImageReaders do you have installed and how do they implement the class method canRead:?
If the JPEGImageReader is still slow, then we can investigate from there.

Related

Change Ghostscript dithering method when converting pdf to 256 color BMP

I am trying to produce some high quality 8bpp bmp from pdf file with ghostscript. For that purpose, I use the bmp256 device.
So far, everything works well and is really fast, but ghostscript use halftoning to dither the image, leading to some uggly patterns when zooming on the picture :
I've managed to reduce their size by playing with the -dDITHERPPI flag, but this is still not satisfying enough. Those are too regular and are too easily spotted, even with little zoom.
Instead of using halftone, I would like to use some error diffusion algorithm, like the Floyd–Steinberg one. I found this algorithm is implemented on other devices, but they are all printer related devices, so I can't really use them.
Plus, I need to be as fast as possible when converting the PDF to 8bpp BMP, and the outputed pictures are very large: so converting it to 24 or 32bpp BMP in the first place to dither it later with another tool is excluded.
I already downloaded the source to try to implement it myself, but the project is really big and complex and I don't know how and where to start.
Is there any way to use some error diffusion algorithm with ghostscript without having to implement it myself ?
If no, is there a prefered way for extending ghostscript ? Any guideline ?

How to remove everything except bitmaps from a PDF?

In How can I remove all images from a PDF?, Kurt Pfeifle gave a piece of PostScript code (by courtesy of Chris Liddell) to filter out all bitmaps from a PDF, using GhostScript.
This works like a charm; however, I'm also interested in the companion task of removing everything except bitmaps from the PDF, and without recompressing bitmaps. Or, eventually, separating the vector and bitmap "layers." (I know, this is not what a layer is in PDF terminology.)
AFAIU, Kurt's filter works by sending all bitmaps to a null device, while leaving everything else to pdfwrite. I read that it is possible to use different devices with GS, so my hope is that it is possible to send everything to a fake/null device by default, and only switch to pdfwrite for those images which are captured by the filter. But unfortunately I'm completely unable to translate such a thing into PostScript code.
Can anyone help, or at least tell me if this approach might be doomed to fail?
Its possible, but its a large amount of work.
You can't start with the nulldevice and push the pdfwrite device as needed, that simply won't work because the pdfwrite device will write out the accumulated PDF file as soon as you unload it. Reloadng it will start a new PDF file.
Also, you need the same instance of the pdfwrite device for all the code, so you can't load the pdfwrite device, load the nulldevice, then load the pdfwrite device again only for the bits you want. Which means the only approach which (currently) works is the one which Chris wrote. You need to load pdfwrite and push the null device into place whenever you want to silently consume an operation.
Just 'images' is quite a limited amount of change, because there aren't that many operators which deal with images.
In order to remove everything except images however, there are a lot of operators. You need to override; stroke, fill, eofill, rectstroke, rectfill, ustroke, ufill, ueofill, shfill, show, ashow, widthshow, awidthshow, xshow, xyshow, yshow, glyphshow, cshow and kshow. I might have missed a few operators but those are the basics at least.
Note that the code Chris originally posted did actually filter various types of objects, not just images, you can find his code here:
http://www.ghostscript.com/~chrisl/filter-obs.ps
Please be aware this is unsupported example code only.

Huge images in iOS app without CATiledLayer?

I have an image at about 7000x6000px. I need this to be in a scrollview/imageView in my app, however this is way to huge for display. It is supposed to be a kind of map. I was hoping to keep the size of the app to the minimum, and the image is just about 13mb in .jpg. In .png it is over 100mb, which is unacceptable. Many have suggested CATiledLayer as an option, but I believe this would result in even bigger file sizes. Anyway, I tried to do it with CATiledLayer, and create my own tiles in TileCutter, (tiles in .jpg), and the size wasn't too bad. But I am having errors all over the place. The iOS version of CATiledLayer is a mystery to me, and I can't find a way to solve this. I get an error saying something about the java-equivalent "index out of bounds of array", even though the array has content at that specific index..
It has a method which returns an array. The array contains data of a .plist. Before the return I log out the content of the array, giving me good data. The call is trying to access
[array objectAtIndex:0]
and put it in a dictionary, but throws OutOfBounds. When logged out the whole array, I can clearly see the content, but when logged out
NSLog("%#",[method objectAtIndex]); I get the same exception.
Anyway, CATiledLayer has given me nothing but problems. I have been reverse-engineering the PhotoScroller project with no luck. Anyone have any other solutions?
Thanks.
Apple has this really neat project, PhotoScroller, that uses CATiledLayer and lets you scroll through several images and zoom them. This seemed really neat until I found out that Apple "cheated" and pre-tiled the images (about 800 tiles saved as file in the bundle!)
I had need for a similar capability, but had to download the images from the network. Thus came about PhotoScrollerNetwork. With the TiledImageBuilder you can download (or read from disk) massive images - I even tested a 18000x18000 image - and it works.
What this class does is start tiling the image as it downloads (when using libjpegturbo) or can save the file then tile (takes longer). The class figures out how many levels of detail are needed to show the image at full resolution and sized to fit in the containing view (a scrollview).
The class uses the disk cache to hold the tiles, but uses and old Unix trick of creating a file, opening it, then unlinking it so that the tiles never really get saved - once the class is dealloced (and the file descriptor closed) the tiles are freed (or if your app crashes they get freed too.
Someone had problems on an iPad 1 with its quite limited memory, so the class now throttles its use of the file system when concurrently loading multiple images. I had a discussion with the iOS kernel manager at WWDC this year, and after explaining the throttling technique to him, he said the algorithm (on managing the amount of disk cache usage) was probably the best technique that could be used.
I think those who suggested CATiledLayer are right. You should really use it! If you need a sample project that displays a huge bitmap using that technology, look here: http://www.cimgf.com/2011/03/01/subduing-catiledlayer/
Many technologies we use as Cocoa/Cocoa Touch developers stand
untouched by the faint of heart because often we simply don’t
understand them and employing them can seem a daunting task. One of
those technologies is found in Core Animation and is referred to as
the CATiledLayer. It seems like a magical sort of technology because
so much of its implementation is a bit of a black box and this fact
contributes to it being misunderstood. CATiledLayer simply provides a
way to draw very large images without incurring a severe memory hit.
This is important no matter where you’re deploying, but it especially
matters on iOS devices as memory is precious and when the OS tells you
to free up memory, you better be able to do so or your app will be
brought down. This blog post is intended to demonstrate that
CATiledLayer works as advertised and implementing it is not as hard as
it may have once seemed.

Does CGBitmapContextCreate() have a size limit?

I want to make an extremely large bitmap (250,000 pixels on each side, to be eventually written out as BigTIFF). I don't see a memory size or dimensional limit anywhere in the docs, can Core Graphics handle it?
CG is not designed for that kind of workload.
(I'd be surprised if you found any general-purpose graphics framework that is, frankly. If you're pushing images that big, you're going to have to write your own code to get anything done in a reasonable amount of time.)
In my experience, images started to fail once dimensions got over 32767 or so. Not in any organized way, just crashes and hard-to-repro failures; certain parts of the API would work, others wouldn't. Things may be better in 64-bit but I wouldn't count on it.

A batch PNG processor for windows to pass googles page speed test

I have googles page speed plugin installed: http://code.google.com/speed/page-speed/
It is saying that I have a lot of pngs that aren't compressed on my site.
I tried using the RIOT image optimizer: http://luci.criosweb.ro/riot/
However with attempts using multiple settings I couldn't get it to pass.
Any ideas? Thanks!
You could try pngcrush, but presumably you'll get much greater savings from converting to JPEG with quality slightly less than 100 (I usually find 92 pretty good). ImageMagick would be the tool of choice for bulk processing.
I never managed to create paletted PNGs, but in principle those should be pretty efficient when you're dealing with illustrations that only use a few colours.
The good png optimzers are:
pngout http://advsys.net/ken/utils.htm
pngcrush http://pmt.sourceforge.net/pngcrush/
optipng http://optipng.sourceforge.net/
advpng http://advancemame.sourceforge.net/comp-readme.html
For best results use all 4 in that order.
You can also use pngnq http://pngnq.sourceforge.net/ to reduce the image even more at the cost of some quality. (And after using pngnq, run the image through the optimizers.)
Thanks for all the suggestions guys. I think in my case the easiest method is to grab the cache files that google page speed produces. Here is the info: http://code.google.com/speed/page-speed/docs/using_firefox.html#savefiles
Also you'll need to run it in firefox as chrome doesn't produce the same files.