Skip to content

Instantly share code, notes, and snippets.

@keimina
Created August 23, 2015 17:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save keimina/ede5e708c0832b6486ee to your computer and use it in GitHub Desktop.
Save keimina/ede5e708c0832b6486ee to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#This software is released under the MIT License, see below.
#----------------License----------------
#The MIT License (MIT)
#
#Copyright (c) <2015> <Kei Minagawa>
#
#Permission is hereby granted, free of charge, to any person obtaining a copy
#of this software and associated documentation files (the "Software"), to deal
#in the Software without restriction, including without limitation the rights
#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
#copies of the Software, and to permit persons to whom the Software is
#furnished to do so, subject to the following conditions:
#
#The above copyright notice and this permission notice shall be included in
#all copies or substantial portions of the Software.
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
#THE SOFTWARE.
#----------------What is this?----------------
#Windows bmp file crop function written in pure Python2.7. Extremely simple.
#----------------Note----------------
# 1. This only works for windows bmp file with no compression, no color palet and 32bit RGBA images.
# 2. This only tested on Mac OS X Yosemite.
# 3. Very slow. Not optimised.
#----------------Source code----------------
import struct
from collections import namedtuple
from itertools import islice
from itertools import chain
from math import copysign
Bitmapfileheader = namedtuple("Bitmapfileheader", ["bfType", "bfSize", "bfReserved1", "bfReserved2", "bfOffBits"])
Bitmapinfoheader = namedtuple("Bitmapinfoheader", ["biSize", "biWidth", "biHeight", "biPlanes", "biBitCount", "biCompression", "biSizeImage", "biXPixPerMeter", "biYPixPerMeter", "biClrUsed", "biClrImporant"])
Color = namedtuple("Color", ["B", "G", "R", "A"])
bitmapfileheaderFmt = struct.Struct("<HLHHL")
bitmapinfoheaderFmt = struct.Struct("<LllHHLLllLL")
colorFmt = struct.Struct("<BBBB")
def cropBmp(inFilename, outFilename, x, y, w, h):
#read
inImg = []
with open(inFilename, "rb") as fp:
bitmapfileheader = Bitmapfileheader(*bitmapfileheaderFmt.unpack(fp.read(bitmapfileheaderFmt.size)))
bitmapinfoheader = Bitmapinfoheader(*bitmapinfoheaderFmt.unpack(fp.read(bitmapinfoheaderFmt.size)))
it = iter(lambda: fp.read(colorFmt.size), "")
for i in xrange(abs(bitmapinfoheader.biHeight)):
inImg.append([Color(*colorFmt.unpack(colorChunk)) for colorChunk in islice(it, bitmapinfoheader.biWidth)])
if bitmapinfoheader.biHeight > 0:
inImg.reverse()
#crop
outImg = [row[x:x + w] for row in inImg[y: y + h]]
if bitmapinfoheader.biHeight > 0:
outImg.reverse()
#save
with open(outFilename, "wb") as outFp:
#copy & write header
bitmapinfoheader = bitmapinfoheader._replace(biWidth=w)
bitmapinfoheader = bitmapinfoheader._replace(biHeight=copysign(h, bitmapinfoheader.biHeight))
outFp.write(bitmapfileheaderFmt.pack(*bitmapfileheader.__dict__.values()))
outFp.write(bitmapinfoheaderFmt.pack(*bitmapinfoheader.__dict__.values()))
#write outImg
for color in chain.from_iterable(outImg):
outFp.write(colorFmt.pack(*color.__dict__.values()))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment