¡Bienvenid@ a Mundo Maker!

¿Quieres aprender todo sobre el RPG Maker?



Regístrate y forma parte de Mundo Maker.
Conectarse

Recuperar mi contraseña

Temas importantes
----------------------------------------
Páginas con recursos RPG Maker
----------------------------------------
----------------------------------------
----------------------------------------
----------------------------------------
----------------------------------------
----------------------------------------
----------------------------------------
----------------------------------------
----------------------------------------
Afiliados
Estadísticas
Tenemos 3930 miembros registrados.
El último usuario registrado es LKendo.

Nuestros miembros han publicado un total de 83411 mensajes en 11868 argumentos.
Navega con Google Chrome
[DESCARGA]

Creación de una librería para WecTools

Ver el tema anterior Ver el tema siguiente Ir abajo

RPG Maker XP Creación de una librería para WecTools

Mensaje por Wecoc el 2017-06-16, 16:54

Información principal

Sobre WecTools:
WecTools es un proyecto abierto hecho con RPG maker XP que usa una nueva base de scripts para recrear un programa de grafismo, con muchas opciones pensadas para la creación de recursos para las distintas versiones de RPG maker. WecTools ha llegado a su fase final; los tools que dispone aún tienen algunos bugs y cosas pendientes, pero lo que queda se puede ir arreglando paralelamente a la adaptación de métodos a la librería DLL. Dispone de 15 tools, toda una hazaña que solo ha sido posible gracias a la colaboración de varios miembros de Mundo Maker. El proyecto será lanzado en español y posteriormente traducido al inglés.

WecTools usa una serie de métodos para Bitmap y Palette que consumen muchos recursos; no solo hacen que el programa vaya lento, a veces puede llegar a colgarse. Es por eso que es imprescindible pasar los métodos más lentos a una DLL. Mi tiempo y mis conocimientos de C++ son limitados, necesito de vuestra colaboración para hacer la librería. Que una sola persona haga todas las funciones entiendo que es muy tedioso, pero entre varios me parece más asequible.

El programa es de uso libre y código abierto (excepto por el hecho de ser un proyecto del maker), no requiere tener el RPG maker para usarlo y cumple con el EULA. Su versión final tendrá un documento con todos los nombres de quien lo haya hecho posible. Así que pido por favor que quien pueda ayude a llevarlo a cabo... Daré adicionalmente una cierta compensación en Créditos MM (la moneda del foro) por el esfuerzo.

Enlazo aquí los scripts originales del proyecto que tienen métodos que hay que adaptar, también pondré una lista de los métodos lentos en cuestión y una base de DLL que creó newold hace un tiempo. Si os faltan detalles o queréis testearlo podéis descargar la última versión disponible en el post principal de WecTools.

Código: Bitmap

Código:
#==============================================================================
# ** Bitmap
#==============================================================================

class Bitmap
  #------------------------------------------------------------------------
  # * Limpiar bitmap
  #------------------------------------------------------------------------
  def erase(*args)
    if args.size == 1
      rect = args[0]
    elsif args.size == 4
      rect = Rect.new(*args)
    end
    fill_rect(rect, Color.new(0, 0, 0, 0))
  end
  #------------------------------------------------------------------------
  # * Rellenar toda la bitmap con un color
  #------------------------------------------------------------------------
  def fill_color(color)
    fill_rect(0, 0, self.width, self.height, color)
  end
  #------------------------------------------------------------------------
  # * Devolver un fragmento de la bitmap
  #------------------------------------------------------------------------
  Cut = Win32API.new('WecTools.dll', 'cut', 'lllii', '')
  def cut(*args)
    case args.size
    when 1 # (rect)
      rect = args[0]
      x, y, width, height = *rect.size
    when 4 # (x, y, width, height)
      x, y, width, height = *args
    end
    return nil if width <= 0 or height <= 0
    bitmap = Bitmap.new(width, height)
    color = Color.new(0, 0, 0, 0)
    Cut.call(self.__id__, bitmap.__id__, color.__id__, x, y)
    return bitmap
  end
  #------------------------------------------------------------------------
  # * Dibujar una bitmap encima de la actual
  #------------------------------------------------------------------------
  def blt_bitmap(*args)
    case args.size
    when 2 # (rect, bitmap)
      rect  = args[0]
      bitmap = args[1]
      x      = rect.x
      y      = rect.y
      width  = rect.width
      height = rect.height
    when 5 # (x, y, width, height, bitmap)
      x      = args[0]
      y      = args[1]
      width  = args[2]
      height = args[3]
      bitmap = args[4]
    end
    for ix in 0...width
      for iy in 0...height
        dx = bitmap.width
        dy = bitmap.height
        set_pixel(ix + x, iy + y, bitmap.get_pixel(ix % dx, iy % dy))
      end
    end
  end
  #------------------------------------------------------------------------
  # * Dibujar texto
  #------------------------------------------------------------------------
  alias draw_text_width_fix draw_text unless $@
  def draw_text(*args)
    if args[0].is_a?(Rect) # (rect, text, align)
      rect = args[0]
      text = args[1]
      align = args[2]
    else # (x, y, width, height, text, align)
      rect = Rect.new(args[0], args[1], args[2], args[3])
      text = args[4]
      align = args[5]
    end
    align = 0 if align == nil
    if self.text_size(text).width > width
      for i in 0...text.size
        if self.text_size(text).width < width
          n = i
        else
          return if n == nil
          text = text[0..n]
          break
        end
      end
    end
    draw_text_width_fix(rect, text, align)
  end
end

#==============================================================================
# ** Bitmap
#==============================================================================

