Y
Y
Yura Imashev2014-12-17 08:07:33
Swift
Yura Imashev, 2014-12-17 08:07:33

Swift - How to optimize image slicing?

I have a UIScrollView. I want to make it so that when the user scrolls it, the image scrolls on the back. The picture is generated programmatically and stored in memory. Its height is the height of the device screen, and the width is slightly larger. But for some reason, on my iPhone 4S, this application slows down. This seems strange to me, considering that in the Gallery I can zoom in on any photo and the scrolling will be perfectly smooth. Obviously I did something wrong.
Here is what I do when the user scrolls the ScrollView:

func scrollViewDidScroll(scrollview: UIScrollView) {
    // Вычисляем смещение картинки
    var pageSize: Float = Float(scrollView.bounds.size.width)
    var page: Float = floorf((Float(scrollview.contentOffset.x) - pageSize / 2.0) / pageSize) + 1

    if (page >= Float(levelPagesCount)) {
        page = Float(levelPagesCount) - 1;
    }
    else if (page < 0) {
        page = 0;
    }
    pageControl.currentPage = Int(page)

    var dx = scrollview.contentOffset.x

    // Когда знаем смещение - можем вырезать нужную часть изображения
    let queue = NSOperationQueue()
    var cgimg: CGImageRef?
    var drawn = false

    // Запускаем функцию вырезания в отдельном потоке
    queue.addOperationWithBlock() {
        if(!self.locked) {
            self.locked = true
            cgimg = self.imageClass!.getImage(dx)
            drawn = true
        }

        NSOperationQueue.mainQueue().addOperationWithBlock() {
            if(drawn) {
                // Помещаем результат в ImageView
                self.myImageView!.layer.contents = cgimg
                self.locked = false
            }
        }
    } 
}

And here is how I "slice" the image:
public func getImage(xOffset: CGFloat) -> CGImage {
    // Здесь 'img' - та самая "широкая" картинка
    return CGImageCreateWithImageInRect(img, CGRectMake(xOffset, 0, imgWidth, imgHeight))!
}

Maybe I made a mistake, and maybe the whole solution is wrong in principle.

Answer the question

In order to leave comments, you need to log in

3 answer(s)
M
ManWithBear, 2014-12-17
@ManWithBear

Operations with contexts are quite expensive. The first thing that comes to mind is
1) render the image once at the maximum size, and add it to the UIImageView in the scroll, pressing it to the borders.
2) if the speed of scrolling the text and the picture should be different, then add another ScrollView for the current one, with the picture and handles to move it.
Just a fun fact: I tried to open a 40k pixels by 40k image in the gallery on the iPad3, the scroll was not smooth at all :)

A
An, 2014-12-18
@Flanker_4

You are doing the wrong thing in the wrong place.
scrollViewDidScroll is called very often. When scrolling by 10 px, it will twitch 10 times (well, almost, it has its own specifics). And you also fill it with queue sauce, and if the queue is asynchronous, then generally a hat, you will get 10 image generation operations for the same 10 pixels.
You need to either take this big picture, wrap it in a UIImageView , and insert it into uiscrollview as a subview. Pictures up to 2k high will scroll without any problems.
If the picture is damn big, from 5k or more, then you need to cut it, but not like you.
Make two UIImageViews of a certain size (well, for example, 1.5x-2x the height of the device’s screen) and insert as above as a subview, when the user scrolls to half of this image (you track this in didScroll ) start generating the next portion of the image, insert it into uiimageview and shove it under first. When the user scrolls, the picture will be generated and for the user it will look seamless. If the user starts scrolling further, rip out the first imageView , regenerate the image for it and paste it below. In general, you shift two tiles as the user scrolls.

F
Flie, 2014-12-17
@Flie

Maybe I'm wrong, but you should try running time profiling and see which operation takes the maximum time in it (considering that the brakes are noticeable, I think that just the longest operation will cause them)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question