Медленное рисование текста на NSImage - Как улучшить производительность? - PullRequest
0 голосов
/ 19 апреля 2020

Я использую следующий код для рисования текста на NSImage

func drawText(image :NSImage) ->NSImage
    {

        let text = textdata
        let font = NSFont(name:String(combo_font.stringValue), size: 50)
        let imageRect = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)

        let fontAttributes = [NSAttributedStringKey.font: font]

        let fontsize = (text as NSString).size(withAttributes: fontAttributes)

        let textRect = CGRect(x: (image.size.width/2-fontsize.width/2), y: image.size.height/2, width: fontsize.width, height: fontsize.height)



        let textStyle = NSMutableParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
        let textFontAttributes = [
            NSAttributedStringKey.font: font,
            NSAttributedStringKey.foregroundColor: NSColor.white,
            NSAttributedStringKey.paragraphStyle: textStyle
        ]
        let im:NSImage = NSImage(size: image.size)
        let rep:NSBitmapImageRep = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: Int(image.size.width), pixelsHigh: Int(image.size.height), bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: NSColorSpaceName.calibratedRGB, bytesPerRow: 0, bitsPerPixel: 0)!
        im.addRepresentation(rep)
        im.lockFocus()
        image.draw(in: imageRect)
        text.draw(in: textRect, withAttributes: textFontAttributes)
        im.unlockFocus()
        return im
    }

Чтобы предотвратить зависание пользовательского интерфейса, я выполняю длительную операцию в фоновом потоке

override func controlTextDidChange(_ obj: Notification) {
        if(obj.object is  NSTextField)
        {
            let textdata=obj.object as! NSTextField
            if(txtfield.identifier?.rawValue=="txt_field")
            {


                self.textdata=self.txtbox.stringValue
                DispatchQueue.global().async {
                self.img_view.image=self.drawText(image: NSImage(byReferencingFile: self.selectedfilename)!);

                }

            }

        }
    }

При обработке изображения размером 391 КБ, процесс обновления пользовательского интерфейса занимает слишком много времени. Как я могу улучшить производительность. Мне просто нужно отобразить предварительный просмотр для пользователя, изменение размера изображения до меньшего размера также позволяет повысить производительность; тот же внешний вид должен быть достигнут и на изображении с полным разрешением, а также при последующей обработке.

Обновление: в отношении фоновой резьбы

 let group = DispatchGroup()
          group.enter()
          self.progress_preview.isHidden=false
          self.progress_preview.startAnimation(self)

          DispatchQueue.global(qos: .background).async {

            self.text = self.txt_text.stringValue 
            self.globaimage  = self.drawText(image: NSImage(byReferencingFile: self.selectedfilename)!);
             group.leave()
         }

         // does not wait. But the code in notify() gets run
         // after enter() and leave() calls are balanced

          group.notify(queue: .main) {
          self.img_view.image=self.globaimage
          self.progress_preview.isHidden=true
          self.progress_preview.stopAnimation(self)

         }

1 Ответ

2 голосов
/ 23 апреля 2020

Нет смысла воссоздавать изображение с текстом в пользовательском интерфейсе каждый раз, когда текст изменяется, оно всегда будет тяжелым, потому что изображения могут быть огромными, и самое трудоемкое здесь - копирование самого изображения.

Для решения отдельный пользовательский интерфейс и генерация окончательного изображения . Ie. Просто добавьте обычную метку (плоская NSTextField) поверх изображения (NSImageView) с заранее установленными параметрами (местоположение, ограничения, шрифт, стиль и т. Д.) * (1011 *) в Storyboard, Xib и т. Д. c) и обновлять только этот пользовательский интерфейс TextField при редактировании. И только один раз, при экспорте, визуализируйте окончательный текст в окончательное изображение - для экспорта ожидается долгая операция для пользователя, поэтому не нужно беспокоиться, плюс некоторый прогресс.

Кстати, слои также можно использовать, но это не требуется.

...