class Bitmap
  attr_reader :hue
  #------------------------------------------------------------------------
  # * Initialize
  #------------------------------------------------------------------------
  alias hue_fix_ini initialize unless $@
  def initialize(*args)
    hue_fix_ini(*args)
    @hue = 0
  end
  #------------------------------------------------------------------------
  # * Asignar hue
  #------------------------------------------------------------------------
  def hue=(hue)
    if @hue > 0
      _hue_change(-@hue)
    end
    @hue = hue % 360.0
    _hue_change(hue)
  end
  #------------------------------------------------------------------------
  # * Cambiar hue
  #------------------------------------------------------------------------
  def hue_change(hue)
    _hue_change(hue)
    @hue = (@hue + hue) % 360.0
  end
  #------------------------------------------------------------------------
  # * Cambiar hue (interno)
  #------------------------------------------------------------------------
  def _hue_change(hue)
    return if hue == 0
    for iy in 0...self.height
      for ix in 0...self.width
        color = self.get_pixel(ix, iy)
        next if color.alpha == 0
        new_color = color.clone
        new_color.hue = (color.hue + hue) % 360.0
        next if color == new_color
        self.set_pixel(ix, iy, new_color)
      end
    end
  end
  #------------------------------------------------------------------------
  # * Dibujar línea horizontal
  #------------------------------------------------------------------------
  def draw_hline(x, y, width, color, stroke=1)
    return if stroke <= 0
    fill_rect(x, y, width, stroke, color)
  end
  #------------------------------------------------------------------------
  # * Dibujar línea vertical
  #------------------------------------------------------------------------
  def draw_vline(x, y, height, color, stroke=1)
    return if stroke <= 0
    fill_rect(x, y, stroke, height, color)
  end
  #------------------------------------------------------------------------
  # * Dibujar rectángulo
  #------------------------------------------------------------------------
  def draw_rect(x, y, width, height, color, stroke=1)
    return if stroke <= 0
    fill_rect(x, y, width, stroke, color)
    fill_rect(x, y, stroke, height, color)
    fill_rect(x+width-stroke, y, stroke, height, color)
    fill_rect(x, y+height-stroke, width, stroke, color)
  end
  #------------------------------------------------------------------------
  # * Rellenar círculo
  #------------------------------------------------------------------------
  def fill_circle(x, y, width, height, color)
    if width <= 3
      fill_rect(x, y, width, height, color)
      return
    end
    width += 1
    height += 1
    cx = x + width.quo(2)
    cy = y + height.quo(2)
    for ix in x...(x + width)
      for iy in y...(y + height)
        distance = Math.sqrt((cx - ix) ** 2 + (cy - iy) ** 2)
        if width % 2 == 0
          if distance < (width - 1).quo(2)
            set_pixel(ix, iy, color)
          end
        else
          if distance.ceil < width.quo(2)
            set_pixel(ix, iy, color)
          end
        end
      end
    end
  end
  #------------------------------------------------------------------------
  # * Dibujar línea
  #------------------------------------------------------------------------
  def draw_brush_line(x1, y1, x2, y2, color, circle=false, brush_size=1)
    cx = x2 - x1
    cy = y2 - y1
    if cx.abs > cy.abs
      if x2 < x1
        temp = x2 ; x2 = x1 ; x1 = temp
        temp = y2 ; y2 = y1 ; y1 = temp
      end
      for i in 0..cx.abs
        x = x1 + i
        y = y1 + cy * i / cx
        xs = x - (brush_size.quo(2)).floor
        xe = x + (brush_size.quo(2)).ceil
        ys = y - (brush_size.quo(2)).floor
        ye = y + (brush_size.quo(2)).ceil
        if circle
          fill_circle(xs, ys, xe - xs, ye - ys, color)
        else
          fill_rect(xs, ys, xe - xs, ye - ys, color)
        end
      end
    else
      if y2 < y1
        temp = x2 ; x2 = x1 ; x1 = temp
        temp = y2 ; y2 = y1 ; y1 = temp
      end
      for i in 0..cy.abs
        x = x1 + cx * i / cy
        y = y1 + i
        xs = x - (brush_size.quo(2)).floor
        xe = x + (brush_size.quo(2)).ceil
        ys = y - (brush_size.quo(2)).floor
        ye = y + (brush_size.quo(2)).ceil
        if circle
          fill_circle(xs, ys, xe - xs, ye - ys, color)
        else
          fill_rect(xs, ys, xe - xs, ye - ys, color)
        end
      end
    end
  end
  #------------------------------------------------------------------------
  # * Comprobar si dadas unas coordenadas, hay un color cerca (1px)
  #------------------------------------------------------------------------
  def touching_color?(x, y, color, tolerance=0)
    directions = []
    case tolerance
    when 0
      directions.push(2) if get_pixel(x, y+1) == color
      directions.push(4) if get_pixel(x-1, y) == color
      directions.push(6) if get_pixel(x+1, y) == color
      directions.push(8) if get_pixel(x, y-1) == color
    when 100
      directions = [2, 4, 6, 8]
    else
      directions.push(2) if get_pixel(x, y+1).diff(color) * 100 < tolerance
      directions.push(4) if get_pixel(x-1, y).diff(color) * 100 < tolerance
      directions.push(6) if get_pixel(x+1, y).diff(color) * 100 < tolerance
      directions.push(8) if get_pixel(x, y-1).diff(color) * 100 < tolerance
    end
    return directions
  end
  #------------------------------------------------------------------------
  # * Dibujar las outlines de un dibujo negro
  #------------------------------------------------------------------------
  def draw_outlines(bitmap, color, zoom=1.0)
    for ix in 0...bitmap.width
      for iy in 0...bitmap.height
        if bitmap.get_pixel(ix, iy) == Color.black
          touching = bitmap.touching_color?(ix, iy, Color.black)
          if !touching.include?(2)
            x = ix * zoom
            y = (iy + 1) * zoom - 1
            draw_hline(x, y, zoom, color)
          end
          if !touching.include?(4)
            x = ix * zoom
            y = iy * zoom
            draw_vline(x, y, zoom, color)
          end
          if !touching.include?(6)
            x = (ix + 1) * zoom - 1
            y = iy * zoom
            draw_vline(x, y, zoom, color)
          end
          if !touching.include?(8)
            x = ix * zoom
            y = iy * zoom
            draw_hline(x, y, zoom, color)
          end
        end
      end
    end
  end
  #------------------------------------------------------------------------
  # * Devolver los colores que están cerca (1px) de unas coordenadas
  #------------------------------------------------------------------------
  def touching_colors(x, y, color, tolerance=0)
    pixels = []
    if touching_color?(x, y, color, tolerance).include?(2)
      unless pixels.include?([x, y+1])
        pixels.push([x, y+1])
      end
    end
    if touching_color?(x, y, color, tolerance).include?(4)
      unless pixels.include?([x-1, y])
        pixels.push([x-1, y])
      end
    end
    if touching_color?(x, y, color, tolerance).include?(6)
      unless pixels.include?([x+1, y])
        pixels.push([x+1, y])
      end
    end
    if touching_color?(x, y, color, tolerance).include?(8)
      unless pixels.include?([x, y-1])
        pixels.push([x, y-1])
      end
    end
    return pixels
  end
  #------------------------------------------------------------------------
  # * Devolver rango de un color según si toca a otros píxeles con el mismo
  #  (Sistema del bote de pintura)
  #------------------------------------------------------------------------
  def color_range(x, y, color, tolerance=0)
    pixels = []
    pixels.push(*touching_colors(x, y, color, tolerance))
    loop do
      clone_pixels = pixels.clone
      pixels.each do |coord|
        touching = touching_colors(coord[0], coord[1], color, tolerance)
        for i in 0...touching.size
          unless pixels.include?(touching[i])
            pixels.push(touching[i])
          end
        end
      end
      pixels.uniq!
      if pixels.size == clone_pixels.size
        break
      end
    end
    pixels.sort_coords!
    return pixels
  end
  #------------------------------------------------------------------------
  # * Obtener los rangos de un color (ver color_range) a lo largo de una bitmap
  #------------------------------------------------------------------------
  def get_color_ranges(color, tolerance=0)
    ranges = []
    for ix in 0...self.width
      for iy in 0...self.height
        readed = false
        for i in ranges
          readed = true if i.include?([ix, iy])
        end
        if not readed
          if get_pixel(ix, iy) == color
            ranges.push(color_range(ix, iy, color, tolerance))
          end
        end
      end
    end
    return ranges
  end
  attr_reader :cbitmap
  #------------------------------------------------------------------------
  # * Convertir un color en un dibujado de la textura
  #------------------------------------------------------------------------
  def blt_color(color, src_bitmap)
    color_ranges = get_color_ranges(color)
    for range in color_ranges
      sx = range[0][0]
      sy = range[0][1]
      for i in 0...range.size
        x, y = *range[i]
        blt(x, y, src_bitmap, Rect.new((x - sx) % src_bitmap.width,
        (y - sy) % src_bitmap.height, 1, 1))
      end
    end
  end
  #------------------------------------------------------------------------
  # * Convertir un color de un modelo en un dibujado de la textura
  #------------------------------------------------------------------------
  def blt_color_borders(src_bitmap, texture, color, borders)
    b_up, b_down, b_left, b_right = *borders
    bitmap = Bitmap.new(self.width, self.height)
    for iy in 0...src_bitmap.height
      for ix in 0...src_bitmap.width
        if src_bitmap.get_pixel(ix, iy) == color
          left = []
          up = []
          right = []
          down = []
          if b_left != 0
            for bx in 1..b_left
              if ix != 0 and src_bitmap.get_pixel(ix - bx, iy) != color
                left.push(1)
              else
                left.push(0)
              end
            end
          end
          if b_up != 0
            for by in 1..b_up
              if iy != 0 and src_bitmap.get_pixel(ix, iy - by) != color
                up.push(1)
              else
                up.push(0)
              end
            end
          end
          if b_right != 0
            for bw in 1..b_right
              if ix != self.width and src_bitmap.get_pixel(ix + bw, iy) != color
                right.push(1)
              else
                right.push(0)
              end
            end
          end
          if b_down != 0
            for bh in 1..b_down
              if iy != self.height and src_bitmap.get_pixel(ix, iy + bh) != color
                down.push(1)
              else
                down.push(0)
              end
            end
          end
          left  = left.include?(1)  ? 1 : 0
          up    = up.include?(1)    ? 1 : 0
          right = right.include?(1) ? 1 : 0
          down  = down.include?(1)  ? 1 : 0
          case [left, up, right, down]
          when [0, 0, 0, 0]
            new_color = Color.white # Center (White)
          when [1, 0, 0, 0], [1, 0, 1, 0]
            new_color = Color.red # Left (Red)
          when [0, 1, 0, 0], [0, 1, 0, 1]
            new_color = Color.yellow # Up (Yellow)
          when [0, 0, 1, 0]
            new_color = Color.green # Right (Green)
          when [0, 0, 0, 1]
            new_color = Color.blue # Down (Blue)
          when [1, 1, 0, 0]
            new_color = Color.orange # Left-Up (Orange)
          when [1, 0, 0, 1]
            new_color = Color.magenta # Left-Down (Magenta)
          when [0, 1, 1, 0]
            new_color = Color.pink # Right-Up (Pink)
          when [0, 0, 1, 1]
            new_color = Color.cyan # Right-Down (Cyan)
          else
            new_color = Color.gray # Others (Gray)
          end
          bitmap.set_pixel(ix, iy, new_color)
        end
      end
    end
    bx, by, bw, bh = b_left, b_up, b_right, b_down
    sw = src_bitmap.width
    sh = src_bitmap.height
    color_ranges = src_bitmap.get_color_ranges(color)
    for range in color_ranges
      sx = range[0][0]
      sy = range[0][1]
      for i in 0...range.size
        x, y = *range[i]
        color = bitmap.get_pixel(x, y)
        case color
        when Color.white
          result = texture.cut(bx, by, sw - bx - bw, sh - by - bh)
        when Color.red
          result = texture.cut(0, by, bx, sh - by - bh)
        when Color.yellow
          result = texture.cut(bx, 0, sw - bx - bw, by)
        when Color.green
          result = texture.cut(sw - bw, by, bw, sh - by - bh)
        when Color.blue
          result = texture.cut(bx, sh - bh, sw - bx - bw, bh)
        when Color.orange
          result = texture.cut(0, 0, bx, by)
        when Color.magenta
          result = texture.cut(0, sh - bh, bx, bh)
        when Color.pink
          result = texture.cut(sw - bw, 0, bw, by)
        when Color.cyan
          result = texture.cut(sw - bw, sh - bh, bw, bh)
        when Color.gray
          result = texture.cut(bx, by, 1, 1)
        end
        next if result.nil?
        dx = (x - sx - bx) % result.width
        dy = (y - sy - by) % result.height
        new_color = result.get_pixel(dx, dy)
        set_pixel(x, y, new_color)
      end
    end
  end
  #------------------------------------------------------------------------
  # * Stretch blt
  #------------------------------------------------------------------------
  alias stretch_blt_src_fix stretch_blt unless $@
  def stretch_blt(dest_rect, src_bitmap, src_rect=nil, opacity=255)
    if src_rect.is_a?(NilClass)
      src_rect = Rect.new(0, 0, src_bitmap.width, src_bitmap.height)
    end
    stretch_blt_src_fix(dest_rect, src_bitmap, src_rect, opacity)
  end
  #------------------------------------------------------------------------
  # * Fit Blt (Stretch Blt mejorado)
  #------------------------------------------------------------------------
  def fit_blt(dest_rect, src_bitmap, src_rect, opacity=255)
    if dest_rect.width >= src_rect.width && dest_rect.height >= src_rect.height
      dx = dest_rect.x + dest_rect.width  / 2 - src_rect.width  / 2
      dy = dest_rect.y + dest_rect.height / 2 - src_rect.height / 2
      ndest_rect = Rect.new(dx, dy, src_rect.width, src_rect.height)
      return stretch_blt(ndest_rect, src_bitmap, src_rect, opacity)
    else
      lmax = [src_rect.width, src_rect.height].max
      lmin = [src_rect.width, src_rect.height].min
      bitmap = Bitmap.new(lmax, lmax)
      dx = [bitmap.width  / 2 - src_rect.width  / 2, 0].max
      dy = [bitmap.height / 2 - src_rect.height / 2, 0].max
      bitmap.blt(dx, dy, src_bitmap, src_rect)
      src_rect = Rect.new(0, 0, bitmap.width, bitmap.height)
      return stretch_blt(dest_rect, bitmap, src_rect, opacity)
    end
  end
  #------------------------------------------------------------------------
  # * Dibujar bitmap encima de la actual
  #------------------------------------------------------------------------
  DrawBitmap = Win32API.new('WecTools.dll', 'draw_bitmap', 'lllii', '')
  def draw_bitmap(x, y, bitmap)
    color = Color.new(0, 0, 0, 0)
    return if bitmap.nil?
    DrawBitmap.call(self.__id__, bitmap.__id__, color.__id__, x, y)
    return bitmap
  end
  #------------------------------------------------------------------------
  # * Voltear horizontalmente (mirror)
  #------------------------------------------------------------------------
  def flip_x
    result = Bitmap.new(self.width, self.height)
    for ix in 0...self.width
      line = self.cut(ix, 0, 1, self.height)
      result.draw_bitmap(self.width - ix - 1, 0, line)
    end
    return result
  end
  #------------------------------------------------------------------------
  def flip_x!
    result = self.clone
    for ix in 0...result.width
      line = result.cut(ix, 0, 1, self.height)
      self.draw_bitmap(result.width - ix - 1, 0, line)
    end
  end
  #------------------------------------------------------------------------
  # * Voltear verticalmente
  #------------------------------------------------------------------------
  def flip_y
    result = Bitmap.new(self.width, self.height)
    for iy in 0...self.height
      line = self.cut(0, iy, self.width, 1)
      result.draw_bitmap(0, self.height - iy - 1, line)
    end
    return result
  end
  #------------------------------------------------------------------------
  def flip_y!
    result = self.clone
    for iy in 0...result.height
      line = result.cut(0, iy, self.width, 1)
      self.draw_bitmap(0, result.height - iy - 1, line)
    end
  end
  #------------------------------------------------------------------------
  # * Girar a la derecha
  #------------------------------------------------------------------------
  def rotate_right
    bitmap = Bitmap.new(self.height, self.width)
    for iy in 0...self.height
      for ix in 0...self.width
        color = self.get_pixel(ix, iy)
        bitmap.set_pixel(self.height - iy - 1, ix, color)
      end
    end
    return bitmap
  end
  #------------------------------------------------------------------------
  # * Girar a la izquierda
  #------------------------------------------------------------------------
  def rotate_left
    bitmap = Bitmap.new(self.height, self.width)
    for iy in 0...self.height
      for ix in 0...self.width
        color = self.get_pixel(ix, iy)
        bitmap.set_pixel(iy, width - ix - 1, color)
      end
    end
    return bitmap
  end
  #------------------------------------------------------------------------
  # * Colorear
  #------------------------------------------------------------------------
  def colorize(hue, sat, alpha)
    return self if alpha == 0
    result = self.clone
    for iy in 0...result.height
      for ix in 0...result.width
        color = result.get_pixel(ix, iy)
        next if color.alpha == 0
        new_color = color.clone
        new_color.hue = hue
        new_color.sat = sat
        if alpha != 255
          a = alpha / 255.0
          r = (new_color.red  * a + color.red  * (1 - a))
          g = (new_color.green * a + color.green * (1 - a))
          b = (new_color.blue  * a + color.blue  * (1 - a))
          a = new_color.alpha
          new_color = Color.new(r, g, b, a)
        end
        result.set_pixel(ix, iy, new_color)
      end
    end
    return result
  end
  #------------------------------------------------------------------------
  # * Asignar valores RGB
  #------------------------------------------------------------------------
  def set_rgb(red, green, blue)
    return self if red == 0 && green == 0 && blue == 0
    result = self.clone
    for iy in 0...result.height
      for ix in 0...result.width
        color = result.get_pixel(ix, iy)
        next if color.alpha == 0
        a = color.alpha
        r = color.red  + 255 * (red.to_f  / 100)
        g = color.green + 255 * (green.to_f / 100)
        b = color.blue  + 255 * (blue.to_f  / 100)
        r = [[r.to_i, 0].max, 255].min
        g = [[g.to_i, 0].max, 255].min
        b = [[b.to_i, 0].max, 255].min
        new_color = Color.new(r, g, b, a)
        result.set_pixel(ix, iy, new_color)
      end
    end
    return result
  end
  #------------------------------------------------------------------------
  # * Asignar valores HSL
  #------------------------------------------------------------------------
  def set_hsl(hue, sat, lum)
    return self if hue == 0 && sat == 0 && lum == 0
    result = self.clone
    for iy in 0...result.height
      for ix in 0...result.width
        color = result.get_pixel(ix, iy)
        next if color.alpha == 0
        a = color.alpha
        h = (color.hue + hue) % 360
        s = [[color.sat + sat, 0].max, 255].min
        l = [[color.lum + lum, 0].max, 255].min
        c = HSLColor.new(h, s, l)
        new_color = Color.new(c.red, c.green, c.blue, a)
        result.set_pixel(ix, iy, new_color)
      end
    end
    return result
  end
  #------------------------------------------------------------------------
  # * Obtener máscara de diferencia con otra bitmap
  #------------------------------------------------------------------------
  def difference(diff_bitmap)
    result = self.clone
    for iy in 0...self.height
      for ix in 0...self.width
        tx = ix % diff_bitmap.width
        ty = iy % diff_bitmap.height
        color_a = self.get_pixel(ix, iy)
        color_b = diff_bitmap.get_pixel(tx, ty)
        color = Color.new((color_a.red - color_b.red).abs,
                          (color_a.green - color_b.green).abs,
                          (color_a.blue - color_b.blue).abs)
        result.set_pixel(ix, iy, color)
      end
    end
    return result
  end
  #------------------------------------------------------------------------
  # * Quitar colores translúcidos
  #------------------------------------------------------------------------
  def flat_alpha(n=0)
    result = self.clone
    for iy in 0...self.height
      for ix in 0...self.width
        c = self.get_pixel(ix, iy)
        if c.alpha > n && c.alpha < 255
          result.set_pixel(ix, iy, Color.new(c.red, c.green, c.blue))
        elsif c.alpha <= n
          result.set_pixel(ix, iy, Color.new(0, 0, 0, 0))
        end
      end
    end
    return result
  end
  #------------------------------------------------------------------------
  # * Rotar
  #------------------------------------------------------------------------
  def rotate(*args)
    case args.size
    when 1 # (angle)
      sx = self.width / 2
      sy = self.height / 2
      angle = args[0]
    when 3 # (sx, sy, angle)
      sx = args[0] * 2
      sy = args[1] * 2
      angle = args[2]
    end
    angle = (2 * Math::PI * angle) / 360
    cos_a = Math.cos(angle)
    sin_a = Math.sin(angle)
    w = self.width
    h = self.height
    p1_x = -h * sin_a
    p1_y = h * cos_a
    p2_x = w * cos_a - h * sin_a
    p2_y = h * cos_a + w * sin_a
    p3_x = w * cos_a
    p3_y = w * sin_a
    min_x = [0, p1_x, p2_x, p3_x].min
    min_y = [0, p1_y, p2_y, p3_y].min
    max_x = [0, p1_x, p2_x, p3_x].max
    max_y = [0, p1_y, p2_y, p3_y].max
    w = (max_x - min_x).ceil
    h = (max_y - min_y).ceil
    dx = sx - self.width / 2
    dy = sy - self.height / 2
    dest_rect = Rect.new(dx, dy, (max_x - min_x).ceil, (max_y - min_y).ceil)
    src_bitmap = Bitmap.new(dest_rect.width, dest_rect.height)
    for x in 0...dest_rect.width
      for y in 0...dest_rect.height
        src_x = ((x + min_x) * cos_a + (y + min_y) * sin_a).to_i
        src_y = ((y + min_y) * cos_a - (x + min_x) * sin_a).to_i
        if src_x >= 0 and src_x < self.width and
          src_y >= 0 and src_y <= self.height
          dest_x = dx + x
          dest_y = dy + y
          src_color = self.get_pixel(src_x, src_y)
          src_bitmap.set_pixel(dest_x, dest_y, src_color)
        end
      end
    end
    return src_bitmap
  end
  #------------------------------------------------------------------------
  # * Zoom
  #------------------------------------------------------------------------
  def zoom(*args)
    case args.size
    when 1 # (zoom)
      zx = args[0] / 100.0
      zy = args[0] / 100.0
    when 2 # (zoom_x, zoom_y)
      zx = args[0] / 100.0
      zy = args[1] / 100.0
    end
    bitmap = Bitmap.new((self.width * zx).floor, (self.height * zy).floor)
    bitmap.stretch_blt(bitmap.rect, self, self.rect)
    return bitmap
  end
  #------------------------------------------------------------------------
  # * Opacidad
  #------------------------------------------------------------------------
  def opacity(opacity)
    return self if opacity == 255
    bitmap = Bitmap.new(self.width, self.height)
    return bitmap if opacity == 0
    bitmap.stretch_blt(bitmap.rect, self, self.rect, opacity)
    return bitmap
  end
  #------------------------------------------------------------------------
  # * Dibujar encima de la bitmap sin borrar lo de debajo
  #------------------------------------------------------------------------
  def draw_over_bitmap(x, y, bitmap, blend_type=0)
    return if bitmap.nil?
    w = bitmap.width
    h = bitmap.height
    for ix in 0...[w, self.width - x].min
      for iy in 0...[h, self.height - y].min
        dx = ix % bitmap.width
        dy = iy % bitmap.height
        color_a = get_pixel(ix + x, iy + y)
        color_b = bitmap.get_pixel(dx, dy)
        ra = color_a.red  / 255.0
        ga = color_a.green / 255.0
        ba = color_a.blue  / 255.0
        aa = color_a.alpha / 255.0
        rb = color_b.red  / 255.0
        gb = color_b.green / 255.0
        bb = color_b.blue  / 255.0
        ab = color_b.alpha / 255.0
        na = [[aa, ab].max + (aa * ab), 1.0].min
        new_a = (na * 255).to_i
        next if new_a == 0
        case blend_type
        when 0 # Normal
          new_r = (((ra - (ra * ab) / na) + (rb * ab) / na) * 255).to_i
          new_g = (((ga - (ga * ab) / na) + (gb * ab) / na) * 255).to_i
          new_b = (((ba - (ba * ab) / na) + (bb * ab) / na) * 255).to_i
        when 1 # Fusionado
          new_r = ((ra * aa / na + rb * ab / na) * 255).to_i
          new_g = ((ga * aa / na + gb * ab / na) * 255).to_i
          new_b = ((ba * aa / na + bb * ab / na) * 255).to_i
        when 2 # Inverso
          new_r = ((ra * aa / na - rb * ab / na) * 255).to_i
          new_g = ((ga * aa / na - gb * ab / na) * 255).to_i
          new_b = ((ba * aa / na - bb * ab / na) * 255).to_i
        end
        color = Color.new(new_r, new_g, new_b, new_a)
        set_pixel(ix + x, iy + y, color)
      end
    end
  end
  #------------------------------------------------------------------------
  # * Transformar
  #------------------------------------------------------------------------
  def transform(p1, p2, p3, p4, swap_mode=true)
    p1_x, p1_y = p1[0].to_f, p1[1].to_f
    p2_x, p2_y = p2[0].to_f, p2[1].to_f
    p3_x, p3_y = p3[0].to_f, p3[1].to_f
    p4_x, p4_y = p4[0].to_f, p4[1].to_f
    min_x = [0.0, p1_x, p2_x, p3_x, p4_x].min
    min_y = [0.0, p1_y, p2_y, p3_y, p4_y].min
    max_x = [0.0, p1_x, p2_x, p3_x, p4_x].max
    max_y = [0.0, p1_y, p2_y, p3_y, p4_y].max
    w = (max_x - min_x).ceil
    h = (max_y - min_y).ceil
    src_bitmap = Bitmap.new(w, h)
    if (w > h && swap_mode)
      cbitmap = Bitmap.new(self.height, self.width)
      for iy in 0...self.height
        for ix in 0...self.width
          color = self.get_pixel(ix, iy)
          cbitmap.set_pixel(iy, ix, color)
        end
      end
    else
      cbitmap = self.clone
    end
    for iy in 0...h
      for ix in 0...w
        dwa = ([p1_x, p2_x].max - [p1_x, p2_x].min).abs
        dha = ([p1_y, p2_y].max - [p1_y, p2_y].min).abs
        dwb = ([p1_x, p3_x].max - [p1_x, p3_x].min).abs
        dhb = ([p1_y, p3_y].max - [p1_y, p3_y].min).abs
        dwc = ([p1_x, p4_x].max - [p1_x, p4_x].min).abs
        dhc = ([p1_y, p4_y].max - [p1_y, p4_y].min).abs
        dwd = ([p2_x, p3_x].max - [p2_x, p3_x].min).abs
        dhd = ([p2_y, p3_y].max - [p2_y, p3_y].min).abs
        dwe = ([p2_x, p4_x].max - [p2_x, p4_x].min).abs
        dhe = ([p2_y, p4_y].max - [p2_y, p4_y].min).abs
        dwf = ([p3_x, p4_x].max - [p3_x, p4_x].min).abs
        dhf = ([p3_y, p4_y].max - [p3_y, p4_y].min).abs
        dw = [dwa, dwb, dwc, dwd, dwe, dwf, 1].max
        dh = [dha, dhb, dhc, dhd, dhe, dhf, 1].max
        dx = (dw - ix - 1) / dw ; ny = iy / dh
        dy = (dh - iy - 1) / dh ; nx = ix / dw
        if dh > dw
          sx = (p1_x * dx + p2_x * nx).round
          sy = (p1_y * dx + p2_y * nx).round
          ex = (p3_x * dx + p4_x * nx).round
          ey = (p3_y * dx + p4_y * nx).round
          x = (sx * dy + ex * ny).round
          y = (sy * dy + ey * ny).round
        else
          sx = (p1_x * dy + p2_x * ny).round
          sy = (p1_y * dy + p2_y * ny).round
          ex = (p3_x * dy + p4_x * ny).round
          ey = (p3_y * dy + p4_y * ny).round
          x = (sx * dx + ex * nx).round
          y = (sy * dx + ey * nx).round
        end
        nx = (ix.to_f * (cbitmap.width.to_f  / w)).round
        ny = (iy.to_f * (cbitmap.height.to_f / h)).round
        color = cbitmap.get_pixel(nx, ny)
        src_bitmap.set_pixel(x - 1, y - 1, color)
        src_bitmap.set_pixel(x - 1, y, color)
        src_bitmap.set_pixel(x, y - 1, color)
        src_bitmap.set_pixel(x, y, color)
      end
    end
    return src_bitmap
  end
  #------------------------------------------------------------------------
  # * Buscar patrón
  #------------------------------------------------------------------------
  def find_pattern(pattern)
    result = Bitmap.new(self.width, self.height)
    result.fill_color(Color.black)
    pw = (pattern.width  - 1) / 2
    ph = (pattern.height - 1) / 2
    sm = pattern.get_pixel(pw, ph)
    for iy in 0...self.height
      for ix in 0...self.width
        sn = self.get_pixel(ix, iy)
        hue = 0 ; sat = 0 ; lum = 0 ; n = 0
        next if sn.alpha == 0
        for dy in 0...pattern.height
          for dx in 0...pattern.width
            nx = ix + dx - pw
            ny = iy + dy - ph
            next if nx == ix && ny == iy
            en = self.get_pixel(nx % self.width, ny % self.height)
            em = pattern.get_pixel(dx, dy)
            next if en.alpha == 0 or em.alpha == 0
            mhuea = ([sm.hue, em.hue].max - [sm.hue, em.hue].min) % 360
            mhueb = ([sm.hue, em.hue].min - [sm.hue, em.hue].max) % 360
            mhue = [mhuea.abs, mhueb.abs].min.to_i
            nhuea = ([sn.hue, en.hue].max - [sn.hue, en.hue].min) % 360
            nhueb = ([sn.hue, en.hue].min - [sn.hue, en.hue].max) % 360
            nhue = [nhuea.abs, nhueb.abs].min.to_i
            msat = sm.sat - em.sat
            nsat = sn.sat - en.sat
            mlum = sm.lum - em.lum
            nlum = sn.lum - en.lum
            hue += (mhue - nhue).abs.to_i
            sat += (msat - nsat).abs.to_i
            lum += (mlum - nlum).abs.to_i
            n += 1
          end
        end
        next if n == 0
        r = 255 - (255 / n)
        result.set_pixel(ix, iy, Color.new(r - hue, r - sat, r - lum))
      end
    end
    return result
  end
