Как создать изображение из данных холста? - PullRequest
3 голосов
/ 09 января 2011

В моем приложении я пытаюсь сохранить произвольную часть визуализированного HTML-холста в файл изображения.В моем Javascript я вызываю ctx.<a href="https://developer.mozilla.org/En/HTML/Canvas/Pixel_manipulation_with_canvas" rel="nofollow">getImageData</a>(x, y, w, h) и передаю полученный объект в мой код макруби (хотя, если вы знаете решение в objc, я тоже очень заинтересован).

Там я пытаюсь создать NSBitmapImageRep объект, так что я могу затем сохранить в формате изображения, который желает пользователь.

Пока это мой код (функция получает WebScriptObject в качестве аргумента):

def setimagedata(d)
    w =  d.valueForKey("width").to_i
    h =  d.valueForKey("height").to_i
    data = Pointer.new(:char, d.valueForKey("data").valueForKey("length").to_i)
    d.valueForKey("data").valueForKey("length").to_i.times do |i|
        data[i] = d.valueForKey("data").webScriptValueAtIndex(i).to_i
    end
    puts "data complete" # get's called
    @exported_image = NSBitmapImageRep.alloc.initWithBitmapDataPlanes(data,
        pixelsWide: w, pixelsHigh:h, bitsPerSample: 32,
        samplesPerPixel: 4, hasAlpha: true, isPlanar: false, 
        colorSpaceName: NSCalibratedRGBColorSpace, 
        bitmapFormat: NSAlphaNonpremultipliedBitmapFormat, 
        bytesPerRow: 0, bitsPerPixel: 0)
    puts "done" # doesn't get called
end

Кажется, код не проходит через функцию initWithBitmapDataPlanes, но не выдает ошибки.

Мой вопрос: что я делаю не так?Является ли этот подход разумным (если нет, что было бы лучше?).

Редактировать

Используя ответ Phrogz 'ниже, я получил промежуточное решение: я использую другой холст, getImageData, putImageData и toDataURL дляполучить URL-адрес нужного региона.В моем setimagedata я просто сохраняю URL-адрес данных, и мой dataOfType: error: метод выглядит следующим образом:

def dataOfType(type, error:outError)
    workspace = NSWorkspace.sharedWorkspace
    if workspace.type(type, conformsToType: "public.image")
        @data_url[ /(?<=,).+/ ].unpack("m").first
    end
end

Отсутствует секретный соус, этот уродливый хак:

class NSString
    def writeToURL(url, options: opts, error: error)
        File.open(url.path, "w") {|f| f << self }
    end
end

Он используетУтка набирает в Какао и обычно определяет селектор на NSData для записи себя в файл.

Кажется, это работает до сих пор, и я рад, что нашел решение.Однако я все еще хотел бы увидеть решение, использующее NSBitmapImageRep.Следующая функция, которую я реализую, это экспорт в видео, и я считаю, что мне понадобится более тонкий контроль, предоставляемый этим классом.

1 Ответ

3 голосов
/ 09 января 2011

Вместо использования getImageData я бы предложил использовать Canvas.toDataURL .Это даст вам двоичный PNG (или JPEG), который, как оказалось, закодирован в base64.Расшифруйте base64, и вы получите файл, который вы можете сохранить для пользователя или обработать для перекодирования в другой формат.

Редактировать : я первоначально удалил свой ответ, потому что понял, что вы хотелисериализовать субрегион холста.Затем я понял, что если это поможет, вы можете вместо этого сделать следующее:

  1. Создать новый холст размером с субрегион.
  2. Использовать context.drawImage () для копирования подобласти с оригинала на новый холст.
  3. Вызовите Canvas.toDataURL на новом холсте, чтобы получить сериализованные в base64 данные.

Для декодирования данных base64 вы можете использовать метод decoby64 библиотеки base64 ruby.Обратите внимание, что реализация этого метода чрезвычайно проста, и вы можете просто вставить его в строку:

def decode64(str)
  str.unpack("m").first
end

Edit 2 : Например, учитывая результаты вызова toDataURLпомещается в строку Ruby, просто:

require 'base64'
data_only = data_url[ /(?<=,).+/ ] # Find everything after the first comma
File.open( 'foo.png', 'w' ){ |f| f << Base64.decode64( data_only ) }
...