def get_color(self, x, y): line = self.pixels[y] if self.pixelsize == 1: pixel = line[x] if self.palette: return Color.from_pixel(self.palette[pixel]) else: return Color.from_pixel([pixel]) else: start = x * self.pixelsize return Color.from_pixel(line[start:start+self.pixelsize])
def test_resize_bilinear_down_proportional(self): img = image_factory([ [Red, Red, Blue], [Red, Red, Blue], [Blue, Blue, Blue], ]) img = img.resize(2, 2, resample_algorithm=bilinear) self.assertImage(img, [ [Red, Color(64, 0, 191, 255)], [Color(64, 0, 191, 255), Color(16, 0, 239, 255)], ])
def test_resize_bilinear_down_proportional_transparent(self): img = image_factory([ [Red, Red, transparent], [Red, Red, transparent], [transparent, transparent, transparent], ]) img = img.resize(2, 2, resample_algorithm=bilinear) # - the alpha values get blended equally. # - all non-alpha channels get multiplied by their alpha, so the # transparent pixel does not contribute to the result. self.assertImage(img, [ [Red, Color(255, 0, 0, 64)], [Color(255, 0, 0, 64), Color(255, 0, 0, 16)], ])
def get_pixel(pixels, pixelsize, x, y, palette): """ Get the pixel in an image. This returns a list of values, which depend on your mode. """ line = pixels[y] if pixelsize == 1: pixel = line[x] if palette: return Color.from_pixel(palette[pixel]) else: return Color.from_pixel([pixel]) else: start = x * pixelsize return Color.from_pixel(line[start:start+pixelsize])
def _fill_reverse_palette(self): self.reverse_palette = {} if not self.palette: return for index, color in enumerate(self.palette): color_obj = Color.from_pixel(color) color_obj.to_hexcode() self.reverse_palette[color_obj] = index
def test_resize_bilinear_down_simple_completely_transparent(self): img = image_factory([ [transparent, transparent], [transparent, transparent], ]) img = img.resize(1, 1, resample_algorithm=bilinear) # testing this because a naive implementation can cause div/0 error self.assertImage(img, [[Color(0, 0, 0, 0)]])
def test_resize_bilinear_down_simple_transparent(self): img = image_factory([ [Red, Blue], [Blue, transparent], ]) img = img.resize(1, 1, resample_algorithm=bilinear) # - the alpha values get blended equally. # - all non-alpha channels get multiplied by their alpha, so the # transparent pixel does not contribute to the result. self.assertImage(img, [[Color(85, 0, 170, 191)]])
def test_resize_bilinear_down_simple(self): img = image_factory([ [Red, Blue], [Blue, Green], ]) img = img.resize(1, 1, resample_algorithm=bilinear) self.assertImage( img, [ # all the colors blended equally [Color(64, 32, 128, 255)] ])
def test_resize_bilinear_up_proportional(self): img = image_factory([ [Red, Blue], [Blue, Green], ]) img = img.resize(3, 3, resample_algorithm=bilinear) self.assertImage(img, [ [ Color(177, 4, 71, 255), Color(106, 11, 128, 255), Color(0, 21, 212, 255) ], [ Color(106, 11, 128, 255), Color(64, 32, 128, 255), Color(0, 64, 128, 255) ], [ Color(0, 21, 212, 255), Color(0, 64, 128, 255), Color(0, 128, 0, 255) ], ])
def test_from_hexcode(self): c = Color.from_hexcode('feef1510') self.assertEqual(ctuple(c), (254, 239, 21, 16)) c = Color.from_hexcode('123') self.assertEqual(ctuple(c), (17, 34, 51, 255))
# DISCLAIMED. IN NO EVENT SHALL JONAS OBRIST BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from pymaging import Image from pymaging.formats import register from pymaging.colors import Color from pymaging.tests.test_basic import PymagingBaseTestCase from pymaging.utils import get_test_file from pymaging.webcolors import Black, White from pymaging_jpg.jpg import JPG ALMOST_BLACK = Color(8, 8, 8, 255) class JPGTests(PymagingBaseTestCase): def setUp(self): register(JPG) def test_decode(self): img = Image.open_from_path( get_test_file(__file__, 'black-white-100.jpg')) self.assertImage( img, [ [Black, White], [White, ALMOST_BLACK] # no clue why this is "almost" black ],
psd.header.height - (layer.bbox.y1 + start[1]) ) angle = math.atan2(start[1] - end[1], start[0] - end[0]) - 1.570796 offsets.write( " Offset { pos: Vec2::<GLfloat> { x: %i.0, y: %i.0 }, angle: %f },\n" % (abs_pos[0], abs_pos[1], angle) ) if x + psd.header.width > width: y += psd.header.height x = 0 else: x += psd.header.width offsets.write("];\n") else: atlas = Image.new(colors.RGBA, width, height, Color.from_hexcode("#00000000")) metadata_filename = outpath + ".info" metadata = open(metadata_filename, "w") currentframe = None for name, number, index, layer in frames: if name != currentframe: currentframe = name metadata.write("%s frame %i offset = %i\n" % (name, number, index)) atlas.blit(y + layer.bbox.y1, x + layer.bbox.x1, layer.as_pymaging()) if x + psd.header.width > width: y += psd.header.height x = 0
psd.header.height - (layer.bbox.y1 + start[1])) angle = math.atan2(start[1] - end[1], start[0] - end[0]) - 1.570796 offsets.write( " Offset { pos: Vec2::<GLfloat> { x: %i.0, y: %i.0 }, angle: %f },\n" % (abs_pos[0], abs_pos[1], angle)) if x + psd.header.width > width: y += psd.header.height x = 0 else: x += psd.header.width offsets.write("];\n") else: atlas = Image.new(colors.RGBA, width, height, Color.from_hexcode("#00000000")) metadata_filename = outpath + ".info" metadata = open(metadata_filename, "w") currentframe = None for name, number, index, layer in frames: if name != currentframe: currentframe = name metadata.write("%s frame %i offset = %i\n" % (name, number, index)) atlas.blit(y + layer.bbox.y1, x + layer.bbox.x1, layer.as_pymaging()) if x + psd.header.width > width: y += psd.header.height x = 0
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL JONAS OBRIST BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from pymaging.tests.test_basic import PymagingBaseTestCase, image_factory from pymaging.colors import Color from pymaging.webcolors import Red, Green, Blue from pymaging.resample import bilinear transparent = Color(0, 0, 0, 0) class NearestResamplingTests(PymagingBaseTestCase): def test_resize_nearest_down(self): img = image_factory([ [Red, Green, Blue], [Green, Blue, Red], [Blue, Red, Green], ]) img = img.resize(2, 2) self.assertImage(img, [ [Red, Blue], [Blue, Green], ])
def test_color_mix_with(self): base = Red color = Lime.get_for_brightness(0.5) result = base.cover_with(color) self.assertEqual(result, Color(128, 127, 0, 255))
def test_alpha_mixing(self): img = image_factory([[Red]]) semi_transparent_green = Lime.get_for_brightness(0.5) img.draw(Pixel(0, 0), semi_transparent_green) result = img.get_color(0, 0) self.assertEqual(result, Color(128, 127, 0, 255))
def working_cover_with(self, cover_color): try: return old_cover_with(self, cover_color) except ZeroDivisionError: return Color(0, 0, 0, 0)
def get_color(self, x, y): return Color.from_pixel(self.get_pixel(x, y))
def test_from_pixel(self): c = Color.from_pixel([10, 20, 30]) self.assertEqual(ctuple(c), (10, 20, 30, 255)) c = Color.from_pixel([10, 20, 30, 40]) self.assertEqual(ctuple(c), (10, 20, 30, 40))
def test_constructor(self): c = Color(10, 20, 30) self.assertEqual(c.red, 10) self.assertEqual(c.alpha, 255)
# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL JONAS OBRIST BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from pymaging.colors import Color # List of web color names taken from http://en.wikipedia.org/wiki/Web_colors IndianRed = Color(205, 92, 92, 255) LightCoral = Color(240, 128, 128, 255) Salmon = Color(250, 128, 114, 255) DarkSalmon = Color(233, 150, 122, 255) LightSalmon = Color(255, 160, 122, 255) Red = Color(255, 0, 0, 255) Crimson = Color(220, 20, 60, 255) FireBrick = Color(178, 34, 34, 255) DarkRed = Color(139, 0, 0, 255) Pink = Color(255, 192, 203, 255) LightPink = Color(255, 182, 193, 255) HotPink = Color(255, 105, 180, 255) DeepPink = Color(255, 20, 147, 255) MediumVioletRed = Color(199, 21, 133, 255) PaleVioletRed = Color(219, 112, 147, 255) LightSalmon = Color(255, 160, 122, 255)