end


Última edición por Wecoc el 2017-06-25, 01:03, editado 1 vez
avatar
Wecoc
Administrador
Administrador



Créditos 8988

Gracias : 442

Volver arriba Ir abajo

RPG Maker XP Re: Creación de una librería para WecTools

Mensaje por Wecoc el 2017-06-16, 16:54

Código: Palette

Código:
#==============================================================================
# ** Palette
#==============================================================================

class Palette < Array
  #------------------------------------------------------------------------
  # Obtener el color con el mínimo de un parámetro concreto
  #------------------------------------------------------------------------
  def min(sym)
    min = 360
    for i in 0...self.size
      if self[i].send(sym) < min
        min = self[i].send(sym)
      end
    end
    return min
  end
  #------------------------------------------------------------------------
  # Obtener el índice del color con el mínimo de un parámetro concreto
  #------------------------------------------------------------------------
  def min_index(sym)
    min = 360
    for i in 0...self.size
      if self[i].send(sym) < min
        min = self[i].send(sym)
        index = i
      end
    end
    return index
  end
  #------------------------------------------------------------------------
  # Obtener el color con el máximo de un parámetro concreto
  #------------------------------------------------------------------------
  def max(sym)
    max = 0
    for i in 0...self.size
      if self[i].send(sym) > max
        max = self[i].send(sym)
      end
    end
    return max
  end
  #------------------------------------------------------------------------
  # Obtener el índice del color con el máximo de un parámetro concreto
  #------------------------------------------------------------------------
  def max_index(sym)
    max = 0
    for i in 0...self.size
      if self[i].send(sym) > max
        max = self[i].send(sym)
        index = i
      end
    end
    return index
  end
  #------------------------------------------------------------------------
  # Ordenar por color (RGB)
  #------------------------------------------------------------------------
  def sort_by_color
    result = self.clone
    result.sort! do |a, b|
      (a.red + a.green + a.blue) - (b.red + b.green + b.blue)
    end
    return result
  end
  #------------------------------------------------------------------------
  def sort_by_color!
    self.replace(self.sort_by_color)
  end
  #------------------------------------------------------------------------
  # Ordenar según parámetro (hue, sat, lum)
  #------------------------------------------------------------------------
  def sort_by_par(sym)
    result = self.clone
    result.sort! { |a, b| a.send(sym) - b.send(sym) }
  end
  #------------------------------------------------------------------------
  def sort_by_par!(sym)
    self.replace(self.sort_by_par(sym))
  end
  #------------------------------------------------------------------------
  # Ordenar por abundacia en bitmap
  #------------------------------------------------------------------------
  def sort_by_ab(bitmap)
    array = get_abundance(bitmap)
    array.sort! { |a, b| a[1] - b[1] }
    result = Palette.new
    for i in 0...array.size
      result.push(array[i][0])
    end
    return result
  end
  #------------------------------------------------------------------------
  def sort_by_ab!(bitmap)
    self.replace(sort_by_ab(bitmap))
  end
  #------------------------------------------------------------------------
  # Obtener abundancias en una bitmap
  #------------------------------------------------------------------------
  def get_abundance(bitmap)
    result = []
    for i in 0...self.size
      color = self[i]
      value = 0
      for ix in 0...bitmap.width
        for iy in 0...bitmap.height
          if bitmap.get_pixel(ix, iy) == color
            value += 1
          end
        end
      end
      result.push([color, value])
    end
    return result
  end
  #------------------------------------------------------------------------
  # Quitar repetidos
  #------------------------------------------------------------------------
  def uniq
    array = []
    result = Palette.new
    for i in 0...self.size
      color = self[i].clone
      array.push([color.red, color.green, color.blue])
    end
    array.uniq!
    for i in 0...array.size
      result.push(Color.new(array[i][0], array[i][1], array[i][2]))
    end
    return result
  end
  #------------------------------------------------------------------------
  def uniq!
    self.replace(self.uniq)
  end
  #------------------------------------------------------------------------
  # Clonar
  #------------------------------------------------------------------------
  def clone
    result = Palette.new
    for i in 0...self.size
      result.push(self[i].clone)
    end
    return result
  end
  #------------------------------------------------------------------------
  # Juntar colores cercanos (perc = porcentaje de similitud)
  #------------------------------------------------------------------------
  def join_colors(perc, bitmap)
    return self if perc == 0
    for i in 0...self.size
      for j in 0...self.size
        next if i == j
        if self[i].diff(self[j]) * 100 < perc
          ab = Palette.new
          ab.concat([self[i], self[j]])
          ab.sort_by_ab!(bitmap)
          self.delete(ab[0])
          join_colors(perc, bitmap)
          return
        end
      end
    end
    return self
  end
  #------------------------------------------------------------------------
  def smart_join_colors(perc, bitmap)
    return self if perc == 0
    self.sort_by_par!(:lum)
    for i in 0...self.size
      for j in 0...self.size
        next if i == j
        if self[i].smart_diff(self[j]) * 200 < perc
          ab = Palette.new
          ab.concat([self[i], self[j]])
          ab.sort_by_ab!(bitmap)
          self.delete(ab[0])
          smart_join_colors(perc, bitmap)
          return
        end
      end
    end
    self.sort_by_color!
    return self
  end
  #------------------------------------------------------------------------
  # Reducir paleta (n = número de colores)
  #------------------------------------------------------------------------
  def reduce_palette(n, bitmap)
    return self if self.size <= n
    self.sort_by_ab!(bitmap)
    for i in 0...(self.size - n)
      self.delete(self[0])
    end
    self.sort_by_color!
    return self
  end
  #------------------------------------------------------------------------
  def smart_reduce_palette(n, bitmap)
    return self if self.size <= n
    clone_array = self.clone
    for perc in 0..100
      new_palette = self.clone
      new_palette.join_colors(perc, bitmap)
      if new_palette.size <= n
        self.replace(new_palette)
        break
      end
    end
    if self.size < n
      for i in 0...self.size
        clone_array.delete(self[i])
      end
      clone_array.sort_by_ab!(bitmap)
      for i in 0...(n - self.size)
        self.push(clone_array[clone_array.size - i - 1])
      end
    end
    self.sort_by_color!
    return self
  end
