查看: 66|回复: 0

[转载发布] ImageEx

[复制链接]
  • TA的每日心情
    开心
    2024-5-10 09:55
  • 签到天数: 37 天

    连续签到: 3 天

    [LV.5]常住居民I

    2028

    主题

    32

    回帖

    7260

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    VIP
    0
    卡币
    5184
    OK点
    16
    积分
    7260
    发表于 同元一千年八月九日(秋) | 显示全部楼层 |阅读模式
    感觉很鸡肋,电脑里扔了2个多月,毕竟都写了,发贴混点经验。
    ImageEx_rmxp.dll  VS2015  C++语言编写(因为有库是C++的,其实都是按C写的)。


    RUBY 代码
    [code]module ImageEx
      dll = "ImageEx_rmxp.dll"

      # ———— png 与 jpeg ——————————————————
      # 仅支持 jpeg(Gray/RGB)、png(Gray/GrayAlpha/RGB/RGBA)
      # 使用libjpeg/libpng
      # ————————————————————————————

      # 支持的模式会转换至BGRA,不支持的模式会返回-1。
      # filename_uft8, bitmap_obj_id
      Load_JPG = Win32API.new(dll, 'bitmap_load_jpg', 'PL', 'L')
      # filename_utf8, bitmap_obj_id
      # channels  1或3    BGRA会转换至支持的对应模式
      # quality   0..100  质量越好,文件越大
      Save_JPG = Win32API.new(dll, 'bitmap_save_to_jpg', 'PLLL', 'L')

      # 支持的模式会转换至BGRA,不支持的模式无效操作。
      # filename_uft8, bitmap_obj_id
      Load_PNG = Win32API.new(dll, 'bitmap_load_png', 'PL', 'L')
      # filename_utf8, bitmap_obj_id
      # channels  1..4  BGRA会转换至支持的对应模式
      Save_PNG = Win32API.new(dll, 'bitmap_save_to_png', 'PLL', 'L')


      # ———— gif 与 webp ——————————————————————————
      # 仅支持读取,无论是否使用线程(Win32 CreateThread)都需要释放(调用dispose)
      # gif中disposal_method不支持DISPOSE_PREVIOUS
      # 播放效果视文件而定,可能会“画面闪烁”
      # 效率:非线程模式,640*480大小,读取一帧 gif:1000次/秒 webp:300次/秒
      #            参照,640*480大小的Bitmap#blt    260+次/秒         
      # 使用libgif/libwebp
      # ————————————————————————————————————

      # filename_utf8   : utf8编码的文件名。
      # sprite_obj_id   : RMXP 精灵(Sprite) 对象的 object_id,精灵需设置好其位图。
      # gif_cell_string : GIF_CELL_SIZE字节的字符串,用来保存一些数据。
      # play_mode : 0..3位 是否抠图。抠图效果不错,对效率影响不大。      
      #                    1:抠除黑色;2:抠除白色;其他(0/3):原图。
      #             4..7位 是否线程模式。  0:不使用;非0:使用。
      # loop_count : 自定义播放次数。 0:文件默认次数;负数:一直播放;正数:指定次数。
      Show_GIF = Win32API.new(dll, 'show_gif', 'PLPLL', 'L')
      Draw_GIF = Win32API.new(dll, 'draw_gif', 'L', 'L')
      Free_GIF = Win32API.new(dll, 'free_gif', 'L', 'L')  
      GIF = 0x666967
      GIF_CELL_SIZE = Show_GIF.call(nil, 0, 0, 0, 0)

      # 参数四 mode : 是否线程模式。  0:不使用;非0:使用。
      # 其余参数,参见Show_GIF
      Show_WEBP = Win32API.new(dll, 'show_webp', 'PLPLL', 'L')
      Draw_WEBP = Win32API.new(dll, 'draw_webp', 'L', 'L')
      Free_WEBP = Win32API.new(dll, 'free_webp', 'L', 'L')  
      WEBP = 0x70626577
      WEBP_CELL_SIZE = Show_WEBP.call(nil, 0, 0, 0, 0)

      # 这两个方法其实没什么用……
      defself.get_png_wh(filename)
        w = h = 0
        File.open(filename, 'rb')do |f|
          if f.read(8) == "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A"
            f.seek(8, IO::SEEK_CUR)
            w, h = f.read(8).unpack('NN')
          end
        end
        return w, h
      end

      defself.get_jpg_wh(filename)
        w = h = 0
        File.open(filename, 'rb')do |f|
          if f.read(2) == "\xFF\xD8"
            sof0 = "\xFF\xC0"
            while(buf = f.read(2)) != sof0
              size = f.read(2).unpack('n')
              f.seek(size - 2, IO::SEEK_CUR)
            end
            f.seek(3, IO::SEEK_CUR)
            h, w = f.read(4).unpack('nn')
          end
        end
        return w, h
      end
    end


    class Bitmap
      def to_int
        self.__id__
      end

      def save_jpg(filename, channels = 3, quality = 90)
        ImageEx::Save_JPG.call(filename, self, channels, quality)
      end

      def save_png(filename, channels = 4)
        ImageEx::Save_PNG.call(filename, self, channels)
      end

      # 读取图片至位图,主要是同样大小的单帧静态图片的动画,避免重复新建Bitmap  
      def load_jpg(filename)
        ImageEx::Load_JPG.call(filename, self)
      end

      def load_png(filename)
        ImageEx::Load_PNG.call(filename, self)
      end   
    end

    # GifSprite/WebpSprite并没打算复用,用完就释放掉,再新建
    class GifSprite < Sprite

      def initialize(filename, mode = 0, loop_count = 0, viewport = nil)

        w = h = 0
        File.open(filename, "rb")do |f|
          if(f.read(6) =~ /GIF8[79]a/)
            w, h = f.read(4).unpack('SS')
          end
        end

        if w == 0 || h == 0
          raise"#{self.class} ERR: #{filename} 可能不是 gif 图片"
        end

        super(viewport)

        self.bitmap = Bitmap.new(w, h)
        self.instance_evaldo
          def bitmap=(obj)
          end
        end

        self.bitmap.instance_evaldo
          alias:dispose_ori:dispose
          def dispose(tag = 0)
            dispose_ori if tag == ImageEx::GIF
          end
        end

        @cell = "\0" * ImageEx::GIF_CELL_SIZE
        err = ImageEx::Show_GIF.call(filename, self.__id__, @cell.__id__,
          mode, loop_count)

        case err
        when-1   thenraise"#{self.class} ERR: 打开 #{filename} 文件失败"
        when-2   thenraise"#{self.class} ERR: 位图 与 #{filename} 不符"
        when-3   thenraise"#{self.class} ERR: @cell 参数不符合要求"
        when-100thenraise"#{self.class} ERR: 解析 #{filename} 失败"
        when-101thenraise"#{self.class} ERR: 内存不足"
        end

        @cell_ptr = [@cell].pack('p').unpack('L')[0]
        @cell.freeze

        @use_thread = (mode & 0xF0 != 0) && (err != -99)
        @delay = 0
        @loop_over = false
      end

      def over?
        return@loop_overif@use_thread == false
        i, c = @cell.unpack('@16LL')
        return c != 0 && i >= c
      end

      def update_frame
        returnif(@loop_over | @use_thread) == true
        returnif(self.disposed? | self.bitmap.disposed?) == true
        returnifself.visible == false || self.opacity == 0

        if@delay > 0
          @delay -= 1
        else
          ms = ImageEx::Draw_GIF.call(@cell_ptr)
          if ms < 0
            @loop_over = true
          else
            @delay = (ms * Graphics.frame_rate + 999) / 1000
          end
        end
      end

      def dispose
        returnifself.disposed? == true
        ImageEx::Free_GIF.call(@cell_ptr)
        self.bitmap.dispose(ImageEx::GIF)
        super
      end
    end


    class WebpSprite < Sprite

      def initialize(filename, mode = 0, loop_count = 0, viewport = nil)

        w = h = 0
        File.open(filename, "rb")do |f|
          if(f.read(4) == "RIFF")
            f.seek(4, IO::SEEK_CUR)

            if(f.read(4) == "WEBP")        
              chunk = f.read(4)
              f.seek(4, IO::SEEK_CUR)

              if(chunk == "VP8 ")
                if(f.read(1).unpack('C')[0][0] == 0)
                  f.seek(2, IO::SEEK_CUR)
                  if(f.read(3) == "\x9D\x01\x2A")
                    w, h = f.read(4).unpack('SS')
                  end
                end
              elsif(chunk == "VP8L")
                f.seek(1, IO::SEEK_CUR)
                n = f.read(4).unpack('L')[0]

                w = (n & 0x3FFF) + 1
                h = ((n & 0xFFFC000) >> 14) + 1
              elsif(chunk == "VP8X")
                f.seek(4, IO::SEEK_CUR)

                w, w16, h, h16 = f.read(6).unpack('SCSC')
                w += (w16

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有账号?立即注册

    x
    天天去同能,天天有童年!
    回复 论坛版权

    使用道具 举报

    ahome_bigavatar:guest
    ahome_bigavatar:welcomelogin
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|Archiver|手机版|小黑屋|同能RPG制作大师 ( 沪ICP备12027754号-3 )

    GMT+8, 2024-5-21 02:22 , Processed in 0.047597 second(s), 42 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.

    快速回复 返回顶部 返回列表