Objective-C / Mac - установить цвет пикселей? - PullRequest
1 голос
/ 03 июля 2011

В моем приложении Mac я позволяю пользователю рисовать на сетке, каждый квадрат на сетке представляет пиксель и имеет свой собственный цвет.Можно ли затем взять этот цвет и просто поочередно создать изображение, задав цвет пикселя?

Я не могу придумать, как еще это сделать.Мне нужно экспортировать изображение после того, как пользователь нарисовал в этой сетке, которую я делаю.

Спасибо.

Цель моего приложения: пользователь может рисовать в сетке.Таким образом, конечное изображение может иметь размер 16x16 пикселей, однако пользователь в приложении может нарисовать каждый пиксель в квадрат сетки (16x16).Затем он выводится в формате конечного изображения, которое может быть 16x16 пикселей, буквально на экране.Пока сетка визуально, а покраска крупнее.Каждый квадрат на сетке представляет пиксель в конечном изображении, и пользователь может поместить один цвет в каждый квадрат.Надеюсь, это имеет смысл, если нет, я попытаюсь разработать и связать пример.

Ответы [ 3 ]

1 голос
/ 07 июля 2011

[ TLDR: Использование Model-View-Controller .]

Здесь необходимо учитывать три различных момента:

  1. «Идеальное» изображение, которое рисует пользователь, сетка из 16x16 (или сколько угодно) цветных пикселей.
  2. Экранное представление, где каждый пиксель отображается в гораздо большем размере, чтобы пользователь мог взаимодействовать с ним..
  3. Конечный файл изображения, экспортируемый из приложения.

Хранение этих элементов отдельно в вашем уме, и ваша реализация сделает вашу жизнь lot проще.

# 1 - это модель , и в этом случае она, вероятно, будет состоять из массива из 256 (или сколько угодно) цветовых значений, возможно, наряду с некоторыми описательными данными, такими как размеры в пикселях и цветовое пространство,Для чего-то такого простого вы могли бы не хотеть создавать отдельный класс модели (хотя вы должны это делать), но даже если это просто массив ivar, сидящий в монолитном классе приложения, вы все равно должны думать о нем как об отдельной сущности

# 2 - это представление контроллером тенденциями), и вы почти наверняка должны реализовать его с помощью пользовательского подкласса NSView.Было бы возможно построить сетку из 256 экземпляров NSColorWell или другого существующего типа NSView, но это было бы просто глупо .Представление имеет два задания:

  1. Нарисуйте модель на экране.Сделайте это, перебирая значения данных и рисуя каждое из них в виде заполненного прямоугольника соответствующего размера.Методы NSBezierPath здесь ваши друзья, особенно методы класса fillRect и strokeRect.
  2. . Опосредовать ввод данных пользователем.Например, вы можете решить, что пользователь раскрасит пиксель, щелкнув по нему мышью.Вашему представлению будет отправлено событие для каждого щелчка мыши, и вам нужно будет ответить, сопоставив местоположение щелчка с правильным пикселем (в основном, делением), а затем внеся соответствующие изменения в модель.

# 3 - это в некотором роде просто другой вид, в том смысле, что это еще один способ представления модели.Код для его создания иногда включается в модель (скажем, если существует только один канонический способ сериализации данных), но рекомендуется размещать его где-то еще, особенно если позже вы захотите добавить другие произвольные механизмы.

Ключевым моментом здесь является то, что это изображение на самом деле не имеет ничего общего со стороной NSView, это вопрос получения данных модели и их записи.Вы можете писать с помощью NSImage методов или с помощью Core Graphics, как упомянуто в других ответах, но абсолютно не следует *1054* делать то, что вы пытаетесь вручную обработать с экрана.Так лежит безумие!

1 голос
/ 03 июля 2011

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

Попробуйте что-нибудь вроде:

NSData *data;
NSBitmapImageRep *rep;
rep = [self bitmapImageRepForCachingDisplayInRect:[self frame]];
[self cacheDisplayInRect:[self frame] toBitmapImageRep:rep];
data = [rep TIFFRepresentation];

Это должно работать, если ваш взгляд не openGL.

EDIT:

Не знаю, если вы уже решили это, но одним из подходов может быть отображение прозрачной сетки 16/16 NSButtons. Когда вы нажимаете одну кнопку, вы меняете ее цвет (или позволяете пользователю выбрать одну).

Когда пользователь закончит, вы создаете растровое изображение 16x16 пикселей «вручную» (устанавливая его пиксель в соответствующий цвет кнопки), или сохраняете изображение (описанным мною способом) и уменьшаете его.

Кнопки не являются строго необходимыми; Вы можете переопределить метод hitTest в своем NSView и определить с помощью сенсорной координаты, какую область вида нужно закрасить.

0 голосов
/ 03 июля 2011

Ваше изображение может быть буфером ширины * высоты * 3 байта (char).Обычно используется первый ряд строки, поэтому пиксель с координатами (x, y) соответствует трем байтам, начиная с (width*y+x)*3.Эти три байта будут содержать красный, зеленый и синий компоненты цвета этого пикселя, соответственно.Изначально вы можете установить все байты 255 для белого фона.

Если вы хотите закрасить пиксель в точке (x, y) цветом (r, g, b), вы можете сделать

i = (width*y+x)*3;
buf[i] = r;
buf[i+1] = g;
buf[i+2] = b;

Если вы хотите работать с изображением с помощью графических вызовов Quartz, вы можете создать CGContext, обернув его, используя CGBitmapContextCreate.Однако для изменения цвета отдельных пикселей запись соответствующих байтов напрямую является самым быстрым подходом.Также важно, чтобы вы понимали, как растровые изображения представлены в памяти, поэтому это двойной выигрыш.

...