end

#==============================================================================
# ** Bitmap
#==============================================================================

class Bitmap
  
  attr_reader :palette
  
  #------------------------------------------------------------------------
  # Definir la paleta de la imagen y obtenerla
  #------------------------------------------------------------------------
  def get_palette
    @palette = Palette.new
    for ix in 0...self.width
      for iy in 0...self.height
        color = get_pixel(ix, iy)
        if color.alpha != 0
          @palette.push(color)
        end
      end
    end
    @palette.uniq!
    @palette.sort_by_color!
    return @palette
  end
  #------------------------------------------------------------------------
  # Convertir cada color en el siguiente más claro
  #------------------------------------------------------------------------
  def lighten
    get_palette if @palette.nil?
    palette = @palette.clone.sort_by_par!(:lum)
    for ix in 0...self.width
      for iy in 0...self.height
        current_color = self.get_pixel(ix, iy)
        next if current_color == Color.new(0, 0, 0, 0)
        index = palette.index(current_color)
        new_color = palette[index + 1]
        next if new_color.nil?
        self.set_pixel(ix, iy, new_color)
      end
    end
    @palette = nil
    return self
  end
  #------------------------------------------------------------------------
  # Convertir cada color en el siguiente más oscuro
  #------------------------------------------------------------------------
  def darken
    get_palette if @palette.nil?
    palette = @palette.clone.sort_by_par!(:lum)
    for ix in 0...self.width
      for iy in 0...self.height
        current_color = self.get_pixel(ix, iy)
        next if current_color == Color.new(0, 0, 0, 0)
        index = palette.index(current_color)
        next if index == 0
        new_color = palette[index - 1]
        self.set_pixel(ix, iy, new_color)
      end
    end
    @palette = nil
    return self
  end
  #------------------------------------------------------------------------
  # Canviar un color por otro (reg = modo regresivo)
  #------------------------------------------------------------------------
  def swap_pixel_color(x, y, color1, color2, reg=false)
    if get_pixel(x, y) == color1
      set_pixel(x, y, color2)
      return self
    end
    if reg == true
      if get_pixel(x, y) == color2
        set_pixel(x, y, color1)
        return self
      end
    end
  end
  #------------------------------------------------------------------------
  def swap_color(color1, color2, reg=false)
    for ix in 0...self.width
      for iy in 0...self.height
        swap_pixel_color(ix, iy, color1, color2, reg)
      end
    end
    return self
  end
  #------------------------------------------------------------------------
  def swap_color_ex(src_bitmap, color1, color2)
    for iy in 0...src_bitmap.height
      for ix in 0...src_bitmap.width
        c = src_bitmap.get_pixel(ix, iy)
        if c == color1
          set_pixel(ix, iy, color2)
        end
      end
    end
  end
  #------------------------------------------------------------------------
  # Indexar paleta de la imagen a nueva paleta
  #------------------------------------------------------------------------
  def indexate(array)
    get_palette if @palette.nil?
    for i in 0...@palette.size
      swap_color(@palette[i], @palette[i].nearest(array))
    end
    @palette = nil
    return self
  end
  #------------------------------------------------------------------------
  def smart_indexate(array)
    get_palette if @palette.nil?
    palette = @palette.clone
    amax = palette.max(:lum)
    amin = palette.min(:lum)
    bmax = array.max(:lum)
    bmin = array.min(:lum)
    r = (bmax - bmin).quo([amax - amin, 1].max)
    for i in 0...palette.size
      palette[i].lum = (bmax + (palette[i].lum - amax) * r).to_i
      swap_color(@palette[i], palette[i])
    end
    for i in 0...palette.size
      swap_color(palette[i], palette[i].smart_nearest(array))
    end
    @palette = nil
    return self
  end
  #------------------------------------------------------------------------
  # Reducir paleta
  #------------------------------------------------------------------------
  def reduce_palette(n)
    get_palette if @palette.nil?
    palette = @palette.clone
    palette.reduce_palette(n, self)
    indexate(palette)
  end
  #------------------------------------------------------------------------
  def smart_reduce_palette(n)
    get_palette if @palette.nil?
    palette = @palette.clone
    palette.smart_reduce_palette(n, self)
    smart_indexate(palette)
  end
  #----------------------------------------------------------------------------
  # * Aplicar dithering a la imagen
  #----------------------------------------------------------------------------
  def dithering(dithering_map, new_palette, sx=0, sy=0)
    palette = self.get_palette
    new_bitmap = self.clone
    n = dithering_map.width / dithering_map.height
    for c in palette
      next if new_palette.include?(c)
      result = new_palette.clone
      result.sort! do |a, b|
        c.diff(a) - c.diff(b)
      end
      near_colors = [result[0], result[1]]
      a = c.diff(near_colors[0])
      b = c.diff(near_colors[1])
      i = a.to_f / (a + b)
      i = (i * n).floor
      h = dithering_map.height
      d_bitmap = dithering_map.cut(h * i, 0, h, h)
      for x in 0...d_bitmap.width
        for y in 0...d_bitmap.height
          if d_bitmap.get_pixel(x, y) == Color.new(255, 255, 255)
            d_bitmap.set_pixel(x, y, near_colors[0])
          else
            d_bitmap.set_pixel(x, y, near_colors[1])
          end
        end
      end
      for x in 0...self.width
        for y in 0...self.height
          if get_pixel(x, y) == c
            new_color = d_bitmap.get_pixel((x + sx) % d_bitmap.width,
            (y + sy) % d_bitmap.height)
            new_bitmap.set_pixel(x, y, new_color)
          end
        end
      end
    end
    return new_bitmap
  end
  #----------------------------------------------------------------------------
  # * Difuminar imagen
  #----------------------------------------------------------------------------
  def blur(r=1.0, sp=[])
    palette = self.get_palette
    result = self.clone
    for iy in 0...self.height
      for ix in 0...self.width
        color = get_pixel(ix, iy)
        next if color.alpha != 255
        next if sp.include?(color)
        outcolors = []
        c = get_pixel(ix-1, iy-1) rescue Color.new(0,0,0,0) ; outcolors.push(c)
        c = get_pixel(ix  , iy-1) rescue Color.new(0,0,0,0) ; outcolors.push(c)
        c = get_pixel(ix+1, iy-1) rescue Color.new(0,0,0,0) ; outcolors.push(c)
        c = get_pixel(ix-1, iy  ) rescue Color.new(0,0,0,0) ; outcolors.push(c)
        c = get_pixel(ix+1, iy  ) rescue Color.new(0,0,0,0) ; outcolors.push(c)
        c = get_pixel(ix-1, iy+1) rescue Color.new(0,0,0,0) ; outcolors.push(c)
        c = get_pixel(ix  , iy+1) rescue Color.new(0,0,0,0) ; outcolors.push(c)
        c = get_pixel(ix+1, iy+1) rescue Color.new(0,0,0,0) ; outcolors.push(c)
        outcolors = outcolors.select{|c| c.alpha == 255}
        outcolors = outcolors.select{|c| !sp.include?(c)}
        red   = color.red
        green = color.green
        blue  = color.blue
        for i in 0...outcolors.size
          red   += (outcolors[i].red   * r)
          green += (outcolors[i].green * r)
          blue  += (outcolors[i].blue  * r)
        end
        red   /= ((outcolors.size * r) + 1).to_i
        green /= ((outcolors.size * r) + 1).to_i
        blue  /= ((outcolors.size * r) + 1).to_i
        newcolor = Color.new(red, green, blue)
        next if newcolor == color
        if !palette.include?(newcolor)
          newcolor = newcolor.nearest(palette)
        end
        result.set_pixel(ix, iy, newcolor)
      end
    end
    return result
  end
