createImageFromChannels static method

Image createImageFromChannels(
  1. int? colorMode,
  2. int? bitDepth,
  3. int width,
  4. int height,
  5. List<PsdChannel> channelList,
)

Implementation

static Image createImageFromChannels(int? colorMode, int? bitDepth, int width,
    int height, List<PsdChannel> channelList) {
  final output = Image(width, height);
  final pixels = output.getBytes();

  final channels = <int, PsdChannel>{};
  for (var ch in channelList) {
    channels[ch.id] = ch;
  }

  final numChannels = channelList.length;
  final ns = (bitDepth == 8)
      ? 1
      : (bitDepth == 16)
          ? 2
          : -1;
  if (ns == -1) {
    throw ImageException('PSD: unsupported bit depth: $bitDepth');
  }

  final channel0 = channels[0];
  final channel1 = channels[1];
  final channel2 = channels[2];
  final channel_1 = channels[-1];

  for (var y = 0, di = 0, si = 0; y < height; ++y) {
    for (var x = 0; x < width; ++x, si += ns) {
      switch (colorMode) {
        case COLORMODE_RGB:
          final xi = di;
          pixels[di++] = _ch(channel0!.data, si, ns);
          pixels[di++] = _ch(channel1!.data, si, ns);
          pixels[di++] = _ch(channel2!.data, si, ns);
          pixels[di++] =
              numChannels >= 4 ? _ch(channel_1!.data, si, ns) : 255;

          final r = pixels[xi];
          final g = pixels[xi + 1];
          final b = pixels[xi + 2];
          final a = pixels[xi + 3];
          if (a != 0) {
            // Photoshop/Gimp blend the image against white (argh!),
            // which is not what we want for compositing. Invert the blend
            // operation to try and undo the damage.
            pixels[xi] = (((r + a) - 255) * 255) ~/ a;
            pixels[xi + 1] = (((g + a) - 255) * 255) ~/ a;
            pixels[xi + 2] = (((b + a) - 255) * 255) ~/ a;
          }
          break;
        case COLORMODE_LAB:
          final L = _ch(channel0!.data, si, ns) * 100 >> 8;
          final a = _ch(channel1!.data, si, ns) - 128;
          final b = _ch(channel2!.data, si, ns) - 128;
          final alpha = numChannels >= 4 ? _ch(channel_1!.data, si, ns) : 255;
          final rgb = labToRgb(L, a, b);
          pixels[di++] = rgb[0];
          pixels[di++] = rgb[1];
          pixels[di++] = rgb[2];
          pixels[di++] = alpha;
          break;
        case COLORMODE_GRAYSCALE:
          final gray = _ch(channel0!.data, si, ns);
          final alpha = numChannels >= 2 ? _ch(channel_1!.data, si, ns) : 255;
          pixels[di++] = gray;
          pixels[di++] = gray;
          pixels[di++] = gray;
          pixels[di++] = alpha;
          break;
        case COLORMODE_CMYK:
          final c = _ch(channel0!.data, si, ns);
          final m = _ch(channel1!.data, si, ns);
          final y = _ch(channel2!.data, si, ns);
          final k = _ch(channels[numChannels == 4 ? -1 : 3]!.data, si, ns);
          final alpha = numChannels >= 5 ? _ch(channel_1!.data, si, ns) : 255;
          final rgb = cmykToRgb(255 - c, 255 - m, 255 - y, 255 - k);
          pixels[di++] = rgb[0];
          pixels[di++] = rgb[1];
          pixels[di++] = rgb[2];
          pixels[di++] = alpha;
          break;
        default:
          throw ImageException('Unhandled color mode: $colorMode');
      }
    }
  }

  return output;
}