Еще один вопрос IKImageView: копирование региона - PullRequest
1 голос
/ 23 марта 2010

Я пытаюсь использовать функцию выбора и копирования IKImageView. Если все, что вам нужно, это иметь приложение с изображением, выбрать часть и скопировать ее в буфер обмена, это легко. Вы устанавливаете пункт меню копирования на метод копирования первого респондента: (id), и волшебным образом все работает.

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

IKImageView, похоже, не имеет метода копирования, у него, похоже, нет метода, который даже скажет вам выбранный прямоугольник!

Я просмотрел книгу Хиллегаса, поэтому я понимаю, как работает буфер обмена, но не то, как вывести часть изображения из вида ...

Теперь я начинаю думать, что допустил ошибку, основав свой проект на IKImageView, но это то, на чем основан Preview (или я так прочитал), поэтому я решил, что он должен быть стабильным ... и вообще, сейчас уже слишком поздно, я слишком глубоко в этом разбираюсь ...

Итак, кроме использования IKImageView, есть предложения, как скопировать выбранную область в буфер обмена вручную?

РЕДАКТИРОВАТЬ На самом деле, я нашел метод copy (id), но когда я его вызываю, я получаю

 <Error>: CGBitmapContextCreate: unsupported parameter combination: 8 integer bits/component; 16 bits/pixel; 1-component color space; kCGImageAlphaPremultipliedLast; 2624 bytes/row.

Что, очевидно, не происходит, когда я делаю обычную копию через первого респондента ... Я понимаю сообщение об ошибке, но я не уверен, откуда он получает эти параметры ...

Есть ли способ отследить это и посмотреть, как это происходит? Отладчик не поможет по понятным причинам, а также из-за того, что я делаю это в Mozilla, поэтому отладчик в любом случае не вариант ...

РЕДАКТИРОВАТЬ 2 Мне кажется, что метод copy: (id), который я нашел, может копировать VIEW, а не копировать часть изображения в буфер обмена, что мне и нужно.

Причина, по которой я думал, что это была копия буфера обмена, заключается в том, что в другом проекте, где я копирую из IKImageView в буфер обмена прямо из меню редактирования, он просто отправляет копию: (id) в firstResponder, но я Я не совсем уверен, что делает с ним первый корреспондент ...

EDIT 3 Похоже, что ошибка CGBitmapContextCreate исходит от [imageView image], что, как ни странно, IS документированного метода.

Вполне возможно, что это происходит, потому что я помещаю изображение туда с помощью метода setImage: (id), передавая ему NSImage * ... Есть ли какой-то другой, более умный способ вставить NSImage в IKImageView

Ответы [ 2 ]

0 голосов
/ 26 марта 2010

Хорошо, значит copy: nil завершается с ошибкой, а [imageView image] происходит сбой, но оказывается, что у меня есть еще одна копия NSImage, когда я вначале добавил ее в представление, так что я мог это сделать. Кроме того, CGImageCreateWithImageInRect ожидает CGImageRef, а не NSImage *, поэтому мне пришлось выполнить некоторые преобразования.

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

И по какой-то причине компилятор неожиданно начал жаловаться на то, что NSRect не относится к типу CGRect (что означает, что он внезапно перешел с 32 на 64 бит или что-то в этом роде ... не знаю почему ...)

В любом случае, вот моя копия выбранного изображения:

- (NSImage*)selectedImage
{
    //get the current selection
    CGRect selection = flipCGRect(imageView, [imageView selectionRect]);

    //get the portion of the image that the selection defines
    struct CGImage * full = [[doc currentImage] CGImageForProposedRect: NULL context: NULL hints: NULL];

    CGImageRef selectedImage = CGImageCreateWithImageInRect( full, selection);


    //convert it to an NSBitmapImageRep
    NSBitmapImageRep* bitmap = [[[NSBitmapImageRep alloc] initWithCGImage:selectedImage] autorelease];
    CGImageRelease(selectedImage);

//     //create an image from the bitmap data
    NSImage* image = [[[NSImage alloc] initWithData:[bitmap TIFFRepresentation]] autorelease];

//     //in 10.6 you can skip converting to an NSBitmapImageRep by doing this:
    //NSImage* image = [[NSImage alloc] initWithCGImage:selectedImage size:NSZeroSize];     
    return image;

}

Я написал flipCGRect, и [doc currentImage] возвращает NSImage * ...

0 голосов
/ 25 марта 2010

Метод -copy: в IKImageView делает то же, что и любой другой метод -copy:: он копирует текущий выбор в буфер обмена. Однако по некоторым причинам он реализован как приватный метод в IKImageView.

Вы можете просто позвонить напрямую:

[imageView copy:nil];

Это скопирует все, что в данный момент выбрано в буфер обмена.

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

Однако вы можете использовать приватный метод -selectionRect, чтобы получить CGRect текущего выделения и использовать его для извлечения выделенной части изображения:

//stop the compiler from complaining when we call a private method
@interface IKImageView (CompilerSTFU)
- (CGRect)selectionRect
@end

@implementation YourController
//imageView is an IBOutlet connected to your IKImageView
- (NSImage*)selectedImage
{
    //get the current selection
    CGRect selection = [imageView selectionRect];

    //get the portion of the image that the selection defines
    CGImageRef selectedImage = CGImageCreateWithImageInRect([imageView image],(CGRect)selection);

    //convert it to an NSBitmapImageRep
    NSBitmapImageRep* bitmap = [[[NSBitmapImageRep alloc] initWithCGImage:selectedImage] autorelease];
    CGImageRelease(selectedImage);

    //create an image from the bitmap data
    NSImage* image = [[[NSImage alloc] initWithData:[bitmap TIFFRepresentation]] autorelease];

    //in 10.6 you can skip converting to an NSBitmapImageRep by doing this:
    //NSImage* image = [[NSImage alloc] initWithCGImage:selectedImage size:NSZeroSize];     
    return image;
}
@end
...