end

#==============================================================================
# ** Color
#==============================================================================

class Color
  #------------------------------------------------------------------------
  # Obtener la diferencia con otro color
  #------------------------------------------------------------------------
  def diff(color)
    r = (self.red - color.red).abs     / 255.0
    g = (self.green - color.green).abs / 255.0
    b = (self.blue - color.blue).abs   / 255.0
    return (r + g + b) / 3
  end
  #------------------------------------------------------------------------
  def smart_diff(color)
    l = (self.lum - color.lum).abs / 255.0
    s = (self.sat - color.sat).abs / 255.0
    return (l*2 + s) / 3
  end
  #------------------------------------------------------------------------
  # Obtener el color más cercano en una paleta
  #------------------------------------------------------------------------
  def nearest(array)
    result = array.clone
    result.sort! do |a, b|
      diff(a) - diff(b)
    end
    return result[0]
  end
  #------------------------------------------------------------------------
  def smart_nearest(array)
    result = array.clone
    result.sort! do |a, b|
      smart_diff(a) - smart_diff(b)
    end
    return result[0]
  end
end

Métodos

- Bitmap:cut
- Bitmap:blt_bitmap
- Bitmap:_hue_change
- Bitmap:fill_circle
- Bitmap:draw_brush_line
- Bitmap:color_range
- Bitmap:get_color_ranges
- Bitmap:blt_color
- Bitmap:blt_color_borders
- Bitmap:draw_bitmap
- Bitmap:flip_x!
- Bitmap:flip_y!
- Bitmap:rotate_right
- Bitmap:rotate_left
- Bitmap:colorize
- Bitmap:set_rgb
- Bitmap:set_hsl
- Bitmap:difference
- Bitmap:flat_alpha
- Bitmap:rotate
- Bitmap:zoom
- Bitmap:opacity
- Bitmap:draw_over_bitmap
- Bitmap:transform
- Bitmap:find_pattern

