createImageFromChannels static method

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

Implementation

static Image createImageFromChannels(PsdColorMode? colorMode, int? bitDepth,
    int width, int height, List<PsdChannel> channelList) {
  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;

  final output =
      Image(width: width, height: height, numChannels: numChannels);

  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];

  var si = -ns;
  for (final p in output) {
    si += ns;
    switch (colorMode) {
      case PsdColorMode.rgb:
        p.r = _ch(channel0!.data, si, ns);
        p.g = _ch(channel1!.data, si, ns);
        p.b = _ch(channel2!.data, si, ns);
        p.a = numChannels >= 4 ? _ch(channel_1!.data, si, ns) : 255;

        if (p.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.
          p
            ..r = (((p.r + p.a) - 255) * 255) / p.a
            ..g = (((p.g + p.a) - 255) * 255) / p.a
            ..b = (((p.b + p.a) - 255) * 255) / p.a;
        }
        break;
      case PsdColorMode.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);
        p.r = rgb[0];
        p.g = rgb[1];
        p.b = rgb[2];
        p.a = alpha;
        break;
      case PsdColorMode.grayscale:
        final gray = _ch(channel0!.data, si, ns);
        final alpha = numChannels >= 2 ? _ch(channel_1!.data, si, ns) : 255;
        p.r = gray;
        p.g = gray;
        p.b = gray;
        p.a = alpha;
        break;
      case PsdColorMode.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);
        p.r = rgb[0];
        p.g = rgb[1];
        p.b = rgb[2];
        p.a = alpha;
        break;
      default:
        throw ImageException('Unhandled color mode: $colorMode');
    }
  }

  return output;
}