├── CartoonGAN ├── network │ ├── __init__.py │ └── Transformer.py ├── requirements.txt ├── lazy.py └── app.py ├── README.md ├── AnimeGAN ├── video.py ├── lazy.py └── quicklook.py └── LICENSE /CartoonGAN/network/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /CartoonGAN/requirements.txt: -------------------------------------------------------------------------------- 1 | gradio==3.0.5 2 | huggingface-hub==0.6.0 3 | pillow==9.1.1 4 | torch==1.11.0 5 | torchvision==0.12.0 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Have fun with the model: AnimeGAN 2 | 3 | Talk about how to use Anime GAN to generate video. (both CPU and GPU) 4 | -------------------------------------------------------------------------------- /AnimeGAN/video.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import towhee 3 | 4 | def parse_args(): 5 | desc = "AnimeGAN CLI by soulteary" 6 | parser = argparse.ArgumentParser(description=desc) 7 | parser.add_argument('--model', type=str, default='Shinkai', help='origin / facepaintv2 / hayao / paprika / shinkai') 8 | parser.add_argument('--device', type=str, default='cpu', help='cpu / cuda') 9 | parser.add_argument('--input', type=str, default='./video.mp4', help='video filename') 10 | parser.add_argument('--output', type=str, default='./result/', help='output path') 11 | parser.add_argument('--rate', type=int, default=15, help='video rate') 12 | """ 13 | If you want to resize, you need to specify both --resize and --maxsize 14 | """ 15 | return parser.parse_args() 16 | 17 | 18 | arg = parse_args() 19 | towhee.read_video(arg.input) \ 20 | .set_parallel(5) \ 21 | .img2img_translation.animegan(model_name = arg.model, device=arg.device) \ 22 | .to_video(arg.output + '/result.mp4', 'x264', arg.rate) -------------------------------------------------------------------------------- /CartoonGAN/lazy.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import towhee 3 | 4 | def parse_args(): 5 | desc = "CartoonGAN CLI by soulteary" 6 | parser = argparse.ArgumentParser(description=desc) 7 | parser.add_argument('--model', type=str, default='Shinkai', help='Shinkai / Hosoda / Miyazaki / Kon') 8 | parser.add_argument('--device', type=str, default='cpu', help='cpu / cuda') 9 | parser.add_argument('--input', type=str, default='./images', help='images directory') 10 | parser.add_argument('--output', type=str, default='./result/', help='output path') 11 | """ 12 | If you want to resize, you need to specify both --resize and --maxsize 13 | """ 14 | return parser.parse_args() 15 | 16 | arg = parse_args() 17 | towhee.glob['path'](arg.input + "/*.png") \ 18 | .set_parallel(5) \ 19 | .image_decode['path', 'img']() \ 20 | .img2img_translation.cartoongan['img', 'new_img'](model_name = arg.model, device=arg.device) \ 21 | .save_image[('new_img', 'path'), 'new_path'](dir=arg.output + "/", format="png") \ 22 | .to_list() -------------------------------------------------------------------------------- /AnimeGAN/lazy.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import towhee 3 | 4 | def parse_args(): 5 | desc = "AnimeGAN CLI by soulteary" 6 | parser = argparse.ArgumentParser(description=desc) 7 | parser.add_argument('--model', type=str, default='Shinkai', help='origin / facepaintv2 / hayao / paprika / shinkai') 8 | parser.add_argument('--device', type=str, default='cpu', help='cpu / cuda') 9 | parser.add_argument('--input', type=str, default='./images', help='images directory') 10 | parser.add_argument('--output', type=str, default='./result/', help='output path') 11 | """ 12 | If you want to resize, you need to specify both --resize and --maxsize 13 | """ 14 | return parser.parse_args() 15 | 16 | arg = parse_args() 17 | towhee.glob['path'](arg.input + "/*.png") \ 18 | .set_parallel(5) \ 19 | .image_decode['path', 'img']() \ 20 | .img2img_translation.animegan['img', 'new_img'](model_name = arg.model, device=arg.device) \ 21 | .save_image[('new_img', 'path'), 'new_path'](dir=arg.output + "/", format="png") \ 22 | .to_list() -------------------------------------------------------------------------------- /AnimeGAN/quicklook.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import towhee 3 | 4 | def parse_args(): 5 | desc = "AnimeGAN CLI by soulteary" 6 | parser = argparse.ArgumentParser(description=desc) 7 | parser.add_argument('--model', type=str, default='Shinkai', help='origin / facepaintv2 / hayao / paprika / shinkai') 8 | parser.add_argument('--device', type=str, default='cpu', help='cpu / cuda') 9 | parser.add_argument('--input', type=str, default='./video.mp4', help='video filename') 10 | parser.add_argument('--output', type=str, default='./result/', help='output path') 11 | parser.add_argument('--rate', type=int, default=15, help='video rate') 12 | """ 13 | If you want to resize, you need to specify both --resize and --maxsize 14 | """ 15 | return parser.parse_args() 16 | 17 | 18 | arg = parse_args() 19 | towhee.read_video(arg.input) \ 20 | .set_parallel(5) \ 21 | .image_resize(fx=0.2, fy=0.2) \ 22 | .img2img_translation.animegan(model_name = arg.model, device=arg.device) \ 23 | .to_video(arg.output + '/result.mp4', 'x264', arg.rate) -------------------------------------------------------------------------------- /CartoonGAN/app.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import glob, os 3 | import time 4 | from pathlib import Path 5 | from PIL import Image 6 | 7 | import torch 8 | import numpy as np 9 | import torchvision.transforms as transforms 10 | from torch.autograd import Variable 11 | from network.Transformer import Transformer 12 | from huggingface_hub import hf_hub_download 13 | 14 | import logging 15 | 16 | logging.basicConfig(level=logging.INFO) 17 | logger = logging.getLogger(__name__) 18 | 19 | def parse_args(): 20 | desc = "CartoonGAN CLI by soulteary" 21 | parser = argparse.ArgumentParser(description=desc) 22 | parser.add_argument('--model', type=str, default='Shinkai', help='Shinkai / Hosoda / Miyazaki / Kon') 23 | parser.add_argument('--input', type=str, default='./images', help='images directory') 24 | parser.add_argument('--output', type=str, default='./result/', help='output path') 25 | parser.add_argument('--resize', type=int, default=0, 26 | help='Do you need a program to adjust the image size?') 27 | parser.add_argument('--maxsize', type=int, default=0, 28 | help='your desired image output size') 29 | """ 30 | If you want to resize, you need to specify both --resize and --maxsize 31 | """ 32 | return parser.parse_args() 33 | 34 | def prepare_dirs(path): 35 | Path(path).mkdir(parents=True, exist_ok=True) 36 | 37 | 38 | arg = parse_args() 39 | 40 | 41 | enable_gpu = torch.cuda.is_available() 42 | 43 | if enable_gpu: 44 | # If you have multiple cards, 45 | # you can assign to a specific card, eg: "cuda:0"("cuda") or "cuda:1" 46 | # Use the first card by default: "cuda" 47 | device = torch.device("cuda") 48 | else: 49 | device = "cpu" 50 | 51 | def get_model(style): 52 | # Makoto Shinkai 53 | if style == "Shinkai": 54 | MODEL_REPO_SHINKAI = "akiyamasho/AnimeBackgroundGAN-Shinkai" 55 | MODEL_FILE_SHINKAI = "shinkai_makoto.pth" 56 | model_hfhub = hf_hub_download(repo_id=MODEL_REPO_SHINKAI, filename=MODEL_FILE_SHINKAI) 57 | # Mamoru Hosoda 58 | elif style == "Hosoda": 59 | MODEL_REPO_HOSODA = "akiyamasho/AnimeBackgroundGAN-Hosoda" 60 | MODEL_FILE_HOSODA = "hosoda_mamoru.pth" 61 | model_hfhub = hf_hub_download(repo_id=MODEL_REPO_HOSODA, filename=MODEL_FILE_HOSODA) 62 | # Hayao Miyazaki 63 | elif style == "Miyazaki": 64 | MODEL_REPO_MIYAZAKI = "akiyamasho/AnimeBackgroundGAN-Miyazaki" 65 | MODEL_FILE_MIYAZAKI = "miyazaki_hayao.pth" 66 | model_hfhub = hf_hub_download(repo_id=MODEL_REPO_MIYAZAKI, filename=MODEL_FILE_MIYAZAKI) 67 | # Satoshi Kon 68 | elif style == "Kon": 69 | MODEL_REPO_KON = "akiyamasho/AnimeBackgroundGAN-Kon" 70 | MODEL_FILE_KON = "kon_satoshi.pth" 71 | model_hfhub = hf_hub_download(repo_id=MODEL_REPO_KON, filename=MODEL_FILE_KON) 72 | 73 | model = Transformer() 74 | model.load_state_dict(torch.load(model_hfhub, device)) 75 | if enable_gpu: 76 | model = model.to(device) 77 | model.eval() 78 | return model 79 | 80 | def inference(img, model): 81 | # load image 82 | input_image = img.convert("RGB") 83 | input_image = np.asarray(input_image) 84 | # RGB -> BGR 85 | input_image = input_image[:, :, [2, 1, 0]] 86 | input_image = transforms.ToTensor()(input_image).unsqueeze(0) 87 | # preprocess, (-1, 1) 88 | input_image = -1 + 2 * input_image 89 | 90 | if enable_gpu: 91 | logger.info(f"CUDA found. Using GPU.") 92 | # Allows to specify a card for calculation 93 | input_image = Variable(input_image).to(device) 94 | else: 95 | logger.info(f"CUDA not found. Using CPU.") 96 | input_image = Variable(input_image).float() 97 | 98 | # forward 99 | output_image = model(input_image) 100 | output_image = output_image[0] 101 | # BGR -> RGB 102 | output_image = output_image[[2, 1, 0], :, :] 103 | output_image = output_image.data.cpu().float() * 0.5 + 0.5 104 | 105 | return transforms.ToPILImage()(output_image) 106 | 107 | 108 | prepare_dirs(arg.output) 109 | 110 | model = get_model(arg.model) 111 | 112 | enable_resize = False 113 | max_dimensions = -1 114 | if arg.maxsize > 0: 115 | max_dimensions = arg.maxsize 116 | if arg.resize : 117 | enable_resize = True 118 | 119 | globPattern = arg.input + "/*.png" 120 | 121 | for filePath in glob.glob(globPattern): 122 | basename = os.path.basename(filePath) 123 | with Image.open(filePath) as img: 124 | if(enable_resize): 125 | img.thumbnail((max_dimensions, max_dimensions), Image.Resampling.LANCZOS) 126 | 127 | start_time = time.time() 128 | inference(img, model).save(arg.output + "/" + basename, "PNG") 129 | print("--- %s seconds ---" % (time.time() - start_time)) 130 | -------------------------------------------------------------------------------- /CartoonGAN/network/Transformer.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | 5 | 6 | class Transformer(nn.Module): 7 | def __init__(self): 8 | super(Transformer, self).__init__() 9 | # 10 | self.refpad01_1 = nn.ReflectionPad2d(3) 11 | self.conv01_1 = nn.Conv2d(3, 64, 7) 12 | self.in01_1 = InstanceNormalization(64) 13 | # relu 14 | self.conv02_1 = nn.Conv2d(64, 128, 3, 2, 1) 15 | self.conv02_2 = nn.Conv2d(128, 128, 3, 1, 1) 16 | self.in02_1 = InstanceNormalization(128) 17 | # relu 18 | self.conv03_1 = nn.Conv2d(128, 256, 3, 2, 1) 19 | self.conv03_2 = nn.Conv2d(256, 256, 3, 1, 1) 20 | self.in03_1 = InstanceNormalization(256) 21 | # relu 22 | 23 | ## res block 1 24 | self.refpad04_1 = nn.ReflectionPad2d(1) 25 | self.conv04_1 = nn.Conv2d(256, 256, 3) 26 | self.in04_1 = InstanceNormalization(256) 27 | # relu 28 | self.refpad04_2 = nn.ReflectionPad2d(1) 29 | self.conv04_2 = nn.Conv2d(256, 256, 3) 30 | self.in04_2 = InstanceNormalization(256) 31 | # + input 32 | 33 | ## res block 2 34 | self.refpad05_1 = nn.ReflectionPad2d(1) 35 | self.conv05_1 = nn.Conv2d(256, 256, 3) 36 | self.in05_1 = InstanceNormalization(256) 37 | # relu 38 | self.refpad05_2 = nn.ReflectionPad2d(1) 39 | self.conv05_2 = nn.Conv2d(256, 256, 3) 40 | self.in05_2 = InstanceNormalization(256) 41 | # + input 42 | 43 | ## res block 3 44 | self.refpad06_1 = nn.ReflectionPad2d(1) 45 | self.conv06_1 = nn.Conv2d(256, 256, 3) 46 | self.in06_1 = InstanceNormalization(256) 47 | # relu 48 | self.refpad06_2 = nn.ReflectionPad2d(1) 49 | self.conv06_2 = nn.Conv2d(256, 256, 3) 50 | self.in06_2 = InstanceNormalization(256) 51 | # + input 52 | 53 | ## res block 4 54 | self.refpad07_1 = nn.ReflectionPad2d(1) 55 | self.conv07_1 = nn.Conv2d(256, 256, 3) 56 | self.in07_1 = InstanceNormalization(256) 57 | # relu 58 | self.refpad07_2 = nn.ReflectionPad2d(1) 59 | self.conv07_2 = nn.Conv2d(256, 256, 3) 60 | self.in07_2 = InstanceNormalization(256) 61 | # + input 62 | 63 | ## res block 5 64 | self.refpad08_1 = nn.ReflectionPad2d(1) 65 | self.conv08_1 = nn.Conv2d(256, 256, 3) 66 | self.in08_1 = InstanceNormalization(256) 67 | # relu 68 | self.refpad08_2 = nn.ReflectionPad2d(1) 69 | self.conv08_2 = nn.Conv2d(256, 256, 3) 70 | self.in08_2 = InstanceNormalization(256) 71 | # + input 72 | 73 | ## res block 6 74 | self.refpad09_1 = nn.ReflectionPad2d(1) 75 | self.conv09_1 = nn.Conv2d(256, 256, 3) 76 | self.in09_1 = InstanceNormalization(256) 77 | # relu 78 | self.refpad09_2 = nn.ReflectionPad2d(1) 79 | self.conv09_2 = nn.Conv2d(256, 256, 3) 80 | self.in09_2 = InstanceNormalization(256) 81 | # + input 82 | 83 | ## res block 7 84 | self.refpad10_1 = nn.ReflectionPad2d(1) 85 | self.conv10_1 = nn.Conv2d(256, 256, 3) 86 | self.in10_1 = InstanceNormalization(256) 87 | # relu 88 | self.refpad10_2 = nn.ReflectionPad2d(1) 89 | self.conv10_2 = nn.Conv2d(256, 256, 3) 90 | self.in10_2 = InstanceNormalization(256) 91 | # + input 92 | 93 | ## res block 8 94 | self.refpad11_1 = nn.ReflectionPad2d(1) 95 | self.conv11_1 = nn.Conv2d(256, 256, 3) 96 | self.in11_1 = InstanceNormalization(256) 97 | # relu 98 | self.refpad11_2 = nn.ReflectionPad2d(1) 99 | self.conv11_2 = nn.Conv2d(256, 256, 3) 100 | self.in11_2 = InstanceNormalization(256) 101 | # + input 102 | 103 | ##------------------------------------## 104 | self.deconv01_1 = nn.ConvTranspose2d(256, 128, 3, 2, 1, 1) 105 | self.deconv01_2 = nn.Conv2d(128, 128, 3, 1, 1) 106 | self.in12_1 = InstanceNormalization(128) 107 | # relu 108 | self.deconv02_1 = nn.ConvTranspose2d(128, 64, 3, 2, 1, 1) 109 | self.deconv02_2 = nn.Conv2d(64, 64, 3, 1, 1) 110 | self.in13_1 = InstanceNormalization(64) 111 | # relu 112 | self.refpad12_1 = nn.ReflectionPad2d(3) 113 | self.deconv03_1 = nn.Conv2d(64, 3, 7) 114 | # tanh 115 | 116 | def forward(self, x): 117 | y = F.relu(self.in01_1(self.conv01_1(self.refpad01_1(x)))) 118 | y = F.relu(self.in02_1(self.conv02_2(self.conv02_1(y)))) 119 | t04 = F.relu(self.in03_1(self.conv03_2(self.conv03_1(y)))) 120 | 121 | ## 122 | y = F.relu(self.in04_1(self.conv04_1(self.refpad04_1(t04)))) 123 | t05 = self.in04_2(self.conv04_2(self.refpad04_2(y))) + t04 124 | 125 | y = F.relu(self.in05_1(self.conv05_1(self.refpad05_1(t05)))) 126 | t06 = self.in05_2(self.conv05_2(self.refpad05_2(y))) + t05 127 | 128 | y = F.relu(self.in06_1(self.conv06_1(self.refpad06_1(t06)))) 129 | t07 = self.in06_2(self.conv06_2(self.refpad06_2(y))) + t06 130 | 131 | y = F.relu(self.in07_1(self.conv07_1(self.refpad07_1(t07)))) 132 | t08 = self.in07_2(self.conv07_2(self.refpad07_2(y))) + t07 133 | 134 | y = F.relu(self.in08_1(self.conv08_1(self.refpad08_1(t08)))) 135 | t09 = self.in08_2(self.conv08_2(self.refpad08_2(y))) + t08 136 | 137 | y = F.relu(self.in09_1(self.conv09_1(self.refpad09_1(t09)))) 138 | t10 = self.in09_2(self.conv09_2(self.refpad09_2(y))) + t09 139 | 140 | y = F.relu(self.in10_1(self.conv10_1(self.refpad10_1(t10)))) 141 | t11 = self.in10_2(self.conv10_2(self.refpad10_2(y))) + t10 142 | 143 | y = F.relu(self.in11_1(self.conv11_1(self.refpad11_1(t11)))) 144 | y = self.in11_2(self.conv11_2(self.refpad11_2(y))) + t11 145 | ## 146 | 147 | y = F.relu(self.in12_1(self.deconv01_2(self.deconv01_1(y)))) 148 | y = F.relu(self.in13_1(self.deconv02_2(self.deconv02_1(y)))) 149 | y = torch.tanh(self.deconv03_1(self.refpad12_1(y))) 150 | 151 | return y 152 | 153 | 154 | class InstanceNormalization(nn.Module): 155 | def __init__(self, dim, eps=1e-9): 156 | super(InstanceNormalization, self).__init__() 157 | self.scale = nn.Parameter(torch.FloatTensor(dim)) 158 | self.shift = nn.Parameter(torch.FloatTensor(dim)) 159 | self.eps = eps 160 | self._reset_parameters() 161 | 162 | def _reset_parameters(self): 163 | self.scale.data.uniform_() 164 | self.shift.data.zero_() 165 | 166 | def __call__(self, x): 167 | n = x.size(2) * x.size(3) 168 | t = x.view(x.size(0), x.size(1), n) 169 | mean = torch.mean(t, 2).unsqueeze(2).unsqueeze(3).expand_as(x) 170 | # Calculate the biased var. torch.var returns unbiased var 171 | var = torch.var(t, 2).unsqueeze(2).unsqueeze(3).expand_as(x) * ( 172 | (n - 1) / float(n) 173 | ) 174 | scale_broadcast = self.scale.unsqueeze(1).unsqueeze(1).unsqueeze(0) 175 | scale_broadcast = scale_broadcast.expand_as(x) 176 | shift_broadcast = self.shift.unsqueeze(1).unsqueeze(1).unsqueeze(0) 177 | shift_broadcast = shift_broadcast.expand_as(x) 178 | out = (x - mean) / torch.sqrt(var + self.eps) 179 | out = out * scale_broadcast + shift_broadcast 180 | return out 181 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------