- Palette:get_abundance
- Bitmap:get_palette
- Bitmap:lighten
- Bitmap:darken
- Bitmap:swap_color
- Bitmap:swap_color_ex
- Bitmap:dithering
- Bitmap:blur
- Plane:bitmap

Los que estan en gris son opcionales.
Los que estan en rojo hay que vigilar porque el método original podría tener algún error.
Los que estan en verde ya se han pasado a la librería.

Si se detecta algún otro que debería estar en la lista, se puede añadir. Dentro de los propios tools y engines a veces también puede haber algún método del mismo estilo, pero esos en principio no será necesario pasarlos. En otros scripts dentro de la base, uno que suele causar lag es el recuadro de colores de Window_PickColor. El problema es que usa nuevos parámetros definidos en la clase Color y eso quizá puede suponer un problema.

Lista actualizada: 24/06/2017
Scripts actualizados: 24/06/2017


Links Externos

Base para la librería:
RGSS Bitmap CODE C

Otros links de interés:
Fog of War (DLL Source)
RPG.Net Source Forge
Building a custom DLL to use with RPG Maker


Última edición por Wecoc el 2017-06-25, 01:16, editado 4 veces
avatar
Wecoc
Administrador
Administrador



Créditos 8988

Gracias : 442

Volver arriba Ir abajo

RPG Maker XP Re: Creación de una librería para WecTools

Mensaje por Wecoc el 2017-06-17, 15:12

UPDATE: 0.02

Temía que nadie se animara pero la verdad es que empezamos muy bien, Eron se ha animado a ayudarme y gracias a él ya tenemos las dos primeras funciones hechas y ya funcionando en el proyecto :D

Código:
// --------------------------------------------------------------------------------------------------------------------------------------
// WecTools DLL
// Version: 0.02
// --------------------------------------------------------------------------------------------------------------------------------------

