Вопрос

Я пытаюсь использовать функцию выбора и копирования IKImageView.Если все, что вам нужно, это иметь приложение с изображением, выбрать часть и скопировать ее в буфер обмена, это легко.Вы устанавливаете в меню копирования метод copy:(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, но я не на самом деле я уверен, что с этим сделает тот, кто первым ответит...

РЕДАКТИРОВАТЬ 3 Похоже, что ошибка CGBitmapContextCreate возникает из-за [imageView image] что, как ни странно, ЯВЛЯЕТСЯ документированный метод.

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

Это было полезно?

Решение

А -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

Другие советы

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

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

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

В любом случае, вот моя копия selectedImage:

- (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*...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top