#!/usr/bin/env python

#
# fast-scale3x.py
# Scale pixel art using Scale3x algorithm
#
# Copyright 2011 Khomsan Phongphisansakun
# You may use and distribute this plug-in under the terms of GNU GPL
#
# Based on scale2x.py by Eduardo 'trialforce' Bonfandini
# Fast pixel operation based on arclayer.py by Akkana Peck
#

from gimpfu import *
from array import array

def python_scale3x(img, layer):
  gimp.progress_init("Scaling...")

  newWidth, newHeight = layer.width * 3, layer.height * 3
  destDrawable = gimp.Layer(img, "Scale3x", newWidth, newHeight,
                            layer.type, layer.opacity, layer.mode)

  srcWidth, srcHeight = layer.width, layer.height
  srcRgn = layer.get_pixel_rgn(0, 0, srcWidth, srcHeight)
  src_pixels = array("B", srcRgn[0:srcWidth, 0:srcHeight])

  dstRgn = destDrawable.get_pixel_rgn(0, 0, newWidth, newHeight)
  p_size = len(srcRgn[0,0])
  dest_pixels = array("B", "\x00" * (newWidth * newHeight * p_size))

  for x in range(srcWidth):
    for y in range(srcHeight):

      x1 = x - 1
      if (x1 < 0): x1 = 0
      y1 = y - 1
      if (y1 < 0): y1 = 0
      x2 = x + 1
      if (x2 > srcWidth - 1): x2 = srcWidth - 1
      y2 = y + 1
      if (y2 > srcHeight - 1): y2 = srcHeight - 1

      src_pos = (x1 + srcWidth * y1) * p_size
      E = src_pixels[src_pos: src_pos + p_size]
      src_pos = (x + srcWidth * y1) * p_size
      A = src_pixels[src_pos: src_pos + p_size]
      src_pos = (x2 + srcWidth * y1) * p_size
      F = src_pixels[src_pos: src_pos + p_size]

      src_pos = (x1 + srcWidth * y) * p_size
      C = src_pixels[src_pos: src_pos + p_size]
      src_pos = (x + srcWidth * y) * p_size
      P = src_pixels[src_pos: src_pos + p_size]
      src_pos = (x2 + srcWidth * y) * p_size
      B = src_pixels[src_pos: src_pos + p_size]

      src_pos = (x1 + srcWidth * y2) * p_size
      G = src_pixels[src_pos: src_pos + p_size]
      src_pos = (x + srcWidth * y2) * p_size
      D = src_pixels[src_pos: src_pos + p_size]
      src_pos = (x2 + srcWidth * y2) * p_size
      H = src_pixels[src_pos: src_pos + p_size]

#     E A F   --\   P1 P2 P3
#     C P B   --/   P4 P5 P6
#     G D H         P7 P8 P9

      P1, P2, P3, P4, P5, P6, P7, P8, P9 = P, P, P, P, P, P, P, P, P
      if (A != D and C != B):
        if (C == A): P1 = A
        if (A == B): P3 = B
        if (B == D): P9 = D
        if (D == C): P7 = C
        if (C == A and P != F or A == B and P != E): P2 = A
        if (A == B and P != H or B == D and P != F): P6 = B
        if (B == D and P != G or D == C and P != H): P8 = D
        if (D == C and P != E or C == A and P != G): P4 = C

      newx = x * 3
      newy = y * 3

      dest_pos = (newx + newWidth * newy) * p_size
      dest_pixels[dest_pos : dest_pos + p_size] = P1
      dest_pos = ((newx + 1) + newWidth * newy) * p_size
      dest_pixels[dest_pos : dest_pos + p_size] = P2
      dest_pos = ((newx + 2) + newWidth * newy) * p_size
      dest_pixels[dest_pos : dest_pos + p_size] = P3

      dest_pos = (newx + newWidth * (newy + 1)) * p_size
      dest_pixels[dest_pos : dest_pos + p_size] = P4
      dest_pos = ((newx + 1) + newWidth * (newy + 1)) * p_size
      dest_pixels[dest_pos : dest_pos + p_size] = P5
      dest_pos = ((newx + 2) + newWidth * (newy + 1)) * p_size
      dest_pixels[dest_pos : dest_pos + p_size] = P6

      dest_pos = (newx + newWidth * (newy + 2)) * p_size
      dest_pixels[dest_pos : dest_pos + p_size] = P7
      dest_pos = ((newx + 1) + newWidth * (newy + 2)) * p_size
      dest_pixels[dest_pos : dest_pos + p_size] = P8
      dest_pos = ((newx + 2) + newWidth * (newy + 2)) * p_size
      dest_pixels[dest_pos : dest_pos + p_size] = P9

    gimp.progress_update(float(x + 1) / srcWidth)

  dstRgn[0:newWidth, 0:newHeight] = dest_pixels.tostring()
  destDrawable.update(0, 0, newWidth, newHeight)

  newImage = pdb.gimp_image_new(newWidth, newHeight, 0)
  newLayer = pdb.gimp_layer_new_from_drawable(destDrawable, newImage)
  pdb.gimp_image_add_layer(newImage, newLayer, -1)
  pdb.gimp_display_new(newImage)

register(
  "python_fu_scale3x",
  "Scale using Scale3x algorithm",
  "Scale using Scale3x algorithm",
  "Khomsan Phongphisansakun",
  "Khomsan Phongphisansakun",
  "2011",
  "<Image>/Image/Scale using Scale3x",
  "*",
  [],
  [],
  python_scale3x)

main()