#include <cstdlib>
#include <ctype.h>
#include <math.h>
#include <windows.h>
#include <time.h>
// --------------------------------------------------------------------------------------------------------------------------------------
#define RGSSApi extern "C" __declspec(dllexport)

// --------------------------------------------------------------------------------------------------------------------------------------
double round(double d)
{
   return floor(d + 0.5);
}
// --------------------------------------------------------------------------------------------------------------------------------------
BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved){
   switch (ul_reason_for_call){
      case DLL_PROCESS_ATTACH:
      case DLL_THREAD_ATTACH:
      case DLL_THREAD_DETACH:
      case DLL_PROCESS_DETACH:
      break;
   }
   return true;
}
// --------------------------------------------------------------------------------------------------------------------------------------
// Rect RGSS (rect.__id__ = object)
// RECTSTRUCT * rect = ((RGSSRECT*)(object<<1))->rectvars;
// --------------------------------------------------------------------------------------------------------------------------------------
typedef struct{
   DWORD unka;
   DWORD unkb;
   DWORD x; // x rect
   DWORD y; // y rect
   DWORD width; // width rect
   DWORD height; // height rect
}RECTSTRUCT;
typedef struct{
   DWORD flags;
   DWORD klass;
   void (*dmark) (void*);
   void (*dfree) (void*);
   RECTSTRUCT * rectvars;
}RGSSRECT;
// --------------------------------------------------------------------------------------------------------------------------------------
// Color RGSS (method 1) (color.__id__ = object)
// RGSSCOLOR *color = ((RGSSCOLOR*)(object << 1));
// color->data[1] = red, color->data[2] = green, color->data[3] = blue, color->data[4] = alpha
// --------------------------------------------------------------------------------------------------------------------------------------
typedef struct{
   DWORD flags;
   DWORD klass;
   void(*dmark) (void*);
   void(*dfree) (void*);
   double *data; //red is index 1, green is index 2, blue 3, alpha 4
}RGSSCOLOR;
// --------------------------------------------------------------------------------------------------------------------------------------
// Bitmap RGSS (method 1) (bitmap.__id__ = object)
// RGSSBMINFO *bitmap = ((RGSSBITMAP*)(object << 1))->bm->bminfo;
// --------------------------------------------------------------------------------------------------------------------------------------
typedef struct{
   DWORD unk1;
   DWORD unk2;
   BITMAPINFOHEADER *infoheader;
   RGSSCOLOR *firstRow;
   RGBQUAD *lastRow;
}RGSSBMINFO;
typedef struct{
   DWORD unk1;
   DWORD unk2;
   RGSSBMINFO *bminfo;
}BITMAPSTRUCT;
typedef struct{
   DWORD flags;
   DWORD klass;
   void(*dmark) (void*);
   void(*dfree) (void*);
   BITMAPSTRUCT *bm;
}RGSSBITMAP;
// --------------------------------------------------------------------------------------------------------------------------------------
// Color RGSS (method 2)
// RGSSRGBA *color = ((RGSSRGBA*)(object << 1));
// color->red = red, color->green = green, color->blue = blue, color->alpha = alpha
// --------------------------------------------------------------------------------------------------------------------------------------
typedef union{
   unsigned int pixel;
   struct{
      unsigned char blue;
      unsigned char green;
      unsigned char red;
      unsigned char alpha;
   };
}RGSSRGBA;
// --------------------------------------------------------------------------------------------------------------------------------------
// Bitmap RGSS (method 2)
// --------------------------------------------------------------------------------------------------------------------------------------
typedef struct{
    DWORD unk1;
    DWORD unk2;
    BITMAPINFOHEADER *infoheader;
    RGSSRGBA *firstRow;
    RGSSRGBA *lastRow;
}RGSSBMINFO2;
typedef struct{
    DWORD unk1;
    DWORD unk2;
    RGSSBMINFO2 *bminfo;
}BITMAPSTRUCT2;
typedef struct{
    DWORD flags;
    DWORD klass;
    void (*dmark) (void*);
    void (*dfree) (void*);
    BITMAPSTRUCT2 *bm;
}RGSSBITMAP2;
// --------------------------------------------------------------------------------------------------------------------------------------
// Table RGSS (table.__id__ = object)
// TABLESTRUCT * table = ((TABLEDATA*)(object<<1))->tablevars;
// --------------------------------------------------------------------------------------------------------------------------------------
typedef struct{
   DWORD unka; //0
   DWORD unkb; //0
   DWORD dimensions; // # of parameters
   DWORD xsize; // xsize
   DWORD ysize; // ysize (returns 1 if not specified)
   DWORD zsize; // zsize (returns 1 if not specified)
   DWORD total_elements; // xsize * ysize * zsize
   INT16 * data; // 1-D Array, where [x,y,z] can be found at index [x+(y*xsize)+(z*xsize*ysize)]
}TABLESTRUCT;
typedef struct{
   DWORD unk1;
   DWORD classname; // I think?
   DWORD unk3;
   DWORD unk4;
   TABLESTRUCT * tablevars;
}TABLEDATA;
// --------------------------------------------------------------------------------------------------------------------------------------

// --------------------------------------------------------------------------------------------------------------------------------------
int min(int a, int b){
   if (a>b)
      return b;
   else
      return a;
}
// --------------------------------------------------------------------------------------------------------------------------------------
int max(int a, int b){
   if (a>b)
      return a;
   else
      return b;
}

// --------------------------------------------------------------------------------------------------------------------------------------
// * Get Colors
// --------------------------------------------------------------------------------------------------------------------------------------

RGSSApi int* get_colors(long object){
   RGSSBMINFO2 *bitmap = ((RGSSBITMAP2*)(object << 1))->bm->bminfo;
   long width, height, x, y, x2, y2;
   RGSSRGBA *row;
   RGSSRGBA *lastrow;
   int *colors;
   width = bitmap->infoheader->biWidth;
   height = bitmap->infoheader->biHeight;
   row = bitmap->lastRow;
   colors = new int(width*height*4);
   for (y = 0; y < height; y++) {
      y2 = y * width * 4;
      for (x = 0; x < width; x++) {
         x2 = x * 4;
         colors[y2 + x2 + 0] = row->red;
         colors[y2 + x2 + 1] = row->green;
         colors[y2 + x2 + 2] = row->blue;
         colors[y2 + x2 + 3] = row->alpha;
         row++;
      }
   }
   return colors;
}

// --------------------------------------------------------------------------------------------------------------------------------------
// * Clear Rect
// --------------------------------------------------------------------------------------------------------------------------------------

RGSSApi BOOL clear_rect(long object, int x, int y, int w, int h){
   RGSSBMINFO *bitmap = ((RGSSBITMAP*)(object << 1))->bm->bminfo;
   DWORD rowsize;
   DWORD width, height;
   LPBYTE row;
   int i, e;
   if (!bitmap) return false;
   width = bitmap->infoheader->biWidth;
   height = bitmap->infoheader->biHeight;
   if (x>(int)width) x = width;
   if (y>(int)height) y = height;
   if (x<0) x = 0;
   if (y<0) y = 0;
   if (w<0) return false;
   if (h<0) return false;
   if (x + w>(int)width) w = width - x;
   if (y + h>(int)height) h = height - y;
   rowsize = width * 4;
   row = (LPBYTE)(bitmap->firstRow);
   row -= rowsize * y;
   for (i = y; i < y + h; i++) {
      LPBYTE thisrow = row;
      thisrow += 4 * x;
      for (e = x; e < x + w; e++) {
         thisrow[0] = 0;
         thisrow[1] = 0;
         thisrow[2] = 0;
         thisrow[3] = 0;
         thisrow += 4;
      }
      row -= rowsize;
   }
   return true;
}

// --------------------------------------------------------------------------------------------------------------------------------------
// * Fill Rect
// --------------------------------------------------------------------------------------------------------------------------------------

RGSSApi BOOL fill_rect(long object, int x, int y, int w, int h, int r, int g, int b, int a){
   RGSSBMINFO *bitmap = ((RGSSBITMAP*)(object << 1))->bm->bminfo;
   DWORD rowsize;
   DWORD width, height;
   LPBYTE row;
   int i, e;
   if (!bitmap) return false;
   width = bitmap->infoheader->biWidth;
   height = bitmap->infoheader->biHeight;
   if (x>(int)width) return false;
   if (y>(int)height) return false;
   if (x<0) w += x;
   if (x<0) x = 0;
   if (y<0) h += y;
   if (y<0) y = 0;
   if (w<0) return false;
   if (h<0) return false;
   if (x + w>(int)width) w = width - x;
   if (y + h>(int)height) h = height - y;
   rowsize = width * 4;
   row = (LPBYTE)(bitmap->firstRow);
   row -= rowsize * y;
   for (i = y; i < y + h; i++) {
      LPBYTE thisrow = row;
      thisrow += 4 * x;
      for (e = x; e < x + w; e++) {
         thisrow[0] = b;
         thisrow[1] = g;
         thisrow[2] = r;
         thisrow[3] = a;
         thisrow += 4;
      }
      row -= rowsize;
   }
   return true;
}

// --------------------------------------------------------------------------------------------------------------------------------------
// * Blt
// --------------------------------------------------------------------------------------------------------------------------------------

RGSSApi BOOL blt(long object, long source, int x, int y, int srcx, int srcy, int w, int h, int opacity){
   RGSSBMINFO *bitmap = ((RGSSBITMAP*)(object << 1))->bm->bminfo;
   RGSSBMINFO *src = ((RGSSBITMAP*)(source << 1))->bm->bminfo;
   DWORD rowsize, srcrowsize;
   DWORD width, height, srcwidth, srcheight;
   LPBYTE row, srcrow;
   int i, e, sa;
   int m2 = 255 * 255;
   if (!bitmap) return false;
   if (opacity == 0) return false;
   width = bitmap->infoheader->biWidth;
   height = bitmap->infoheader->biHeight;
   srcwidth = src->infoheader->biWidth;
   srcheight = src->infoheader->biHeight;
   if (srcx>(int)srcwidth) srcx = srcwidth;
   if (srcy>(int)srcheight) srcy = srcheight;
   if (srcx<0) srcx = 0;
   if (srcy<0) srcy = 0;
   if (srcwidth<0) return false;
   if (srcheight<0) return false;
   if (srcx + w>(int)srcwidth) w = srcwidth - srcx;
   if (srcy + h>(int)srcheight) h = srcheight - srcy;
   if (x>(int)width) x = width;
   if (y>(int)height) y = height;
   if (x<0) x = 0;
   if (y<0) y = 0;
   if (w<0) return false;
   if (h<0) return false;
   if (x + w>(int)width) w = width - x;
   if (y + h>(int)height) h = height - y;
   rowsize = width * 4;
   srcrowsize = srcwidth * 4;
   row = (LPBYTE)(bitmap->firstRow);
   srcrow = (LPBYTE)(src->firstRow);
   row -= rowsize * y;
   srcrow -= srcrowsize * srcy;
   for (i = y; i < y + h; i++) {
      LPBYTE thisrow = row;
      LPBYTE thissrcrow = srcrow;
      thisrow += 4 * x;
      thissrcrow += 4 * srcx;
      for (e = x; e < x + w; e++) {
         sa = thissrcrow[3] * opacity;
         if (sa == m2) {
            thisrow[0] = thissrcrow[0];
            thisrow[1] = thissrcrow[1];
            thisrow[2] = thissrcrow[2];
            thisrow[3] = 255;
         }
         else if (thisrow[3] == 0) {
            thisrow[0] = thissrcrow[0];
            thisrow[1] = thissrcrow[1];
            thisrow[2] = thissrcrow[2];
         thisrow[3] = sa / 255;
         }
         else if (sa != 0) {
            sa /= 255;
            if (sa == 0) continue;
            thisrow[0] = thissrcrow[0] * sa / 255 + thisrow[0] * (255 - sa) / 255;
            thisrow[1] = thissrcrow[1] * sa / 255 + thisrow[1] * (255 - sa) / 255;
            thisrow[2] = thissrcrow[2] * sa / 255 + thisrow[2] * (255 - sa) / 255;
            thisrow[3] = min(thisrow[3] + sa * sa / 255, 255);
         }
         thisrow += 4;
         thissrcrow += 4;
      }
      row -= rowsize;
      srcrow -= srcrowsize;
   }
   return true;
}

// --------------------------------------------------------------------------------------------------------------------------------------
// * Get Pixel
// --------------------------------------------------------------------------------------------------------------------------------------

RGSSApi BOOL get_pixel(long object, long x, long y,long color_dest){
   RGSSBMINFO *bitmap = ((RGSSBITMAP*)(object << 1))->bm->bminfo;
   RGSSCOLOR *color = ((RGSSCOLOR*)(color_dest << 1));
   if (!bitmap or !color) return false;
   color->data[1] = 0; // red
   color->data[2] = 0; // green
   color->data[3] = 0; // blue
   color->data[4] = 0; // alpha
   DWORD width = bitmap->infoheader->biWidth;
   DWORD height = bitmap->infoheader->biHeight;
   if (x < 0 or x >= width or y < 0 or y >= height) return false;
   DWORD rowsize = width * 4;
   LPBYTE thisrow = (LPBYTE)(bitmap->firstRow);
   thisrow += (x * 4);
   thisrow -= (rowsize * y);
   color->data[1] = thisrow[2]; // red
   color->data[2] = thisrow[1]; // green
   color->data[3] = thisrow[0]; // blue
   color->data[4] = thisrow[3]; // alpha
   return true;
}

// --------------------------------------------------------------------------------------------------------------------------------------
// * Set Pixel
// --------------------------------------------------------------------------------------------------------------------------------------

RGSSApi BOOL set_pixel(long object, long x, long y,long color_dest){
   RGSSBMINFO *bitmap = ((RGSSBITMAP*)(object << 1))->bm->bminfo;
   RGSSCOLOR *color = ((RGSSCOLOR*)(color_dest << 1));
   if (!bitmap or !color) return false;
   DWORD width = bitmap->infoheader->biWidth;
   DWORD height = bitmap->infoheader->biHeight;
   if (x < 0 or x >= width or y < 0 or y >= height) return false;
   DWORD rowsize = width * 4;
   LPBYTE thisrow = (LPBYTE)(bitmap->firstRow);
   thisrow += (x  * 4);
   thisrow -= (rowsize * y);
   thisrow[2] = color->data[1]; // red
   thisrow[1] = color->data[2]; // green
   thisrow[0] = color->data[3]; // blue
   thisrow[3] = color->data[4]; // alpha
   return true;
}

// --------------------------------------------------------------------------------------------------------------------------------------
// * Cut
// --------------------------------------------------------------------------------------------------------------------------------------

RGSSApi BOOL cut(long object1, long object2, long x, long y, long color_dest){
   RGSSBMINFO *bitmap1 = ((RGSSBITMAP*)(object1 << 1))->bm->bminfo;
   RGSSBMINFO *bitmap2 = ((RGSSBITMAP*)(object2 << 1))->bm->bminfo;
   RGSSCOLOR *color = ((RGSSCOLOR*)(color_dest << 1));
   if (!bitmap1 or !bitmap2 or !color) return false;
   DWORD width = bitmap2->infoheader->biWidth;
   DWORD height = bitmap2->infoheader->biHeight;
   if (width < 1 or height < 1) return false;
   int ix, iy;
   for (iy = 0; iy < height; iy++) {
      for (ix = 0; ix < width; ix++) {
         get_pixel(object1, ix + x, iy + y, color_dest);
         set_pixel(object2, ix, iy, color_dest);
      }
   }
   return true;
}

// --------------------------------------------------------------------------------------------------------------------------------------
// * Draw Bitmap
// --------------------------------------------------------------------------------------------------------------------------------------

RGSSApi BOOL draw_bitmap(long object1, long object2, long x, long y, long color_dest){
   RGSSBMINFO *bitmap1 = ((RGSSBITMAP*)(object1 << 1))->bm->bminfo;
   RGSSBMINFO *bitmap2 = ((RGSSBITMAP*)(object2 << 1))->bm->bminfo;
   RGSSCOLOR *color = ((RGSSCOLOR*)(color_dest << 1));
   if (!bitmap1 or !bitmap2 or !color) return false;
   DWORD width = bitmap2->infoheader->biWidth;
   DWORD height = bitmap2->infoheader->biHeight;
   DWORD selfwidth = bitmap1->infoheader->biWidth;
   DWORD selfheight = bitmap1->infoheader->biHeight;
   if (width < 1 or height < 1) return false;
   if (selfwidth < 1 or selfheight < 1) return false;
   int minwidth, minheight;
   minwidth = min(width, selfwidth - x);
   minheight = min(height, selfheight - y);
   if (minwidth < 1 or minheight < 1) return false;
   int ix, iy, dx, dy;
   for (iy = 0; iy < minheight; iy++) {
      for (ix = 0; ix < minwidth; ix++) {
         dx = ix % width;
         dy = iy % height;
         get_pixel(object2, dx, dy, color_dest);
         set_pixel(object1, ix + x, iy + y, color_dest);
      }
   }
   return true;
}

// --------------------------------------------------------------------------------------------------------------------------------------

A ver si alguien más se apunta ;D

PD: Por cierto me han comentado que zoom y opacity de Bitmap seguramente se puedan recrear usando stretch_blt y por lo tanto no haría falta pasarlos.
Edit: Confirmado, esos dos métodos se pueden hacer con stretch_blt, que ya es significativamente más rápido, así que los quito de la lista.
avatar
Wecoc
Administrador
Administrador



Créditos 8988

Gracias : 442

Volver arriba Ir abajo

RPG Maker XP Re: Creación de una librería para WecTools

Mensaje por Contenido patrocinado


Contenido patrocinado


Volver arriba Ir abajo

Ver el tema anterior Ver el tema siguiente Volver arriba


Permisos de este foro:
No puedes responder a temas en este foro.